decrypt static method
Decrypt a BIP38-encrypted private key with a passphrase.
This method decrypts a BIP38-encrypted private key using the provided passphrase. It returns the decrypted private key as bytes and identifies the associated public key mode (compressed or uncompressed).
privKeyEnc
: The BIP38-encrypted private key to be decrypted.passphrase
: The passphrase used for decryption.- Returns: A tuple (pair) containing the decrypted private key bytes and the associated public key mode.
Implementation
static Tuple<List<int>, PubKeyModes> decrypt(
String privKeyEnc, String passphrase) {
final privKeyEncBytes = Base58Decoder.checkDecode(privKeyEnc);
/// Check if the length of the encrypted private key is valid.
if (privKeyEncBytes.length != Bip38EcConst.encByteLen) {
throw ArgumentException(
'Invalid encrypted length (${privKeyEncBytes.length})');
}
/// Extract various components from the encrypted private key.
final prefix = privKeyEncBytes.sublist(0, 2);
final flagbyte = List<int>.from([privKeyEncBytes[2]]);
final addressHash = privKeyEncBytes.sublist(3, 7);
final ownerEntropy = privKeyEncBytes.sublist(7, 15);
final encryptedPart1Lower = privKeyEncBytes.sublist(15, 23);
final encryptedPart2 = privKeyEncBytes.sublist(23);
/// Verify the prefix of the encrypted private key.
if (!BytesUtils.bytesEqual(prefix, Bip38EcConst.encKeyPrefix)) {
throw ArgumentException(
'Invalid prefix (${BytesUtils.toHexString(prefix)})');
}
/// Extract flag options based on the flag byte.
final flagOptions = _getFlagbyteOptions(flagbyte);
/// Derive the pass factor and key halves for decryption.
final passfactor =
Bip38EcUtils.passFactor(passphrase, ownerEntropy, flagOptions.item2);
final derivedHalves = Bip38EcUtils.deriveKeyHalves(
Bip38EcUtils.passPoint(passfactor), addressHash, ownerEntropy);
/// Decrypt 'factorb' and compute the private key.
final factorb = _decryptAndGetFactorb(encryptedPart1Lower, encryptedPart2,
derivedHalves.item1, derivedHalves.item2);
final privateKeyBytes = _computePrivateKey(passfactor, factorb);
/// Create a public key from the private key and calculate address hash.
final toPub = Secp256k1PrivateKeyEcdsa.fromBytes(privateKeyBytes);
final addressHashGot = Bip38Addr.addressHash(
toPub.publicKey.point.toBytes(), flagOptions.item1);
/// Verify the extracted address hash matches the expected value.
if (!BytesUtils.bytesEqual(addressHash, addressHashGot)) {
throw ArgumentException(
'Invalid address hash (expected: ${BytesUtils.toHexString(addressHash)}, got: ${BytesUtils.toHexString(addressHashGot)})');
}
return Tuple(privateKeyBytes, flagOptions.item1);
}