generatePrivateKey static method
Generate a BIP38-encrypted private key from an intermediate passphrase.
intPassphrase: The intermediate passphrase.pubKeyMode: The public key mode specifying the address type.
Implementation
static String generatePrivateKey(
String intPassphrase,
PubKeyModes pubKeyMode,
) {
/// Decode the intermediate passphrase into bytes.
final intPassphraseBytes = Base58Decoder.checkDecode(intPassphrase);
/// Ensure the length of the intermediate code is valid.
if (intPassphraseBytes.length != Bip38EcConst.intPassEncByteLen) {
throw ArgumentException.invalidOperationArguments(
"generatePrivateKey",
name: "intPassphrase",
reason: "Invalid intermediate code length",
);
}
/// Extract magic, owner entropy, and passpoint from the intermediate code.
final magic = intPassphraseBytes.sublist(0, 8);
final ownerEntropy = intPassphraseBytes.sublist(8, 16);
final passpoint = Secp256k1PublicKey.fromBytes(
intPassphraseBytes.sublist(16),
);
/// Check if the magic number is valid.
if (!BytesUtils.bytesEqual(magic, Bip38EcConst.intPassMagicNoLotSeq) &&
!BytesUtils.bytesEqual(magic, Bip38EcConst.intPassMagicWithLotSeq)) {
throw ArgumentException.invalidOperationArguments(
"generatePrivateKey",
name: "intPassphrase",
reason: "Invalid magic",
);
}
/// Generate a random seed for seedb and derive a new point.
final seedb = QuickCrypto.generateRandom(Bip38EcConst.seedBByteLen);
final factorb = QuickCrypto.sha256DoubleHash(seedb);
final newPoint = passpoint.point * BigintUtils.fromBytes(factorb);
/// Calculate the address hash.
final addressHash = Bip38Addr.addressHash(newPoint.toBytes(), pubKeyMode);
/// Derive key halves using Scrypt.
final derivedHalves = Bip38EcUtils.deriveKeyHalves(
passpoint.compressed,
addressHash,
ownerEntropy,
);
/// Encrypt seedb and create the BIP38-encrypted private key.
final encryptedParts = _encryptSeedb(
seedb,
derivedHalves.$1,
derivedHalves.$2,
);
final flagbyte = _setFlagbyteBits(magic, pubKeyMode);
final encKeyBytes = [
...Bip38EcConst.encKeyPrefix,
...flagbyte,
...addressHash,
...ownerEntropy,
...encryptedParts.$1.sublist(0, 8),
...encryptedParts.$2,
];
return Base58Encoder.checkEncode(encKeyBytes);
}