首先下载扩展类
composer require paragonie/ecc:^2.5
composer require kornrunner/keccak:^1.1
php开启扩展gmp
composer require kornrunner/secp256k1
在写一个地址通用类
<?php
namespace app\common;
use kornrunner\Keccak;
use kornrunner\Serializer\HexPrivateKeySerializer;
use Mdanter\Ecc\EccFactory;
class UsdtAddress
{
public function generateTronAddress()
{
$adapter = EccFactory::getAdapter();
$generator = EccFactory::getSecgCurves()->generator256k1();
privateKey = generator->createPrivateKey();
// 修正:传入 generator 而不是 adapter
serializer = new HexPrivateKeySerializer(generator);
privateKeyHex = serializer->serialize($privateKey);
// Get public key (uncompressed)
publicKey = privateKey->getPublicKey();
x = str_pad(gmp_strval(publicKey->getPoint()->getX(), 16), 64, '0', STR_PAD_LEFT);
y = str_pad(gmp_strval(publicKey->getPoint()->getY(), 16), 64, '0', STR_PAD_LEFT);
pubkeyHex = '04' . x . $y;
// Keccak256 hash, take last 20 bytes
hash = Keccak::hash(substr(hex2bin(pubkeyHex), 1), 256);
addressHex = '41' . substr(hash, -40); // TRON address prefix is 41
// Base58Check encoding
addressBin = hex2bin(addressHex);
checksum = substr(hash('sha256', hash('sha256', addressBin, true), true), 0, 4);
base58Address = this->base58_encode(addressBin . checksum);
return [
'private_key' => $privateKeyHex,
'address' => $base58Address,
];
}
// Base58 encode helper
function base58_encode($input)
{
$alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
base_count = strlen(alphabet);
num = gmp_init(bin2hex(input), 16);
$encoded = '';
while (gmp_cmp($num, 0) > 0) {
list(num, rem) = gmp_div_qr(num, base_count);
encoded = alphabet[gmp_intval(rem)\] . encoded;
}
// Handle leading zeros
foreach (str_split(input) as byte) {
if ($byte === "\x00") {
encoded = alphabet[0] . $encoded;
} else {
break;
}
}
return $encoded;
}
}