Skip to main content

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();