deriveKeys

Derives shielded public keys from a 32-byte seed using Midnight's algorithm.

Algorithm:

  1. Coin secret key: Blake2b("midnight:csk" || seed)

  2. Coin public key: Blake2b("midnight:zswap-pk[v1]" || coin_secret_key)

  3. Encryption keys: JubJub elliptic curve operations (twisted Edwards on BLS12-381)

Input: The seed should be derived from BIP-32 at path m/44'/2400'/account'/3/index:

  • Derive using HDWallet with role MidnightKeyRole.ZSWAP

  • Extract the 32-byte private key

  • Pass it to this function

Output: Two 32-byte public keys encoded as 64-character hex strings:

  • Coin public key (CPK) - Used in zero-knowledge circuits

  • Encryption public key (EPK) - Used for encrypting transaction data

Security:

  • This function does NOT clear the seed - caller must wipe it

  • Public keys are safe to share/store - they're public information

  • The seed MUST be kept secret - it's equivalent to a private key

Performance:

  • FFI overhead: < 1ms

  • Rust crypto: < 1ms (Blake2b + JubJub)

  • Total: < 2ms per derivation

Compatibility: The output matches Midnight SDK (key derivation version-abstract via Rust FFI):

const zswapKeys = ZswapSecretKeys.fromSeed(seed);
const coinPk = zswapKeys.coinPublicKey; // Matches our coinPublicKey
const encPk = zswapKeys.encPublicKey; // Matches our encryptionPublicKey

Error Handling: Returns null if:

  • Native library not loaded

  • Native function returns null (internal error)

  • Returned keys fail validation (invalid hex format)

Throws IllegalArgumentException if seed is not exactly 32 bytes.

Check stderr/Logcat for detailed error messages from the native library.

Return

ShieldedKeys containing both public keys, or null on error

Parameters

seed

32-byte seed derived from BIP-32 at m/44'/2400'/account'/3/index

Throws

if seed is not 32 bytes