{"id":15338,"library":"iron-webcrypto","title":"WebCrypto-based Iron Implementation","description":"iron-webcrypto is a JavaScript/TypeScript library providing a WebCrypto API-based implementation of `@hapi/iron`. It enables sealing (encrypting and signing) and unsealing JSON-like data using symmetric key encryption with built-in message integrity verification, producing compact, URL-safe string tokens. The current stable version is 2.0.0, which notably dropped support for Node.js versions older than 20 and transitioned to an ESM-only module. It differentiates itself by relying solely on standard WebCrypto APIs, making it highly portable across modern JavaScript runtimes like Node.js v20+, Deno, Bun, and Cloudflare Workers, without depending on Node.js-specific `node:crypto` or `node:buffer` modules. The library's API is designed to be compatible with `@hapi/iron`, facilitating migrations or consistent usage patterns across projects. It ships with full TypeScript type definitions and is primarily intended for server-side or worker environments due to security implications of client-side secret exposure, which could expose encryption secrets.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/brc-dd/iron-webcrypto","tags":["javascript","authentication","data integrity","encryption","webcrypto","typescript"],"install":[{"cmd":"npm install iron-webcrypto","lang":"bash","label":"npm"},{"cmd":"yarn add iron-webcrypto","lang":"bash","label":"yarn"},{"cmd":"pnpm add iron-webcrypto","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"iron-webcrypto is an ESM-only package since v2; CommonJS `require` is not supported. For Deno/JSR, use `import * as Iron from '@brc-dd/iron'`.","wrong":"const Iron = require('iron-webcrypto')","symbol":"Iron","correct":"import * as Iron from 'iron-webcrypto'"},{"note":"All primary functions are named exports from the top-level package. Avoid importing from internal paths.","wrong":"import { seal } from 'iron-webcrypto/lib/seal'","symbol":"seal, unseal","correct":"import { seal, unseal } from 'iron-webcrypto'"},{"note":"Commonly used default options for sealing and unsealing.","symbol":"defaults","correct":"import { defaults } from 'iron-webcrypto'"}],"quickstart":{"code":"import * as Iron from 'iron-webcrypto'\n\nasync function runCryptoExample() {\n  // It's crucial to use a strong, randomly generated secret stored securely\n  // in environment variables or a secrets manager. NEVER hardcode in production.\n  const password = process.env.IRON_SECRET_KEY ?? 'a_long_random_secret_please_change_me_32_chars_min'\n  \n  if (password.length < 32) {\n    console.error('Warning: Password must be at least 32 characters long for security.')\n    return\n  }\n\n  const payload = { userId: 123, scope: ['user'], issuedAt: Date.now() }\n\n  try {\n    const sealed = await Iron.seal(payload, password, Iron.defaults)\n    console.log('Sealed token:', sealed)\n\n    // Simulate receiving the token later or in another service\n    const unsealed = await Iron.unseal(sealed, password, Iron.defaults)\n    console.log('Unsealed payload:', unsealed)\n\n    // Example with TTL (Time To Live)\n    const optionsWithTTL = { ...Iron.defaults, ttl: 5000 } // 5 seconds expiry\n    const sealedWithTTL = await Iron.seal(payload, password, optionsWithTTL)\n    console.log('Sealed token with TTL:', sealedWithTTL)\n\n    // Wait for expiry (optional, for demonstration)\n    // await new Promise(resolve => setTimeout(resolve, 6000))\n    // try {\n    //   await Iron.unseal(sealedWithTTL, password, optionsWithTTL)\n    // } catch (e) {\n    //   console.log('Expected expiry error:', e.message)\n    // }\n\n  } catch (error) {\n    console.error('Cryptography operation failed:', error)\n  }\n}\n\nrunCryptoExample()","lang":"typescript","description":"Demonstrates sealing a JSON object into a tamper-evident, encrypted token and then unsealing it, highlighting the use of a secure password and default options."},"warnings":[{"fix":"Upgrade your Node.js environment to version 20 or higher to ensure compatibility.","message":"Version 2.0.0 of `iron-webcrypto` drops support for Node.js versions older than v20. Running on unsupported versions may lead to runtime errors or unexpected behavior due to missing WebCrypto APIs.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Replace usage of internal utility functions with purpose-built libraries like `uint8array-extras` for base64/buffer operations.","message":"Internal utility functions for base64/buffer operations, which were not part of the public API, have been removed in v2.0.0. If you were using these, migrate to dedicated libraries like `uint8array-extras`.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Use `iron-webcrypto` primarily in server-side, worker, or other secure backend environments where encryption secrets can be properly managed and protected.","message":"While `iron-webcrypto` technically functions in a browser environment due to its WebCrypto reliance, it is not recommended for client-side use. Exposing encryption secrets (passwords) to the client poses significant security risks.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Refactor your application to load encryption secrets from environment variables (e.g., `process.env.IRON_SECRET_KEY`) or a secure secrets management service.","message":"Encryption secrets (passwords) should never be hardcoded in application code. They must be stored securely, ideally in environment variables, a secrets manager, or a secure configuration system.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure that the password provided for sealing and unsealing is at least 32 characters long. Adjust `minPasswordLength` in `SealOptions` if absolutely necessary for specific use cases (though not recommended).","message":"The default `minPasswordLength` is 32 characters. Using passwords shorter than this may be insecure and could result in runtime errors or weakened cryptography.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Change `const Iron = require('iron-webcrypto')` to `import * as Iron from 'iron-webcrypto'` and ensure your project is configured for ESM.","cause":"Attempting to use CommonJS `require()` syntax with an ESM-only package.","error":"ReferenceError: require is not defined in ES module scope"},{"fix":"Upgrade your Node.js version to v20 or higher. Alternatively, ensure your environment provides a `crypto.subtle` implementation.","cause":"Running `iron-webcrypto` in an environment that lacks the WebCrypto API, most commonly an older Node.js version (<v20).","error":"TypeError: crypto.subtle is undefined"},{"fix":"Provide a password that meets or exceeds the minimum length configured in `SealOptions.encryption.minPasswordlength` (default: 32 characters). Always use strong, securely generated passwords.","cause":"The provided password for `seal` or `unseal` is shorter than the minimum required length (default 32 characters).","error":"RangeError: Password must be at least 32 characters long."}],"ecosystem":"npm"}