Post-Quantum Cryptography
Shamwari is built PQC-native from day one. Post-quantum cryptographic operations are integrated directly into key generation, account addressing, transaction signing, block forging, and encrypted messaging via the nxt.crypto package.
Key Primitives Summary
| Primitive | Standard | Function | Public Key Size | Secret Key Size | Output / Sig Size |
|---|---|---|---|---|---|
| ML-KEM-512 | NIST FIPS 203 | Key Encapsulation (KEM) | 800 bytes | 1632 bytes | 768 bytes (Ciphertext) |
| ML-DSA-2 | NIST FIPS 204 | Digital Signatures | 1312 bytes | 2528 bytes | 2420 bytes (Signature) |
ShamwariQKP | Composite | Hybrid QKP Container | 2112 bytes | 4160 bytes | N/A |
Key Generation & PBKDF2 Key Derivation
Key pair generation derives deterministic master seeds from user passphrases using PBKDF2-HMAC-SHA512 (100,000 iterations) paired with SHA3-256 domain separation:
// Derive composite ShamwariQKP from secret phrase
String secretPhrase = "your secret high-entropy passphrase";
ShamwariQKP keyPair = Crypto.getShamwariQKP(secretPhrase);
ShamwariPublicKey publicKey = keyPair.getPublicKey();
ShamwariPrivateKey privateKey = keyPair.getPrivateKey();
Domain Separation Mechanism
Under the hood, Crypto.generateShamwariQKP(byte[] seed) splits the derived 32-byte seed into distinct domain-separated inputs:
0x01 || seedhashed with SHA3-256 produceskyberSeed.0x02 || seedhashed with SHA3-256 producesdilithiumSeed.
Digital Signatures (ML-DSA-2 / Dilithium Level 2)
All protocol transactions, block headers, digital certificates, and administrative actions are authenticated using ML-DSA-2 signatures via nxt.crypto.Crypto.
// Transaction signing
byte[] transactionBytes = "Transaction Payload".getBytes(StandardCharsets.UTF_8);
byte[] signature = Crypto.sign(transactionBytes, privateKey.getDilithiumPrivateKey()); // 2420 bytes
// Signature verification
boolean isValid = Crypto.verify(signature, transactionBytes, publicKey.getDilithiumPublicKey());
Signing Security
ML-DSA uses rejection sampling during signature generation to guarantee that signature instances leak zero information regarding the signer's secret key.
Key Encapsulation & Authenticated Payload Encryption
For confidential payloads and encrypted messaging, Shamwari pairs ML-KEM-512 key encapsulation with AES-256-GCM symmetric encryption using nxt.crypto.EncryptedData. HKDF-SHA256 derives the 32-byte AES key bound to the Kyber ciphertext bytes as salt:
// Encrypt plaintext payload for recipient
byte[] plaintext = "Confidential Payload Data".getBytes(StandardCharsets.UTF_8);
EncryptedData encryptedData = EncryptedData.encrypt(
plaintext,
senderPrivateKey.getKyberPrivateKey(),
recipientPublicKey.getKyberPublicKey()
);
// Decrypt payload as recipient
byte[] decryptedBytes = encryptedData.decrypt(
recipientPrivateKey.getKyberPrivateKey(),
senderPublicKey.getKyberPublicKey()
);
Encrypted Payload Wire Format
The serialized representation of an EncryptedData object combines the AES-GCM ciphertext and 768-byte Kyber ciphertext:
┌────────────────────────────────────────────────────── ────────┐
│ AES-256-GCM Payload │
│ [ 12 B Nonce | Ciphertext | 16 B GCM Tag ] │
├──────────────────────────────────────────────────────────────┤
│ Kyber-512 Ciphertext │
│ [ 768 Bytes ] │
└──────────────────────────────────────────────────────────────┘
Security Controls & ShamwariQKP Memory Protection
To prevent inadvertent leakage of private key material in application logs or network traffic, ShamwariQKP enforces strict access separation and memory sanitation:
- Public-Only Default JSON:
ShamwariQKP.getJSON()andgetPublicJSON()return public key material only. Private keys require an explicit, opt-in call togetPrivateJSON(). - In-Memory Sanitization: Calling
qkp.destroy()orprivateKey.destroy()zeroize secret key byte arrays in memory (Arrays.fill(arr, (byte) 0)). - Side-Channel Mitigation: Key equality evaluations use constant-time byte comparisons (
constantTimeCompare) to eliminate timing side-channels.
// Export public JSON (safe for logging, caching, API responses)
JSONObject publicJson = keyPair.getJSON();
// Opt-in export containing private key (for encrypted wallet backup)
JSONObject privateJson = keyPair.getPrivateJSON();
// Wipe secret key material from memory when finished
keyPair.destroy();
Account Identity & Serialized Key Encodings
Accounts in Shamwari derive their identity directly from a composite ShamwariPublicKey:
- Master Seed Derivation: PBKDF2-HMAC-SHA512 derives a high-entropy seed from the passphrase.
- Domain Separation: SHA3-256 generates independent seeds for ML-KEM-512 and ML-DSA-2.
- ASN.1 / DER Encodings:
- Public keys use ASN.1 X.509
SubjectPublicKeyInfoformat. - Private keys use ASN.1 PKCS#8
PrivateKeyInfoformat.
- Public keys use ASN.1 X.509
- Account ID Conversion: The account numeric ID is derived from the SHA-256 digest of the ASN.1/DER encoded
ShamwariPublicKey.
Protocol-Enforced Account Controls & AI Agents
To support automated finance and autonomous AI software agents, Shamwari introduces AutonomousAccountControl:
- AI Agent Accounts (
AUTONOMOUS): Software-driven accounts operating under hard operational limits established on-chain by a controlling human account. - Protocol Limits: Enforces per-transaction caps, daily transfer caps, transaction-type restrictions, and counterparty account whitelists.
- Security Guarantee: Controlled accounts cannot alter or remove their own operational limits; modifications require an explicit
SET_AUTONOMOUS_ACCOUNT_CONTROLtransaction signed by the controlling account'sML-DSA-2key.