decrypt static method
Decrypt a BIP38-encrypted Bitcoin private key without using ECDSA.
This method decrypts a BIP38-encrypted Bitcoin private key without relying on the Elliptic Curve Digital Signature Algorithm (ECDSA). It takes an encrypted private key and a passphrase as inputs and returns the decrypted private key and the selected public key mode (compressed or uncompressed) as a tuple.
privKeyEnc
: The BIP38-encrypted Bitcoin private key.passphrase
: The passphrase for decryption.- Returns: A tuple (pair) containing the decrypted private key as a List
Implementation
static Tuple<List<int>, PubKeyModes> decrypt(
String privKeyEnc, String passphrase) {
final privKeyEncBytes = Base58Decoder.checkDecode(privKeyEnc);
if (privKeyEncBytes.length != Bip38NoEcConst.encKeyByteLen) {
throw ArgumentException(
'Invalid encrypted key length (${privKeyEncBytes.length})');
}
final prefix = privKeyEncBytes.sublist(0, 2);
final flagbyte = List<int>.from([privKeyEncBytes[2]]);
final addressHash = privKeyEncBytes.sublist(3, 7);
final encryptedHalf1 = privKeyEncBytes.sublist(7, 23);
final encryptedHalf2 = privKeyEncBytes.sublist(23);
// Check prefix and flagbyte
if (!BytesUtils.bytesEqual(prefix, Bip38NoEcConst.encKeyPrefix)) {
throw ArgumentException(
'Invalid prefix (${BytesUtils.toHexString(prefix)})');
}
if (flagbyte[0] != Bip38NoEcConst.flagbyteCompressed.first &&
flagbyte[0] != Bip38NoEcConst.flagbyteUncompressed.first) {
throw ArgumentException(
'Invalid flagbyte (${BytesUtils.toHexString(flagbyte)})');
}
// Derive key halves from the passphrase and address hash
final derivedHalves =
Bip38NoEcUtils.deriveKeyHalves(passphrase, addressHash);
final derivedHalf1 = derivedHalves.item1;
final derivedHalf2 = derivedHalves.item2;
// Get the private key back by decrypting
final privKeyBytes = _decryptAndGetPrivKey(
encryptedHalf1, encryptedHalf2, derivedHalf1, derivedHalf2);
// Get public key mode
final pubKeyMode = flagbyte[0] == Bip38NoEcConst.flagbyteCompressed.first
? PubKeyModes.compressed
: PubKeyModes.uncompressed;
// Verify the address hash
final addressHashGot = Bip38NoEcUtils.addressHash(privKeyBytes, pubKeyMode);
if (!BytesUtils.bytesEqual(addressHash, addressHashGot)) {
throw ArgumentException(
'Invalid address hash (expected: ${BytesUtils.toHexString(addressHash)}, '
'got: ${BytesUtils.toHexString(addressHashGot)})');
}
return Tuple(privKeyBytes, pubKeyMode);
}