decrypt static method
Decrypt a BIP38-encrypted private key with a passphrase.
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 (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.invalidOperationArguments(
"decrypt",
name: "privKeyEnc",
reason: "Invalid encrypted private key length.",
);
}
/// Extract various components from the encrypted private key.
final prefix = privKeyEncBytes.sublist(0, 2);
final flagbyte = [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.invalidOperationArguments(
"decrypt",
name: "privKeyEnc",
reason: "Invalid 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.$2,
);
final derivedHalves = Bip38EcUtils.deriveKeyHalves(
Bip38EcUtils.passPoint(passfactor),
addressHash,
ownerEntropy,
);
/// Decrypt 'factorb' and compute the private key.
final factorb = _decryptAndGetFactorb(
encryptedPart1Lower,
encryptedPart2,
derivedHalves.$1,
derivedHalves.$2,
);
final privateKeyBytes = _computePrivateKey(passfactor, factorb);
/// Create a public key from the private key and calculate address hash.
final toPub = Secp256k1PrivateKey.fromBytes(privateKeyBytes);
final addressHashGot = Bip38Addr.addressHash(
toPub.publicKey.point.toBytes(),
flagOptions.$1,
);
/// Verify the extracted address hash matches the expected value.
if (!BytesUtils.bytesEqual(addressHash, addressHashGot)) {
throw ArgumentException.invalidOperationArguments(
"decrypt",
name: "privKeyEnc",
reason: "Invalid address hash.",
);
}
return (privateKeyBytes, flagOptions.$1);
}