Low level bindings for libsodium cryptographic library
—
Message authentication codes (MAC) using HMAC-SHA512 and Poly1305 for data integrity verification and authenticity.
Compute and verify HMAC-SHA512 message authentication codes.
/**
* Compute HMAC-SHA512 authentication tag
* @param out - Output buffer for authentication tag (must be BYTES long)
* @param input - Input buffer to authenticate
* @param k - Key buffer (must be KEYBYTES long)
* @throws Error if buffer sizes are incorrect or authentication fails
*/
function crypto_auth(out: Buffer, input: Buffer, k: Buffer): void;
/**
* Verify HMAC-SHA512 authentication tag
* @param h - Authentication tag to verify (must be BYTES long)
* @param input - Input buffer that was authenticated
* @param k - Key buffer (must be KEYBYTES long)
* @returns true if tag is valid, false otherwise
*/
function crypto_auth_verify(h: Buffer, input: Buffer, k: Buffer): boolean;Usage Example:
const sodium = require('sodium-native');
// Generate authentication key
const key = Buffer.alloc(sodium.crypto_auth_KEYBYTES);
sodium.randombytes_buf(key);
// Authenticate a message
const message = Buffer.from('Important message');
const tag = Buffer.alloc(sodium.crypto_auth_BYTES);
sodium.crypto_auth(tag, message, key);
// Verify the authentication tag
if (sodium.crypto_auth_verify(tag, message, key)) {
console.log('Message is authentic');
} else {
console.log('Message authentication failed');
}Poly1305 MAC for high-performance message authentication with one-time keys.
/**
* Compute Poly1305 authentication tag
* @param out - Output buffer for authentication tag (must be BYTES long)
* @param input - Input buffer to authenticate
* @param k - One-time key buffer (must be KEYBYTES long)
* @throws Error if buffer sizes are incorrect or authentication fails
*/
function crypto_onetimeauth(out: Buffer, input: Buffer, k: Buffer): void;
/**
* Verify Poly1305 authentication tag
* @param h - Authentication tag to verify (must be BYTES long)
* @param input - Input buffer that was authenticated
* @param k - One-time key buffer (must be KEYBYTES long)
* @returns true if tag is valid, false otherwise
*/
function crypto_onetimeauth_verify(h: Buffer, input: Buffer, k: Buffer): boolean;Initialize, update, and finalize Poly1305 authentication for large data.
/**
* Initialize Poly1305 streaming authentication
* @param state - State buffer (must be STATEBYTES long)
* @param k - One-time key buffer (must be KEYBYTES long)
* @throws Error if initialization fails or buffer sizes incorrect
*/
function crypto_onetimeauth_init(state: Buffer, k: Buffer): void;
/**
* Update Poly1305 streaming authentication with more data
* @param state - State buffer from init
* @param input - Input buffer to add to authentication
* @throws Error if update fails
*/
function crypto_onetimeauth_update(state: Buffer, input: Buffer): void;
/**
* Finalize Poly1305 streaming authentication and get tag
* @param state - State buffer from init/update
* @param out - Output buffer for authentication tag (must be BYTES long)
* @throws Error if finalization fails
*/
function crypto_onetimeauth_final(state: Buffer, out: Buffer): void;Usage Example:
const sodium = require('sodium-native');
// Generate one-time key
const key = Buffer.alloc(sodium.crypto_onetimeauth_KEYBYTES);
sodium.randombytes_buf(key);
// Streaming authentication for large data
const state = Buffer.alloc(sodium.crypto_onetimeauth_STATEBYTES);
sodium.crypto_onetimeauth_init(state, key);
// Process data in chunks
const chunk1 = Buffer.from('First part of ');
const chunk2 = Buffer.from('large message');
sodium.crypto_onetimeauth_update(state, chunk1);
sodium.crypto_onetimeauth_update(state, chunk2);
const tag = Buffer.alloc(sodium.crypto_onetimeauth_BYTES);
sodium.crypto_onetimeauth_final(state, tag);
// Verify using one-shot function
const fullMessage = Buffer.concat([chunk1, chunk2]);
if (sodium.crypto_onetimeauth_verify(tag, fullMessage, key)) {
console.log('Message is authentic');
}// HMAC-SHA512 constants
const crypto_auth_BYTES: number;
const crypto_auth_KEYBYTES: number;
// Poly1305 constants
const crypto_onetimeauth_STATEBYTES: number;
const crypto_onetimeauth_BYTES: number;
const crypto_onetimeauth_KEYBYTES: number;const sodium = require('sodium-native');
class MessageIntegrity {
constructor() {
this.hmacKey = Buffer.alloc(sodium.crypto_auth_KEYBYTES);
sodium.randombytes_buf(this.hmacKey);
}
sign(message) {
const tag = Buffer.alloc(sodium.crypto_auth_BYTES);
sodium.crypto_auth(tag, message, this.hmacKey);
return {
message: message,
tag: tag
};
}
verify(signedMessage) {
return sodium.crypto_auth_verify(
signedMessage.tag,
signedMessage.message,
this.hmacKey
);
}
// For one-time use (e.g., network packets)
signOneTime(message, oneTimeKey) {
const tag = Buffer.alloc(sodium.crypto_onetimeauth_BYTES);
sodium.crypto_onetimeauth(tag, message, oneTimeKey);
return tag;
}
verifyOneTime(message, tag, oneTimeKey) {
return sodium.crypto_onetimeauth_verify(tag, message, oneTimeKey);
}
}const sodium = require('sodium-native');
const fs = require('fs');
class FileIntegrityChecker {
constructor(keyFile) {
if (fs.existsSync(keyFile)) {
this.key = fs.readFileSync(keyFile);
} else {
this.key = Buffer.alloc(sodium.crypto_auth_KEYBYTES);
sodium.randombytes_buf(this.key);
fs.writeFileSync(keyFile, this.key);
}
}
createChecksum(filename) {
const data = fs.readFileSync(filename);
const checksum = Buffer.alloc(sodium.crypto_auth_BYTES);
sodium.crypto_auth(checksum, data, this.key);
// Save checksum file
fs.writeFileSync(`${filename}.checksum`, checksum);
return checksum;
}
verifyChecksum(filename) {
const checksumFile = `${filename}.checksum`;
if (!fs.existsSync(checksumFile)) {
throw new Error('Checksum file not found');
}
const data = fs.readFileSync(filename);
const storedChecksum = fs.readFileSync(checksumFile);
return sodium.crypto_auth_verify(storedChecksum, data, this.key);
}
// For streaming large files
createStreamingChecksum(filename) {
const state = Buffer.alloc(sodium.crypto_auth_STATEBYTES);
sodium.crypto_auth_init(state, this.key);
const fileStream = fs.createReadStream(filename, { highWaterMark: 64 * 1024 });
return new Promise((resolve, reject) => {
fileStream.on('data', (chunk) => {
sodium.crypto_auth_update(state, chunk);
});
fileStream.on('end', () => {
const checksum = Buffer.alloc(sodium.crypto_auth_BYTES);
sodium.crypto_auth_final(state, checksum);
resolve(checksum);
});
fileStream.on('error', reject);
});
}
}const sodium = require('sodium-native');
class APIAuth {
constructor(secretKey) {
this.secretKey = Buffer.from(secretKey);
if (this.secretKey.length !== sodium.crypto_auth_KEYBYTES) {
throw new Error('Invalid secret key length');
}
}
signRequest(method, url, body, timestamp) {
const message = Buffer.from(`${method}|${url}|${body}|${timestamp}`);
const signature = Buffer.alloc(sodium.crypto_auth_BYTES);
sodium.crypto_auth(signature, message, this.secretKey);
return {
signature: signature.toString('hex'),
timestamp: timestamp
};
}
verifyRequest(method, url, body, signature, timestamp) {
const message = Buffer.from(`${method}|${url}|${body}|${timestamp}`);
const signatureBuffer = Buffer.from(signature, 'hex');
if (signatureBuffer.length !== sodium.crypto_auth_BYTES) {
return false;
}
return sodium.crypto_auth_verify(signatureBuffer, message, this.secretKey);
}
}
// Usage
const apiAuth = new APIAuth('your-secret-key-32-bytes-long!!!!!');
const timestamp = Date.now();
const auth = apiAuth.signRequest('GET', '/api/users', '', timestamp);
console.log('Authorization:', auth.signature);
console.log('Timestamp:', auth.timestamp);Install with Tessl CLI
npx tessl i tessl/npm-sodium-native