
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@smartledger/crypto
Advanced tools
Pluggable cryptographic signature suite abstraction for Lumen agents - Now with proper ML-DSA-44/65/87 implementations
Production-ready cryptographic abstractions for post-quantum cryptography.
Version: 1.0.0
Status: ✅ Production Ready
Tests: 68/68 passing
@smartledger/crypto provides a unified interface for classical and post-quantum cryptographic algorithms. Built on industry-standard implementations:
This is the low-level foundation for the SmartLedger key management SDK.
npm install @smartledger/crypto
❌ Without unified abstractions:
✅ With @smartledger/crypto:
SignatureSuite interface for all algorithmsimport {
BsvEcdsaSuite,
MlDsa87Suite,
SuiteRegistry,
} from '@smartledger/crypto';
// Setup registry
const registry = new SuiteRegistry();
registry.register(new BsvEcdsaSuite());
registry.register(new MlDsa87Suite());
// Generate ML-DSA keypair
const mlDsaSuite = registry.getSuite('ml-dsa-87');
const mlKeypair = await mlDsaSuite.generateKeypair();
// Sign
const message = new TextEncoder().encode('hello quantum world');
const signature = await mlDsaSuite.sign(mlKeypair.privateKey, message);
// Verify
const valid = await mlDsaSuite.verify(mlKeypair.publicKey, message, signature);
console.log(valid); // true
All signature algorithms implement this interface:
interface SignatureSuite {
suiteId: string;
generateKeypair(): Promise<KeypairResult>;
sign(privateKey: Uint8Array, message: Uint8Array): Promise<Uint8Array>;
verify(publicKey: Uint8Array, message: Uint8Array, signature: Uint8Array): Promise<boolean>;
formatPublicKey?(publicKey: Uint8Array): string;
formatPrivateKey?(privateKey: Uint8Array): string;
formatSignature?(signature: Uint8Array): string;
}
Runtime suite selection without tight coupling:
const registry = new SuiteRegistry();
registry.register(new BsvEcdsaSuite());
registry.register(new MlDsa87Suite());
// Get suite by ID
const suite = registry.getSuite('ml-dsa-87');
// List available suites
const suiteIds = registry.listSuites(); // ['bsv-ecdsa-secp256k1', 'ml-dsa-87']
Low-level key registry for storing keypairs:
import { KeyRegistry, InMemoryKeyStorage } from '@smartledger/crypto';
const keyRegistry = new KeyRegistry(new InMemoryKeyStorage());
// Register a key
await keyRegistry.registerKey('my-key-id', keypair, 'ml-dsa-87');
// Retrieve
const stored = await keyRegistry.getKey('my-key-id');
console.log(stored.meta.suiteId); // 'ml-dsa-87'
console.log(stored.keypair.publicKey); // Uint8Array
bsv-ecdsa-secp256k1)Classical ECDSA using secp256k1 curve (Bitcoin/BSV compatible).
const suite = new BsvEcdsaSuite();
const keypair = await suite.generateKeypair();
// keypair.publicKey: 33 bytes
// keypair.privateKey: 32 bytes
const sig = await suite.sign(keypair.privateKey, message);
// sig: 64 bytes
⚠️ IMPORTANT: All ML-DSA suites currently use the ML-DSA-87 implementation.
ml-dsa-87) ✅ Correct ImplementationPost-quantum ML-DSA (FIPS 204, security level 5).
const suite = new MlDsa87Suite();
const keypair = await suite.generateKeypair();
// keypair.publicKey: 2592 bytes
// keypair.privateKey: 4864 bytes
const sig = await suite.sign(keypair.privateKey, message);
// sig: ~4597 bytes
ml-dsa-65) ⚠️ Uses ML-DSA-87Intended: NIST Level 3 (AES-192 equivalent)
Actual: Uses ML-DSA-87 implementation (Level 5)
const suite = new MlDsa65Suite();
// Currently produces ML-DSA-87 sized keys/signatures
// See ML-DSA_IMPLEMENTATION_STATUS.md for details
ml-dsa-44) ⚠️ Uses ML-DSA-87Intended: NIST Level 2 (AES-128 equivalent)
Actual: Uses ML-DSA-87 implementation (Level 5)
const suite = new MlDsa44Suite();
// Currently produces ML-DSA-87 sized keys/signatures
// See ML-DSA_IMPLEMENTATION_STATUS.md for details
Recommendation: Use MlDsa87Suite directly until v2.0.0 implements true ML-DSA-44/65 support.
For complete details, see ML-DSA_IMPLEMENTATION_STATUS.md.
register(suite: SignatureSuite): voidRegister a signature suite.
registry.register(new MlDsa87Suite());
getSuite(suiteId: string): SignatureSuiteGet a registered suite by ID.
const suite = registry.getSuite('ml-dsa-87');
listSuites(): string[]List all registered suite IDs.
const ids = registry.listSuites(); // ['bsv-ecdsa-secp256k1', 'ml-dsa-87']
registerKey(keyId: string, keypair: KeypairResult, suiteId: string, meta?: Partial<KeyMeta>): Promise<void>Store a keypair.
await keyRegistry.registerKey('agent-1:pk-1', keypair, 'ml-dsa-87', {
agentId: 'agent-1',
status: 'active',
});
getKey(keyId: string): Promise<StoredKey | null>Retrieve a stored keypair.
const stored = await keyRegistry.getKey('agent-1:pk-1');
if (stored) {
console.log(stored.meta.suiteId);
console.log(stored.keypair.publicKey);
}
listKeys(agentId?: string): Promise<KeyMeta[]>List all keys, optionally filtered by agent.
const allKeys = await keyRegistry.listKeys();
const agentKeys = await keyRegistry.listKeys('agent-1');
deleteKey(keyId: string): Promise<void>Remove a key from storage.
await keyRegistry.deleteKey('agent-1:pk-1');
Default in-memory storage (resets on restart).
const storage = new InMemoryKeyStorage();
const registry = new KeyRegistry(storage);
Implement KeyStorage interface for persistent storage:
interface KeyStorage {
get(keyId: string): Promise<StoredKey | null>;
set(keyId: string, key: StoredKey): Promise<void>;
delete(keyId: string): Promise<void>;
list(agentId?: string): Promise<KeyMeta[]>;
}
Example: File-based storage
class FileKeyStorage implements KeyStorage {
async get(keyId: string) { /* read from file */ }
async set(keyId: string, key: StoredKey) { /* write to file */ }
// ...
}
const registry = new KeyRegistry(new FileKeyStorage());
npm test
Coverage:
@smartledger/keys SDK)This package is the foundation layer. Most users should use the higher-level SDK:
npm install @smartledger/keys
The @smartledger/keys SDK provides:
See @smartledger/keys documentation for full SDK usage.
Full browser support via ESM bundle (161.6 KB gzipped):
<script type="module">
import { BsvEcdsaSuite, MlDsa87Suite } from '@smartledger/keys/browser';
const suite = new MlDsa87Suite();
const keypair = await suite.generateKeypair();
</script>
Browser bundle includes WASM for ML-DSA.
@noble/secp256k1@2.2.0 - ECDSA implementationtypescript@5.3.3vitest@1.0.4Total size: ~46 KB (without WASM, ~200 KB with ML-DSA WASM)
@smartledger/crypto provides the cryptographic foundation:
✅ 68 tests passing
✅ Unified interface (ECDSA + ML-DSA)
✅ Registry pattern (crypto agility)
✅ Audited implementations
✅ Production-ready
Use @smartledger/keys SDK for high-level key management.
Version: 1.0.0
License: MIT
Last Updated: November 28, 2025
FAQs
Pluggable cryptographic signature suite abstraction for Lumen agents - Now with proper ML-DSA-44/65/87 implementations
We found that @smartledger/crypto 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.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.