Port of TweetNaCl cryptographic library to JavaScript providing comprehensive cryptographic primitives
—
Low-level scalar multiplication using x25519. These functions provide the underlying elliptic curve operations used by the higher-level box functions, enabling custom cryptographic protocols and key derivation.
Perform elliptic curve scalar multiplication operations.
/**
* Multiplies an integer scalar by a group element (point on the curve)
* @param {Uint8Array} n - The scalar (32 bytes)
* @param {Uint8Array} p - The group element/point (32 bytes)
* @returns {Uint8Array} Resulting group element (32 bytes)
*/
nacl.scalarMult(n, p): Uint8Array
/**
* Multiplies an integer scalar by the standard base point of the curve
* @param {Uint8Array} n - The scalar (32 bytes)
* @returns {Uint8Array} Resulting group element (32 bytes)
*/
nacl.scalarMult.base(n): Uint8ArrayUsage Examples:
const nacl = require('tweetnacl');
// Generate a random scalar (private key)
const scalar = nacl.randomBytes(nacl.scalarMult.scalarLength);
// Multiply scalar by base point to get public key
const publicKey = nacl.scalarMult.base(scalar);
console.log(publicKey.length); // 32
// Perform Diffie-Hellman key exchange
const aliceSecret = nacl.randomBytes(32);
const bobSecret = nacl.randomBytes(32);
const alicePublic = nacl.scalarMult.base(aliceSecret);
const bobPublic = nacl.scalarMult.base(bobSecret);
// Both parties can compute the same shared secret
const aliceShared = nacl.scalarMult(aliceSecret, bobPublic);
const bobShared = nacl.scalarMult(bobSecret, alicePublic);
// Verify shared secrets are identical
const secretsMatch = aliceShared.every((byte, i) => byte === bobShared[i]);
console.log(secretsMatch); // trueKey Derivation Example:
const nacl = require('tweetnacl');
// Master key derivation
const masterKey = nacl.randomBytes(32);
const basePoint = nacl.scalarMult.base(masterKey);
// Derive child keys using different scalars
const childScalar1 = nacl.hash(new TextEncoder().encode("child1")).slice(0, 32);
const childScalar2 = nacl.hash(new TextEncoder().encode("child2")).slice(0, 32);
const childKey1 = nacl.scalarMult(childScalar1, basePoint);
const childKey2 = nacl.scalarMult(childScalar2, basePoint);
console.log("Child key 1:", childKey1);
console.log("Child key 2:", childKey2);nacl.scalarMult.scalarLength: number // 32 - Length of scalar in bytes
nacl.scalarMult.groupElementLength: number // 32 - Length of group element in bytesconst nacl = require('tweetnacl');
function createDiffieHellmanKeyPair() {
const secretKey = nacl.randomBytes(nacl.scalarMult.scalarLength);
const publicKey = nacl.scalarMult.base(secretKey);
return { secretKey, publicKey };
}
function computeSharedSecret(mySecretKey, theirPublicKey) {
return nacl.scalarMult(mySecretKey, theirPublicKey);
}
// Usage
const alice = createDiffieHellmanKeyPair();
const bob = createDiffieHellmanKeyPair();
const sharedSecretAlice = computeSharedSecret(alice.secretKey, bob.publicKey);
const sharedSecretBob = computeSharedSecret(bob.secretKey, alice.publicKey);
// Both shared secrets are identical
console.log(sharedSecretAlice.every((byte, i) => byte === sharedSecretBob[i])); // trueconst nacl = require('tweetnacl');
function isValidGroupElement(element) {
if (element.length !== nacl.scalarMult.groupElementLength) {
return false;
}
// Check if all bytes are zero (invalid point)
const allZero = element.every(byte => byte === 0);
return !allZero;
}
function isValidScalar(scalar) {
if (scalar.length !== nacl.scalarMult.scalarLength) {
return false;
}
// Check if all bytes are zero (invalid scalar)
const allZero = scalar.every(byte => byte === 0);
return !allZero;
}
// Example validation
const publicKey = nacl.scalarMult.base(nacl.randomBytes(32));
console.log(isValidGroupElement(publicKey)); // true
const zeroKey = new Uint8Array(32); // All zeros
console.log(isValidGroupElement(zeroKey)); // falsenacl.box functions instead.The nacl.box functions internally use scalar multiplication:
nacl.box.keyPair() uses nacl.scalarMult.base() to generate public keysnacl.box.before() uses nacl.scalarMult() to compute shared secretsUnderstanding scalar multiplication helps in designing custom protocols or optimizing performance-critical applications.
Install with Tessl CLI
npx tessl i tessl/npm-tweetnacl