Low level bindings for libsodium cryptographic library
—
Ed25519 digital signatures for message authentication, integrity verification, and non-repudiation.
Generates a random Ed25519 key pair for digital signatures.
/**
* Generate random Ed25519 signing key pair
* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)
* @param sk - Output buffer for secret key (must be SECRETKEYBYTES long)
* @throws Error if buffer sizes are incorrect or generation fails
*/
function crypto_sign_keypair(pk: Buffer, sk: Buffer): void;Generates a deterministic Ed25519 key pair from a seed.
/**
* Generate Ed25519 key pair from seed
* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)
* @param sk - Output buffer for secret key (must be SECRETKEYBYTES long)
* @param seed - Seed buffer (must be SEEDBYTES long)
* @throws Error if buffer sizes are incorrect or generation fails
*/
function crypto_sign_seed_keypair(pk: Buffer, sk: Buffer, seed: Buffer): void;Usage Example:
const sodium = require('sodium-native');
// Generate signing key pair
const publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);
const secretKey = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES);
sodium.crypto_sign_keypair(publicKey, secretKey);
// Or generate from seed for reproducible keys
const seed = Buffer.alloc(sodium.crypto_sign_SEEDBYTES);
sodium.randombytes_buf(seed);
sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed);Signs a message and combines it with the signature.
/**
* Sign message and combine with signature
* @param sm - Output buffer for signed message (must be m.length + BYTES)
* @param m - Message buffer to sign
* @param sk - Secret key buffer (must be SECRETKEYBYTES long)
* @throws Error if buffer sizes are incorrect or signing fails
*/
function crypto_sign(sm: Buffer, m: Buffer, sk: Buffer): void;Verifies a signed message and extracts the original message.
/**
* Verify signed message and extract original message
* @param m - Output buffer for original message (must be sm.length - BYTES)
* @param sm - Signed message buffer to verify
* @param pk - Public key buffer (must be PUBLICKEYBYTES long)
* @returns true if verification successful, false if signature invalid
* @throws Error if buffer sizes are incorrect
*/
function crypto_sign_open(m: Buffer, sm: Buffer, pk: Buffer): boolean;Usage Example:
const sodium = require('sodium-native');
// Sign a message (combined mode)
const message = Buffer.from('Important message');
const signedMessage = Buffer.alloc(message.length + sodium.crypto_sign_BYTES);
sodium.crypto_sign(signedMessage, message, secretKey);
// Verify and extract message
const extractedMessage = Buffer.alloc(signedMessage.length - sodium.crypto_sign_BYTES);
if (sodium.crypto_sign_open(extractedMessage, signedMessage, publicKey)) {
console.log('Verified message:', extractedMessage.toString());
} else {
console.log('Invalid signature');
}Creates a signature that is stored separately from the message.
/**
* Create detached signature for message
* @param sig - Output buffer for signature (must be BYTES long)
* @param m - Message buffer to sign
* @param sk - Secret key buffer (must be SECRETKEYBYTES long)
* @throws Error if buffer sizes are incorrect or signing fails
*/
function crypto_sign_detached(sig: Buffer, m: Buffer, sk: Buffer): void;Verifies a detached signature against a message.
/**
* Verify detached signature against message
* @param sig - Signature buffer to verify (must be BYTES long)
* @param m - Message buffer that was signed
* @param pk - Public key buffer (must be PUBLICKEYBYTES long)
* @returns true if signature is valid, false otherwise
*/
function crypto_sign_verify_detached(sig: Buffer, m: Buffer, pk: Buffer): boolean;Usage Example:
const sodium = require('sodium-native');
// Create detached signature
const message = Buffer.from('Document to sign');
const signature = Buffer.alloc(sodium.crypto_sign_BYTES);
sodium.crypto_sign_detached(signature, message, secretKey);
// Verify detached signature
if (sodium.crypto_sign_verify_detached(signature, message, publicKey)) {
console.log('Signature is valid');
} else {
console.log('Invalid signature');
}Extract public key from secret key and convert between Ed25519 and Curve25519 keys.
/**
* Extract public key from Ed25519 secret key
* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)
* @param sk - Secret key buffer (must be SECRETKEYBYTES long)
* @throws Error if buffer sizes are incorrect or extraction fails
*/
function crypto_sign_ed25519_sk_to_pk(pk: Buffer, sk: Buffer): void;
/**
* Convert Ed25519 public key to Curve25519 public key
* @param x25519pk - Output buffer for Curve25519 public key
* @param ed25519pk - Ed25519 public key to convert
* @throws Error if conversion fails or buffer sizes incorrect
*/
function crypto_sign_ed25519_pk_to_curve25519(x25519pk: Buffer, ed25519pk: Buffer): void;
/**
* Convert Ed25519 secret key to Curve25519 secret key
* @param x25519sk - Output buffer for Curve25519 secret key
* @param ed25519sk - Ed25519 secret key to convert
* @throws Error if conversion fails or buffer sizes incorrect
*/
function crypto_sign_ed25519_sk_to_curve25519(x25519sk: Buffer, ed25519sk: Buffer): void;Usage Example:
const sodium = require('sodium-native');
// Extract public key from secret key
const derivedPublicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);
sodium.crypto_sign_ed25519_sk_to_pk(derivedPublicKey, secretKey);
// Convert Ed25519 keys to Curve25519 for encryption
const curve25519PublicKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES);
const curve25519SecretKey = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES);
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519PublicKey, publicKey);
sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519SecretKey, secretKey);// Seed size for deterministic key generation
const crypto_sign_SEEDBYTES: number;
// Public key size in bytes
const crypto_sign_PUBLICKEYBYTES: number;
// Secret key size in bytes
const crypto_sign_SECRETKEYBYTES: number;
// Signature size in bytes
const crypto_sign_BYTES: number;sodium_malloc() for storage.const sodium = require('sodium-native');
class DocumentSigner {
constructor() {
this.publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);
this.secretKey = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES);
sodium.crypto_sign_keypair(this.publicKey, this.secretKey);
}
signDocument(document) {
const signature = Buffer.alloc(sodium.crypto_sign_BYTES);
sodium.crypto_sign_detached(signature, document, this.secretKey);
return {
document: document,
signature: signature,
publicKey: this.publicKey
};
}
static verifyDocument(signedDoc) {
return sodium.crypto_sign_verify_detached(
signedDoc.signature,
signedDoc.document,
signedDoc.publicKey
);
}
}
// Usage
const signer = new DocumentSigner();
const document = Buffer.from('Important contract text');
const signed = signer.signDocument(document);
if (DocumentSigner.verifyDocument(signed)) {
console.log('Document signature is valid');
}const sodium = require('sodium-native');
class MultiSigVerifier {
constructor() {
this.signers = new Map();
}
addSigner(name, publicKey) {
this.signers.set(name, publicKey);
}
verifySignatures(document, signatures) {
const results = new Map();
for (const [signerName, signature] of signatures) {
const publicKey = this.signers.get(signerName);
if (publicKey) {
const isValid = sodium.crypto_sign_verify_detached(
signature,
document,
publicKey
);
results.set(signerName, isValid);
}
}
return results;
}
requireMinimumSignatures(document, signatures, minRequired) {
const results = this.verifySignatures(document, signatures);
const validCount = Array.from(results.values()).filter(valid => valid).length;
return validCount >= minRequired;
}
}Install with Tessl CLI
npx tessl i tessl/npm-sodium-native