pq-key-encoder
Post-quantum key encoding utilities for NIST PQC algorithms. Encode and decode keys as DER, PEM, JWK, SPKI, and PKCS#8.
Audit status: This package has not yet been independently audited. A security audit is pending — see Security policy.
Installation
npm install pq-key-encoder
# Cargo.toml
[dependencies]
pq-key-encoder = "1.0"
Core types
import { type KeyData, type PQJwk } from 'pq-key-encoder';
const publicKey: KeyData = {
alg: 'ML-KEM-768',
type: 'public',
bytes: publicKeyBytes, // Uint8Array from key generation
};
const privateKey: KeyData = {
alg: 'ML-KEM-768',
type: 'private',
bytes: privateKeyBytes,
};
Everything in this package round-trips through KeyData. KeyData is the in-memory representation; DER/PEM/JWK/SPKI/PKCS#8 are the on-disk or on-wire representations.
DER (SPKI / PKCS#8)
import { fromDER, toDER, fromSPKI, toSPKI, fromPKCS8, toPKCS8 } from 'pq-key-encoder';
// Encode (auto-selects SPKI for public, PKCS#8 for private)
const publicDer = toDER(publicKey);
const privateDer = toDER(privateKey);
// Decode (auto-detects key type from the structure)
const parsedPublic = fromDER(publicDer);
const parsedPrivate = fromDER(privateDer);
// Explicit forms
const spki = toSPKI(publicKey);
const pkcs8 = toPKCS8(privateKey);
const back1 = fromSPKI(spki);
const back2 = fromPKCS8(pkcs8);
PEM
import { fromPEM, toPEM } from 'pq-key-encoder';
const publicPem = toPEM(publicKey); // -----BEGIN PUBLIC KEY-----
const privatePem = toPEM(privateKey); // -----BEGIN PRIVATE KEY-----
const back = fromPEM(publicPem);
PEM labels are the standard PUBLIC KEY and PRIVATE KEY (SPKI / PKCS#8 wrapped in base64). The algorithm is embedded in the DER, not the label.
JWK
import { fromJWK, toJWK, type PQJwk } from 'pq-key-encoder';
const jwk: PQJwk = toJWK(publicKey);
// {
// kty: 'PQC',
// alg: 'ML-KEM-768',
// x: '<base64url of public key bytes>'
// }
const back = fromJWK(jwk);
JWK fields follow the conventions used by the broader PQ JOSE work in pq-algorithm-id and pq-jwk (planned).
Rust
use pq_key_encoder::{PublicKey, PrivateKey};
let key = PublicKey::from_spki(&der_bytes)?;
let pem = key.to_pem();
let priv_key = PrivateKey::from_pkcs8(&pkcs8_bytes)?;
let der = priv_key.to_pkcs8();