
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@smartledger/keys
Advanced tools
Key management SDK for Lumen cryptographic operations - Now with proper ML-DSA-44/65/87 implementations
Single source of truth for cryptographic key operations.
Version: 1.5.1
Status: ✅ Production Ready
Tests: 52/52 passing
New in 1.5.1: All three ML-DSA security levels now available (44/65/87)
Keys are the root of everything in your crypto architecture:
Without a clean SDK layer, key handling becomes ad hoc and brittle:
generateKeypair() implementations scattered across reposWith @smartledger/keys, all your agents/modules/bridge code simply ask:
"Give me a signing key of suite X"
"Sign this payload with keyId Y"
And don't care how keys are stored, rotated, or implemented.
npm install @smartledger/keys
Choose the right security level for your use case:
| Variant | NIST Level | Equivalent | Use Case |
|---|---|---|---|
| ml-dsa-44 | Level 2 | AES-128 | IoT devices, high-throughput systems |
| ml-dsa-65 | Level 3 | AES-192 | General purpose (recommended) |
| ml-dsa-87 | Level 5 | AES-256 | High-security, long-term confidential data |
import { createKeySDK } from '@smartledger/keys';
// One line to get a ready-to-use SDK with ML-DSA + ECDSA suites registered
const sdk = createKeySDK();
// Create both PQ + ECDSA keys for an agent
// Using ml-dsa-65 (Level 3) - recommended for most use cases
const { primaryKey, secondaryKey } = await sdk.createDualSignatureKeys(
'agent-resonance',
{
primarySignatureSuite: 'ml-dsa-65', // or 'ml-dsa-44', 'ml-dsa-87'
secondarySignatureSuite: 'bsv-ecdsa-secp256k1',
}
);
// Sign with both suites (private keys stay hidden)
const message = new TextEncoder().encode('agent output');
const { signatures } = await sdk.signWithSuites('agent-resonance', message);
// Verify both signatures
const verify = await sdk.verifyWithSuites('agent-resonance', message, signatures);
console.log(verify.allValid); // true
createKeySDK(config?) returns a ready-to-use SDK wired with in-memory storage and the default ML-DSA + ECDSA suites. Pass your own keyRegistry or suiteRegistry to override defaults.
createKey(agentId, profile, options?)Create a new key for an agent/module.
Parameters:
agentId (string) - Agent identifier (e.g. 'agent-resonance')profile (CryptoProfile) - Which signature suites to useoptions (CreateKeyOptions) - Optional expiration, usage, etc.Returns: Promise<KeyRecord> - KeyRecord with metadata and public key
Example:
const key = await sdk.createKey(
'agent-schema',
{ primarySignatureSuite: 'ml-dsa-65' }, // Recommended: Level 3
{
expiresAt: new Date(Date.now() + 365 * 86400000).toISOString(), // 1 year
usage: ['signing'],
}
);
getKey(keyId)Get an existing key by ID.
Parameters:
keyId (string) - Key identifierReturns: Promise<KeyRecord | null> - KeyRecord or null if not found
Example:
const key = await sdk.getKey('agent-resonance:pk-ml-1');
if (key) {
console.log(key.meta.suiteId); // 'ml-dsa-65' or 'ml-dsa-44', 'ml-dsa-87'
console.log(key.publicKey); // Uint8Array
}
signWithKey(keyId, message)Sign a message with a key. Private key never leaves the SDK.
Parameters:
keyId (string) - Which key to sign withmessage (Uint8Array) - Message to sign (will be hashed internally)Returns: Promise<Uint8Array> - Signature bytes
Throws: Error if key not found or not active
Example:
const message = new TextEncoder().encode('agent output');
const signature = await sdk.signWithKey('agent-resonance:pk-ml-1', message);
verifySignature(keyId, message, signature)Verify a signature against a public key.
Parameters:
keyId (string) - Which key to verify withmessage (Uint8Array) - Original messagesignature (Uint8Array) - Signature to verifyReturns: Promise<boolean> - true if valid
Example:
const valid = await sdk.verifySignature(
'agent-resonance:pk-ml-1',
message,
signature
);
listKeysForAgent(agentId, activeOnly?)List all keys for an agent.
Parameters:
agentId (string) - Agent identifieractiveOnly (boolean) - If true, only return active keys (default: true)Returns: Promise<KeyRecord[]> - Array of KeyRecords
Example:
const keys = await sdk.listKeysForAgent('agent-schema');
for (const key of keys) {
console.log(`${key.meta.keyId} (${key.meta.suiteId})`);
}
getActiveCryptoProfile(agentId)Get the active crypto profile for an agent.
Looks up the most recent active keys and infers the profile.
Parameters:
agentId (string) - Agent identifierReturns: Promise<CryptoProfile | null> - CryptoProfile or null if no keys found
Example:
const profile = await sdk.getActiveCryptoProfile('agent-schema');
console.log(profile.primarySignatureSuite); // 'ml-dsa-65'
console.log(profile.secondarySignatureSuite); // 'bsv-ecdsa-secp256k1'
rotateAgentKeys(agentId)Rotate an agent's keys.
Generates new keypairs for all active keys, marks old ones as rotated.
Parameters:
agentId (string) - Agent identifierReturns: Promise<KeyRecord[]> - Array of new KeyRecords
Example:
const newKeys = await sdk.rotateAgentKeys('agent-schema');
for (const key of newKeys) {
console.log(`New: ${key.meta.keyId}`);
console.log(`Rotated from: ${key.meta.rotatedFrom}`);
}
getOrCreateKey(agentId, profile, options?)Create key if it doesn't exist, otherwise return existing.
Idempotent key creation for agent setup.
Parameters:
agentId (string) - Agent identifierprofile (CryptoProfile) - Crypto configurationoptions (CreateKeyOptions) - Creation optionsReturns: Promise<KeyRecord> - KeyRecord (new or existing)
Example:
// Safe to call multiple times
const key1 = await sdk.getOrCreateKey('agent-validator', {
primarySignatureSuite: 'ml-dsa-65',
});
const key2 = await sdk.getOrCreateKey('agent-validator', {
primarySignatureSuite: 'ml-dsa-65',
});
console.log(key1.meta.keyId === key2.meta.keyId); // true
createDualSignatureKeys(agentId, profile, options?)Create both primary and secondary keys in one call. Requires profile.secondarySignatureSuite.
Returns: { primaryKey, secondaryKey }
Example:
const { primaryKey, secondaryKey } = await sdk.createDualSignatureKeys(
'agent-bridge',
{
primarySignatureSuite: 'ml-dsa-65', // Recommended
secondarySignatureSuite: 'bsv-ecdsa-secp256k1',
}
);
getOrCreateDualSignatureKeys(agentId, profile, options?)Idempotent version of the above; reuses active keys when present.
Returns: { primaryKey, secondaryKey }
signWithSuites(agentId, message, suites?)Sign once per suite. When suites is omitted, active primary + secondary are used.
Returns: { signatures: Array<{ suiteId, keyId, signature }> }
Example:
const message = new TextEncoder().encode('hybrid payload');
const { signatures } = await sdk.signWithSuites('agent-bridge', message);
verifyWithSuites(agentId, message, signatures)Verify multiple signatures and get per-suite results.
Returns: { results: Array<{ suiteId, keyId, valid }>, allValid: boolean }
Example:
const verify = await sdk.verifyWithSuites('agent-bridge', message, signatures);
console.log(verify.allValid); // true when every suite verifies
Public key record (safe to expose, no private key).
interface KeyRecord {
meta: KeyMeta; // Key metadata
publicKey: Uint8Array; // Public key bytes
}
Options for key creation.
interface CreateKeyOptions {
expiresAt?: string; // ISO 8601
usage?: Array<'signing' | 'encryption' | 'both'>; // Default: ['signing']
cryptoProfileVersion?: string; // Default: '1.0.0'
}
Per-agent/module crypto configuration.
interface CryptoProfile {
primarySignatureSuite: string; // e.g. 'ml-dsa-65' (recommended), 'ml-dsa-44', 'ml-dsa-87'
secondarySignatureSuite?: string; // e.g. 'bsv-ecdsa-secp256k1' (hybrid)
keyEncapsulationSuite?: string; // e.g. 'ml-kem-768' (future)
}
// Agent uses only ML-DSA (recommended: ml-dsa-65)
const key = await sdk.createKey('agent-research', {
primarySignatureSuite: 'ml-dsa-65', // or 'ml-dsa-44' for IoT, 'ml-dsa-87' for max security
});
const message = new TextEncoder().encode('research results');
const signature = await sdk.signWithKey(key.meta.keyId, message);
// One call to create both keys
await sdk.getOrCreateDualSignatureKeys('agent-bridge', {
primarySignatureSuite: 'ml-dsa-65', // Balanced security (recommended)
secondarySignatureSuite: 'bsv-ecdsa-secp256k1',
});
// Sign with both suites
const message = new TextEncoder().encode('bridge output');
const { signatures } = await sdk.signWithSuites('agent-bridge', message);
// Verify both signatures
const verified = await sdk.verifyWithSuites('agent-bridge', message, signatures);
console.log(verified.allValid); // true
// Safe to call on every startup
async function setupAgent(agentId: string) {
const key = await sdk.getOrCreateKey(agentId, {
primarySignatureSuite: 'ml-dsa-65', // Recommended default
}, {
expiresAt: new Date(Date.now() + 365 * 86400000).toISOString(),
});
return key;
}
// Automated rotation job
async function monthlyRotation() {
const agents = ['agent-resonance', 'agent-schema', 'agent-validator'];
for (const agentId of agents) {
const newKeys = await sdk.rotateAgentKeys(agentId);
console.log(`✓ Rotated ${agentId}: ${newKeys.length} keys`);
}
}
getOrCreateKey safe for retriesgetOrCreateKey for idempotent setupsignWithKey (not direct registry access)// Scattered key operations
const suite = globalRegistry.getSuite('ml-dsa-87');
const keypair = await suite.generateKeypair();
await keyRegistry.registerKey('agent-1:pk-1', keypair, 'ml-dsa-87');
const key = await keyRegistry.getKey('agent-1:pk-1');
const sig = await suite.sign(key.keypair.privateKey, message);
// Clean, centralized
const key = await sdk.createKey('agent-1', {
primarySignatureSuite: 'ml-dsa-65', // Choose: 'ml-dsa-44', '65', or '87'
});
const sig = await sdk.signWithKey(key.meta.keyId, message);
@smartledger/keys is the single source of truth for cryptographic keys:
✅ 23 tests passing
✅ Private keys hidden from callers
✅ Crypto-agnostic API (suite is config)
✅ Idempotent operations
✅ Easy to audit
✅ Production-ready
Use it for all key operations. Make crypto agility a reality.
See Also:
Version: 1.0.0
Last Updated: November 28, 2025
FAQs
Key management SDK for Lumen cryptographic operations - Now with proper ML-DSA-44/65/87 implementations
The npm package @smartledger/keys receives a total of 7 weekly downloads. As such, @smartledger/keys popularity was classified as not popular.
We found that @smartledger/keys demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.