generateSpendKey method

Uint8List generateSpendKey()

Derive the 32-byte private spend seed for Monero.

The returned bytes are the raw PBKDF2-HMAC-SHA256 output (10 000 iterations, coin-domain-separated salt). Pass them to MoneroKeys.fromSeed, which performs the required Ed25519 scalar reduction (mod l) before use as a private spend key.

Throws StateError if isEncrypted is true - decrypt the seed with the correct passphrase before calling this method.

Implementation

Uint8List generateSpendKey() {
  if (isEncrypted) {
    throw StateError(
      'Cannot derive a spend key from an encrypted polyseed. '
      'Decrypt the seed with the correct passphrase first.',
    );
  }

  // Salt layout (32 bytes, all fields little-endian):
  //  [0..11]  "POLYSEED key" (UTF-8, 12 bytes)
  //  [12]      0x00 (separator, never written)
  //  [13..15]  0xff 0xff 0xff
  //  [16..19]  coin index (uint32 LE)  -  Monero = 0
  //  [20..23]  encoded birthday (uint32 LE)
  //  [24..27]  features (uint32 LE)
  //  [28..31]  0x00 0x00 0x00 0x00
  final salt = Uint8List(32); // zero-initialised
  const label = 'POLYSEED key'; // 12 chars -> bytes 0-11
  salt.setRange(0, label.length, utf8.encode(label));
  // byte 12 stays 0x00
  salt[13] = 0xff;
  salt[14] = 0xff;
  salt[15] = 0xff;
  _store32(salt, 16, _moneroIndex);
  _store32(salt, 20, _data.birthday);
  _store32(salt, 24, _data.features);
  // bytes 28-31 stay 0x00

  return _pbkdf2HmacSha256(
    password: _data.secret,
    salt: salt,
    iterations: 10000,
    keyLength: 32,
  );
}