Skip to content

ext_crypto

The ext_crypto crate provides cryptographic operations for Forge applications through the runtime:crypto module.

Overview

ext_crypto handles:

  • Random generation - Cryptographically secure random bytes
  • Hashing - SHA-256, SHA-384, SHA-512
  • HMAC - Hash-based message authentication codes
  • Encryption - AES-256-GCM symmetric encryption
  • Key derivation - PBKDF2 key derivation

Module: runtime:crypto

import {
randomBytes,
hash,
hmac,
encrypt,
decrypt,
deriveKey
} from "runtime:crypto";

Key Types

Error Types

enum CryptoErrorCode {
Generic = 8000,
InvalidAlgorithm = 8001,
InvalidKeyLength = 8002,
EncryptionFailed = 8003,
DecryptionFailed = 8004,
HashFailed = 8005,
HmacFailed = 8006,
KeyGenerationFailed = 8007,
KeyDerivationFailed = 8008,
VerificationFailed = 8009,
}
struct CryptoError {
code: CryptoErrorCode,
message: String,
}

Algorithm Types

enum HashAlgorithm {
Sha256,
Sha384,
Sha512,
}
enum EncryptionAlgorithm {
Aes256Gcm,
}

Operations

OpTypeScriptDescription
op_crypto_random_bytesrandomBytes(length)Generate random bytes
op_crypto_hashhash(algorithm, data)Hash data
op_crypto_hmachmac(algorithm, key, data)Generate HMAC
op_crypto_encryptencrypt(key, data, nonce?)Encrypt with AES-256-GCM
op_crypto_decryptdecrypt(key, data, nonce)Decrypt with AES-256-GCM
op_crypto_derive_keyderiveKey(password, salt, iterations)PBKDF2 key derivation
op_crypto_verify_hmacverifyHmac(algorithm, key, data, signature)Verify HMAC

Usage Examples

Random Generation

import { randomBytes } from "runtime:crypto";
// Generate 32 random bytes
const key = await randomBytes(32);
const nonce = await randomBytes(12);

Hashing

import { hash } from "runtime:crypto";
const digest = await hash("sha256", new TextEncoder().encode("hello"));
console.log("SHA-256:", new Uint8Array(digest));

HMAC

import { hmac, verifyHmac } from "runtime:crypto";
const key = new Uint8Array(32);
const data = new TextEncoder().encode("message");
const signature = await hmac("sha256", key, data);
const valid = await verifyHmac("sha256", key, data, signature);

Encryption/Decryption

import { encrypt, decrypt, randomBytes } from "runtime:crypto";
const key = await randomBytes(32); // 256-bit key
const plaintext = new TextEncoder().encode("secret message");
// Encrypt
const { ciphertext, nonce } = await encrypt(key, plaintext);
// Decrypt
const decrypted = await decrypt(key, ciphertext, nonce);

Key Derivation

import { deriveKey } from "runtime:crypto";
const password = new TextEncoder().encode("password");
const salt = await randomBytes(16);
// Derive 256-bit key using PBKDF2
const key = await deriveKey(password, salt, 100000);

File Structure

crates/ext_crypto/
├── src/
│ └── lib.rs # Extension implementation
├── ts/
│ └── init.ts # TypeScript module shim
├── build.rs # forge-weld build configuration
└── Cargo.toml

Rust Implementation

Operations are annotated with forge-weld macros for automatic TypeScript binding generation:

src/lib.rs
use deno_core::{op2, Extension, OpState};
use forge_weld_macro::{weld_op, weld_enum};
use serde::{Deserialize, Serialize};
#[weld_enum]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HashAlgorithm {
Sha256,
Sha384,
Sha512,
}
#[weld_op(async)]
#[op2(async)]
#[buffer]
pub async fn op_crypto_hash(
#[serde] algorithm: HashAlgorithm,
#[buffer] data: &[u8],
) -> Result<Vec<u8>, CryptoError> {
// implementation
}

Build Configuration

build.rs
use forge_weld::ExtensionBuilder;
fn main() {
ExtensionBuilder::new("runtime_crypto", "runtime:crypto")
.ts_path("ts/init.ts")
.ops(&["op_crypto_random_bytes", "op_crypto_hash", "op_crypto_encrypt", /* ... */])
.generate_sdk_module("sdk")
.use_inventory_types()
.build()
.expect("Failed to build runtime_crypto extension");
}

Dependencies

DependencyPurpose
deno_coreOp definitions
ringCryptographic primitives
serdeSerialization
tracingLogging
forge-weldBuild-time code generation
forge-weld-macro#[weld_op], #[weld_enum] macros
linkmeCompile-time symbol collection

Security Notes

  • Uses the ring library for cryptographic operations
  • AES-256-GCM provides authenticated encryption
  • PBKDF2 uses HMAC-SHA256 internally
  • Random bytes are from system’s secure random source