or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

asymmetric-cryptography.mddigital-signatures.mdhash-functions.mdhmac.mdindex.mdkey-derivation.mdkey-exchange.mdrandom-generation.mdsymmetric-encryption.md
tile.json

asymmetric-cryptography.mddocs/

Asymmetric Cryptography

RSA public key cryptography for encryption, decryption, and secure key exchange using public/private key pairs.

Capabilities

Public Key Encryption

Encrypt data using a public key that can only be decrypted with the corresponding private key.

/**
 * Encrypt data using a public key
 * @param {string|Buffer|Object} key - Public key as string, Buffer, or key object
 * @param {Buffer} buffer - Data to encrypt as Buffer
 * @returns {Buffer} Encrypted data as Buffer
 */
function publicEncrypt(key, buffer) { }

Private Key Encryption (Signing)

Encrypt data using a private key for digital signatures (data can be decrypted with public key).

/**
 * Encrypt data using a private key (for digital signatures)
 * @param {string|Buffer|Object} key - Private key as string, Buffer, or key object
 * @param {Buffer} buffer - Data to encrypt as Buffer
 * @returns {Buffer} Encrypted data as Buffer
 */
function privateEncrypt(key, buffer) { }

Public Key Decryption (Signature Verification)

Decrypt data that was encrypted with a private key (signature verification).

/**
 * Decrypt data using a public key (for signature verification)
 * @param {string|Buffer|Object} key - Public key as string, Buffer, or key object
 * @param {Buffer} buffer - Encrypted data to decrypt as Buffer
 * @returns {Buffer} Decrypted data as Buffer
 */
function publicDecrypt(key, buffer) { }

Private Key Decryption

Decrypt data that was encrypted with the corresponding public key.

/**
 * Decrypt data using a private key
 * @param {string|Buffer|Object} key - Private key as string, Buffer, or key object
 * @param {Buffer} buffer - Encrypted data to decrypt as Buffer
 * @returns {Buffer} Decrypted data as Buffer
 */
function privateDecrypt(key, buffer) { }

Key Formats

Keys can be provided in several formats:

String Format (PEM)

const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;

const privateKeyPem = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
-----END PRIVATE KEY-----`;

Key Object Format

const keyObject = {
  key: publicKeyPem,
  padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
  oaepHash: 'sha256'
};

Buffer Format

const keyBuffer = Buffer.from(publicKeyPem, 'utf8');

Usage Examples

Basic Public Key Encryption

Encrypt data with public key, decrypt with private key.

const crypto = require('crypto-browserify');

// Example RSA key pair (in practice, generate or load from secure storage)
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1234...
-----END PUBLIC KEY-----`;

const privateKey = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDX...
-----END PRIVATE KEY-----`;

// Encrypt with public key
const plaintext = 'Secret message';
const buffer = Buffer.from(plaintext, 'utf8');
const encrypted = crypto.publicEncrypt(publicKey, buffer);

console.log('Encrypted:', encrypted.toString('base64'));

// Decrypt with private key
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log('Decrypted:', decrypted.toString('utf8'));

Hybrid Encryption

Combine RSA with symmetric encryption for large data.

const crypto = require('crypto-browserify');

function hybridEncrypt(data, publicKey) {
  // Generate random AES key
  const aesKey = crypto.randomBytes(32);
  const iv = crypto.randomBytes(16);
  
  // Encrypt data with AES
  const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv);
  let encryptedData = cipher.update(data, 'utf8', 'base64');
  encryptedData += cipher.final('base64');
  
  // Encrypt AES key with RSA public key
  const encryptedKey = crypto.publicEncrypt(publicKey, aesKey);
  
  return {
    encryptedKey: encryptedKey.toString('base64'),
    iv: iv.toString('base64'),
    encryptedData: encryptedData
  };
}

function hybridDecrypt(encryptedPackage, privateKey) {
  // Decrypt AES key with RSA private key
  const encryptedKey = Buffer.from(encryptedPackage.encryptedKey, 'base64');
  const aesKey = crypto.privateDecrypt(privateKey, encryptedKey);
  
  // Decrypt data with AES
  const iv = Buffer.from(encryptedPackage.iv, 'base64');
  const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, iv);
  let decrypted = decipher.update(encryptedPackage.encryptedData, 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}

// Usage
const largeData = 'This is a large amount of data that would be inefficient to encrypt directly with RSA...';
const encrypted = hybridEncrypt(largeData, publicKey);
const decrypted = hybridDecrypt(encrypted, privateKey);

Digital Signatures

Create and verify digital signatures using private/public key pairs.

const crypto = require('crypto-browserify');

function createSignature(message, privateKey) {
  const messageBuffer = Buffer.from(message, 'utf8');
  
  // Sign with private key (encrypt with private key)
  const signature = crypto.privateEncrypt(privateKey, messageBuffer);
  return signature.toString('base64');
}

function verifySignature(message, signature, publicKey) {
  try {
    const signatureBuffer = Buffer.from(signature, 'base64');
    
    // Verify with public key (decrypt with public key)
    const decryptedMessage = crypto.publicDecrypt(publicKey, signatureBuffer);
    const originalMessage = decryptedMessage.toString('utf8');
    
    return originalMessage === message;
  } catch (err) {
    return false;
  }
}

// Usage
const message = 'This message is authentic';
const signature = createSignature(message, privateKey);
console.log('Signature:', signature);

const isValid = verifySignature(message, signature, publicKey);
console.log('Signature valid:', isValid);

// Tampering detection
const tamperedMessage = 'This message is NOT authentic';
const isValidTampered = verifySignature(tamperedMessage, signature, publicKey);
console.log('Tampered signature valid:', isValidTampered); // false

Key Exchange

Securely exchange symmetric keys using RSA encryption.

const crypto = require('crypto-browserify');

// Sender generates symmetric key and encrypts it
function sendSymmetricKey(recipientPublicKey) {
  const symmetricKey = crypto.randomBytes(32); // 256-bit AES key
  const encryptedKey = crypto.publicEncrypt(recipientPublicKey, symmetricKey);
  
  return {
    encryptedKey: encryptedKey.toString('base64'),
    keyId: crypto.randomBytes(8).toString('hex') // Key identifier
  };
}

// Recipient decrypts the symmetric key
function receiveSymmetricKey(encryptedKeyPackage, privateKey) {
  const encryptedKey = Buffer.from(encryptedKeyPackage.encryptedKey, 'base64');
  const symmetricKey = crypto.privateDecrypt(privateKey, encryptedKey);
  
  return {
    key: symmetricKey,
    keyId: encryptedKeyPackage.keyId
  };
}

// Usage
const keyPackage = sendSymmetricKey(publicKey);
console.log('Encrypted key package:', keyPackage);

const decryptedKeyInfo = receiveSymmetricKey(keyPackage, privateKey);
console.log('Decrypted key ID:', decryptedKeyInfo.keyId);

Advanced Options

Padding Schemes

RSA encryption supports different padding schemes for security:

const crypto = require('crypto-browserify');

// PKCS#1 v1.5 padding (default)
const encrypted1 = crypto.publicEncrypt({
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PADDING
}, buffer);

// OAEP padding (more secure)
const encrypted2 = crypto.publicEncrypt({
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
  oaepHash: 'sha256'
}, buffer);

// No padding (dangerous, not recommended)
const encrypted3 = crypto.publicEncrypt({
  key: publicKey,
  padding: crypto.constants.RSA_NO_PADDING
}, buffer);

Passphrase-protected Keys

Handle encrypted private keys:

const crypto = require('crypto-browserify');

const encryptedPrivateKey = {
  key: `-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BAQ0wQTApBgkqhkiG9w0BAQwwHAQI...
-----END ENCRYPTED PRIVATE KEY-----`,
  passphrase: 'key-passphrase'
};

// Use encrypted key
const decrypted = crypto.privateDecrypt(encryptedPrivateKey, encryptedBuffer);

Security Considerations

Key Size

  • Use at least 2048-bit RSA keys (4096-bit preferred for long-term security)
  • Larger keys provide better security but slower performance

Padding

  • Always use proper padding (PKCS#1 v1.5 or OAEP)
  • OAEP is preferred for new applications
  • Never use no padding except in very specific circumstances

Data Size Limits

  • RSA can only encrypt data smaller than the key size minus padding overhead
  • For 2048-bit keys: ~245 bytes max with OAEP, ~245 bytes with PKCS#1 v1.5
  • Use hybrid encryption for larger data

Key Management

  • Protect private keys with strong passphrases
  • Store keys securely (hardware security modules, encrypted storage)
  • Use separate key pairs for encryption and signing

Error Handling

RSA functions may throw errors in the following scenarios:

  • Invalid key format: Malformed PEM keys or unsupported key types
  • Data too large: Data exceeds key size limitations
  • Wrong key type: Using private key where public key expected or vice versa
  • Padding errors: Invalid padding during decryption
  • Passphrase errors: Incorrect passphrase for encrypted keys
const crypto = require('crypto-browserify');

try {
  // Data too large for RSA key
  const largeBuffer = Buffer.alloc(1000, 'a');
  const encrypted = crypto.publicEncrypt(publicKey, largeBuffer);
} catch (err) {
  console.error('Data too large for RSA encryption:', err.message);
}

try {
  // Wrong key format
  const invalidKey = 'not-a-valid-key';
  const encrypted = crypto.publicEncrypt(invalidKey, Buffer.from('test'));
} catch (err) {
  console.error('Invalid key format:', err.message);
}

try {
  // Decryption with wrong key
  const encrypted = crypto.publicEncrypt(publicKey, Buffer.from('test'));
  const decrypted = crypto.privateDecrypt('wrong-private-key', encrypted);
} catch (err) {
  console.error('Decryption failed:', err.message);
}