CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sodium-native

Low level bindings for libsodium cryptographic library

Pending
Overview
Eval results
Files

ed25519.mddocs/

Elliptic Curve Operations

Low-level elliptic curve operations on Ed25519 for advanced cryptographic protocols, scalar arithmetic, and point operations.

Capabilities

Scalar Multiplication

Perform scalar multiplication operations on Ed25519 curve points.

/**
 * Multiply Ed25519 base point by scalar
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult_ed25519_base(q: Buffer, n: Buffer): void;

/**
 * Multiply Ed25519 point by scalar
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @param p - Point buffer to multiply (must be BYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult_ed25519(q: Buffer, n: Buffer, p: Buffer): void;

/**
 * Multiply Ed25519 base point by scalar (no clamping)
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult_ed25519_base_noclamp(q: Buffer, n: Buffer): void;

/**
 * Multiply Ed25519 point by scalar (no clamping)
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @param p - Point buffer to multiply (must be BYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult_ed25519_noclamp(q: Buffer, n: Buffer, p: Buffer): void;

Usage Example:

const sodium = require('sodium-native');

// Generate random scalar
const scalar = Buffer.alloc(sodium.crypto_scalarmult_ed25519_SCALARBYTES);
sodium.randombytes_buf(scalar);

// Multiply base point by scalar (equivalent to generating public key)
const point = Buffer.alloc(sodium.crypto_scalarmult_ed25519_BYTES);
sodium.crypto_scalarmult_ed25519_base(point, scalar);

// Multiply the resulting point by another scalar
const scalar2 = Buffer.alloc(sodium.crypto_scalarmult_ed25519_SCALARBYTES);
sodium.randombytes_buf(scalar2);

const point2 = Buffer.alloc(sodium.crypto_scalarmult_ed25519_BYTES);
sodium.crypto_scalarmult_ed25519(point2, scalar2, point);

Point Operations

Perform addition and subtraction operations on Ed25519 curve points.

/**
 * Add two Ed25519 points
 * @param r - Output buffer for result point (must be BYTES long)
 * @param p - First point buffer (must be BYTES long)
 * @param q - Second point buffer (must be BYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_core_ed25519_add(r: Buffer, p: Buffer, q: Buffer): void;

/**
 * Subtract Ed25519 points (r = p - q)
 * @param r - Output buffer for result point (must be BYTES long)
 * @param p - First point buffer (must be BYTES long)
 * @param q - Second point buffer (must be BYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_core_ed25519_sub(r: Buffer, p: Buffer, q: Buffer): void;

Point Validation

Check if a buffer represents a valid Ed25519 curve point.

/**
 * Check if buffer represents a valid Ed25519 point
 * @param p - Point buffer to validate (must be BYTES long)
 * @returns true if point is valid, false otherwise
 */
function crypto_core_ed25519_is_valid_point(p: Buffer): boolean;

Point Generation

Generate Ed25519 points from uniform random bytes.

/**
 * Map uniform bytes to Ed25519 curve point
 * @param p - Output buffer for point (must be BYTES long)
 * @param r - Uniform random bytes (must be UNIFORMBYTES long)
 * @throws Error if buffer sizes are incorrect or mapping fails
 */
function crypto_core_ed25519_from_uniform(p: Buffer, r: Buffer): void;

Usage Example:

const sodium = require('sodium-native');

// Generate two random points
const uniform1 = Buffer.alloc(sodium.crypto_core_ed25519_UNIFORMBYTES);
const uniform2 = Buffer.alloc(sodium.crypto_core_ed25519_UNIFORMBYTES);
sodium.randombytes_buf(uniform1);
sodium.randombytes_buf(uniform2);

const point1 = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
const point2 = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);

sodium.crypto_core_ed25519_from_uniform(point1, uniform1);
sodium.crypto_core_ed25519_from_uniform(point2, uniform2);

// Validate points
console.log('Point 1 valid:', sodium.crypto_core_ed25519_is_valid_point(point1));
console.log('Point 2 valid:', sodium.crypto_core_ed25519_is_valid_point(point2));

// Add points
const sum = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
sodium.crypto_core_ed25519_add(sum, point1, point2);

// Subtract points
const difference = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
sodium.crypto_core_ed25519_sub(difference, point1, point2);

Scalar Operations

Perform arithmetic operations on Ed25519 scalars.

/**
 * Generate random Ed25519 scalar
 * @param r - Output buffer for scalar (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_random(r: Buffer): void;

/**
 * Reduce bytes to Ed25519 scalar modulo curve order
 * @param r - Output buffer for reduced scalar (must be SCALARBYTES long)
 * @param s - Input bytes to reduce (must be NONREDUCEDSCALARBYTES long)
 */
function crypto_core_ed25519_scalar_reduce(r: Buffer, s: Buffer): void;

/**
 * Invert Ed25519 scalar (multiplicative inverse)
 * @param recip - Output buffer for inverted scalar (must be SCALARBYTES long)
 * @param s - Scalar buffer to invert (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_invert(recip: Buffer, s: Buffer): void;

/**
 * Negate Ed25519 scalar
 * @param neg - Output buffer for negated scalar (must be SCALARBYTES long)
 * @param s - Scalar buffer to negate (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_negate(neg: Buffer, s: Buffer): void;

/**
 * Complement Ed25519 scalar (1 - s)
 * @param comp - Output buffer for complement (must be SCALARBYTES long)
 * @param s - Scalar buffer to complement (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_complement(comp: Buffer, s: Buffer): void;

/**
 * Add Ed25519 scalars modulo curve order
 * @param z - Output buffer for sum (must be SCALARBYTES long)
 * @param x - First scalar buffer (must be SCALARBYTES long)
 * @param y - Second scalar buffer (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_add(z: Buffer, x: Buffer, y: Buffer): void;

/**
 * Subtract Ed25519 scalars modulo curve order
 * @param z - Output buffer for difference (must be SCALARBYTES long)
 * @param x - First scalar buffer (must be SCALARBYTES long)
 * @param y - Second scalar buffer (must be SCALARBYTES long)
 */
function crypto_core_ed25519_scalar_sub(z: Buffer, x: Buffer, y: Buffer): void;

Usage Example:

const sodium = require('sodium-native');

// Generate random scalars
const scalar1 = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
const scalar2 = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
sodium.crypto_core_ed25519_scalar_random(scalar1);
sodium.crypto_core_ed25519_scalar_random(scalar2);

// Scalar arithmetic
const sum = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
const difference = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
const inverse = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);

sodium.crypto_core_ed25519_scalar_add(sum, scalar1, scalar2);
sodium.crypto_core_ed25519_scalar_sub(difference, scalar1, scalar2);
sodium.crypto_core_ed25519_scalar_invert(inverse, scalar1);

// Reduce large bytes to scalar
const largeBytes = Buffer.alloc(sodium.crypto_core_ed25519_NONREDUCEDSCALARBYTES);
sodium.randombytes_buf(largeBytes);

const reducedScalar = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
sodium.crypto_core_ed25519_scalar_reduce(reducedScalar, largeBytes);

Curve25519 Scalar Multiplication

Perform scalar multiplication on Curve25519 (Montgomery form).

/**
 * Multiply Curve25519 base point by scalar
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult_base(q: Buffer, n: Buffer): void;

/**
 * Multiply Curve25519 point by scalar
 * @param q - Output buffer for resulting point (must be BYTES long)
 * @param n - Scalar buffer (must be SCALARBYTES long)
 * @param p - Point buffer to multiply (must be BYTES long)
 * @throws Error if buffer sizes are incorrect or operation fails
 */
function crypto_scalarmult(q: Buffer, n: Buffer, p: Buffer): void;

Constants

// Ed25519 point size in bytes
const crypto_core_ed25519_BYTES: number;

// Ed25519 uniform bytes size for point generation
const crypto_core_ed25519_UNIFORMBYTES: number;

// Ed25519 scalar size in bytes
const crypto_core_ed25519_SCALARBYTES: number;

// Ed25519 non-reduced scalar size in bytes
const crypto_core_ed25519_NONREDUCEDSCALARBYTES: number;

// Ed25519 scalar multiplication constants
const crypto_scalarmult_ed25519_BYTES: number;
const crypto_scalarmult_ed25519_SCALARBYTES: number;

// Curve25519 scalar multiplication constants
const crypto_scalarmult_BYTES: number;
const crypto_scalarmult_SCALARBYTES: number;

Security Considerations

  • Scalar Validation: Always validate scalars and points received from external sources.
  • Timing Attacks: All operations are designed to be constant-time.
  • Point Validation: Use crypto_core_ed25519_is_valid_point for untrusted points.
  • Clamping: Use non-clamping variants only when you understand the implications.

Common Patterns

Threshold Signatures Setup

const sodium = require('sodium-native');

class ThresholdSignature {
  static generateShares(threshold, participants) {
    const coefficients = [];
    
    // Generate polynomial coefficients
    for (let i = 0; i < threshold; i++) {
      const coeff = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
      sodium.crypto_core_ed25519_scalar_random(coeff);
      coefficients.push(coeff);
    }
    
    const shares = [];
    
    // Generate shares for each participant
    for (let participant = 1; participant <= participants; participant++) {
      let share = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
      share.fill(0);
      
      // Evaluate polynomial at participant index
      for (let i = 0; i < coefficients.length; i++) {
        const term = Buffer.alloc(sodium.crypto_core_ed25519_SCALARBYTES);
        // term = coefficient * (participant^i)
        // Simplified for example - real implementation needs proper field arithmetic
        if (i === 0) {
          Buffer.from(coefficients[i]).copy(term);
        } else {
          // Simplified power computation
          Buffer.from(coefficients[i]).copy(term);
        }
        
        sodium.crypto_core_ed25519_scalar_add(share, share, term);
      }
      
      shares.push({ participant, share });
    }
    
    return { shares, publicKey: this.derivePublicKey(coefficients[0]) };
  }
  
  static derivePublicKey(secretKey) {
    const publicKey = Buffer.alloc(sodium.crypto_scalarmult_ed25519_BYTES);
    sodium.crypto_scalarmult_ed25519_base(publicKey, secretKey);
    return publicKey;
  }
}

Elliptic Curve Diffie-Hellman

const sodium = require('sodium-native');

class ECDHKeyExchange {
  constructor() {
    // Generate private key (scalar)
    this.privateKey = Buffer.alloc(sodium.crypto_scalarmult_SCALARBYTES);
    sodium.randombytes_buf(this.privateKey);
    
    // Generate public key (point)
    this.publicKey = Buffer.alloc(sodium.crypto_scalarmult_BYTES);
    sodium.crypto_scalarmult_base(this.publicKey, this.privateKey);
  }
  
  // Compute shared secret with peer's public key
  computeSharedSecret(peerPublicKey) {
    const sharedSecret = Buffer.alloc(sodium.crypto_scalarmult_BYTES);
    sodium.crypto_scalarmult(sharedSecret, this.privateKey, peerPublicKey);
    return sharedSecret;
  }
  
  // Derive encryption key from shared secret
  deriveKey(sharedSecret, info = 'encryption') {
    const key = Buffer.alloc(32);
    const combined = Buffer.concat([sharedSecret, Buffer.from(info)]);
    sodium.crypto_generichash(key, combined);
    return key;
  }
}

// Usage
const alice = new ECDHKeyExchange();
const bob = new ECDHKeyExchange();

const aliceShared = alice.computeSharedSecret(bob.publicKey);
const bobShared = bob.computeSharedSecret(alice.publicKey);

console.log('Shared secrets match:', aliceShared.equals(bobShared));

const encryptionKey = alice.deriveKey(aliceShared);

Point Compression/Decompression

const sodium = require('sodium-native');

class PointCompression {
  // Compress Ed25519 point (32 bytes -> 32 bytes with sign bit)
  static compressPoint(point) {
    // Ed25519 points are already in compressed form in sodium-native
    // This is a conceptual example
    return point;
  }
  
  // Decompress Ed25519 point
  static decompressPoint(compressedPoint) {
    // Validate the compressed point
    if (!sodium.crypto_core_ed25519_is_valid_point(compressedPoint)) {
      throw new Error('Invalid compressed point');
    }
    return compressedPoint;
  }
  
  // Generate valid random point
  static generateRandomPoint() {
    const uniform = Buffer.alloc(sodium.crypto_core_ed25519_UNIFORMBYTES);
    sodium.randombytes_buf(uniform);
    
    const point = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
    sodium.crypto_core_ed25519_from_uniform(point, uniform);
    
    return point;
  }
}

Multi-scalar Multiplication

const sodium = require('sodium-native');

class MultiScalarMult {
  // Compute sum of scalar multiplications: s1*P1 + s2*P2 + ... + sn*Pn
  static multiScalarMult(scalars, points) {
    if (scalars.length !== points.length) {
      throw new Error('Scalars and points arrays must have same length');
    }
    
    let result = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
    result.fill(0); // Start with identity point
    
    for (let i = 0; i < scalars.length; i++) {
      const product = Buffer.alloc(sodium.crypto_scalarmult_ed25519_BYTES);
      sodium.crypto_scalarmult_ed25519(product, scalars[i], points[i]);
      
      if (i === 0) {
        Buffer.from(product).copy(result);
      } else {
        sodium.crypto_core_ed25519_add(result, result, product);
      }
    }
    
    return result;
  }
  
  // Compute linear combination with base point: s1*G + s2*P2 + ... + sn*Pn
  static linearCombination(baseScalar, scalars, points) {
    const baseProduct = Buffer.alloc(sodium.crypto_scalarmult_ed25519_BYTES);
    sodium.crypto_scalarmult_ed25519_base(baseProduct, baseScalar);
    
    if (scalars.length === 0) {
      return baseProduct;
    }
    
    const otherProducts = this.multiScalarMult(scalars, points);
    
    const result = Buffer.alloc(sodium.crypto_core_ed25519_BYTES);
    sodium.crypto_core_ed25519_add(result, baseProduct, otherProducts);
    
    return result;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-sodium-native

docs

aead.md

auth.md

box.md

ed25519.md

hash.md

index.md

kdf.md

kx.md

memory.md

pwhash.md

random.md

secretbox.md

secretstream.md

shorthash.md

sign.md

stream.md

tile.json