decrypt static method

(List<int>, PubKeyModes) decrypt(
  1. String privKeyEnc,
  2. String passphrase
)

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);
}