generatePrivateKey static method

String generatePrivateKey(
  1. String intPassphrase,
  2. PubKeyModes pubKeyMode
)

Generate a BIP38-encrypted private key from an intermediate passphrase.

This method creates a BIP38-encrypted private key from an intermediate passphrase and the specified public key mode. It follows BIP38 standards for encryption.

  • intPassphrase: The intermediate passphrase.
  • pubKeyMode: The public key mode specifying the address type.
  • Returns: A BIP38-encrypted private key.

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(
        'Invalid intermediate code length (${intPassphraseBytes.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 =
      Secp256k1PublicKeyEcdsa.fromBytes(intPassphraseBytes.sublist(16));

  /// Check if the magic number is valid.
  if (!BytesUtils.bytesEqual(magic, Bip38EcConst.intPassMagicNoLotSeq) &&
      !BytesUtils.bytesEqual(magic, Bip38EcConst.intPassMagicWithLotSeq)) {
    throw ArgumentException(
        'Invalid magic (${BytesUtils.toHexString(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.item1, derivedHalves.item2);
  final flagbyte = _setFlagbyteBits(magic, pubKeyMode);
  final encKeyBytes = List<int>.from([
    ...Bip38EcConst.encKeyPrefix,
    ...flagbyte,
    ...addressHash,
    ...ownerEntropy,
    ...encryptedParts.item1.sublist(0, 8),
    ...encryptedParts.item2
  ]);

  return Base58Encoder.checkEncode(encKeyBytes);
}