{"id":11367,"library":"msrcrypto","title":"MSR JavaScript Cryptography Library","description":"msrCrypto is a JavaScript cryptography library, originally developed by Microsoft Research and subsequently maintained by Kevlened. It serves as a polyfill for the W3C Web Cryptography API, enabling modern cryptographic primitives like RSA-OAEP, AES-CBC, SHA-256/384/512, HMAC, ECDH, and ECDSA in environments where native Web Crypto API support is absent or inconsistent. Its primary differentiation is its broad browser compatibility, extending to older browsers like Internet Explorer 8, 9, 10, and 11, alongside modern browsers. Since version 1.4, it has adopted a Promise-based API for asynchronous operations, aligning with the Web Crypto API specification. The current stable version, as per the user's input, is 1.5.8, though a `1.6.5` version appears on npm under `@dashdot/msrcrypto` with the last publish 4 years ago, and `1.5.8` itself was published 6 years ago. Its release cadence appears infrequent, with updates primarily addressing API compliance, security bug fixes, and feature enhancements for specific algorithms.","status":"maintenance","version":"1.5.8","language":"javascript","source_language":"en","source_url":"https://github.com/kevlened/msrCrypto","tags":["javascript","crypto","webcrypto","ES3"],"install":[{"cmd":"npm install msrcrypto","lang":"bash","label":"npm"},{"cmd":"yarn add msrcrypto","lang":"bash","label":"yarn"},{"cmd":"pnpm add msrcrypto","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"msrCrypto is designed to be loaded via a script tag, which exposes the global `msrCrypto` object. It is not an ES module or CommonJS module and attempting to import it will result in errors or unintended global pollution.","wrong":"import * as msrCrypto from 'msrcrypto';\nimport { subtle } from 'msrcrypto';\nconst msrCrypto = require('msrcrypto');","symbol":"msrCrypto","correct":"<script src=\"path/to/msrcrypto.js\"></script>"},{"note":"The library creates a global `msrCrypto` object, which mirrors the Web Crypto API's `crypto.subtle` interface. While modern browsers have `window.crypto.subtle`, `msrCrypto.subtle` is the correct entry point for this polyfill.","wrong":"window.crypto.subtle.encrypt(...);","symbol":"msrCrypto.subtle","correct":"msrCrypto.subtle.encrypt(...)"},{"note":"On older browsers (IE8, IE9, IE10) that lack `window.crypto.getRandomValues`, `msrCrypto` requires its internal Pseudo-Random Number Generator (PRNG) to be explicitly initialized with cryptographically secure random bytes (e.g., 48 bytes from a server-side crypto API) via `msrCrypto.initPrng` before performing any cryptographic operations. This is crucial for security.","wrong":"msrCrypto.subtle.generateKey(...); // without prior PRNG initialization on older browsers","symbol":"msrCrypto.initPrng","correct":"if (window.msrCrypto && typeof window.msrCrypto.initPrng === 'function') {\n  // Obtain 48 random bytes from a secure source (e.g., server-side)\n  const entropy = new Uint8Array(48);\n  // Populate entropy with cryptographically strong random values\n  // For example, if on Node.js: require('crypto').randomBytes(48);\n  // For modern browser: window.crypto.getRandomValues(entropy);\n  window.msrCrypto.initPrng(entropy);\n}"}],"quickstart":{"code":"// This quickstart assumes msrcrypto.js has been loaded via a <script> tag,\n// making the global `msrCrypto` object available.\n\n// 1. Generate an AES-CBC key\nconst iv = new new Uint8Array(16); // Initialization Vector\n// On modern browsers, use window.crypto.getRandomValues(iv);\n// On older browsers, ensure PRNG is seeded (see warnings) or provide secure random bytes\n// For this example, we'll simulate random values or assume a modern environment fallback\n// For a truly secure setup in older IE, you'd need server-side entropy for msrCrypto.initPrng()\n\n// Simulate getRandomValues for environments where it might not be available or fully polyfilled for iv generation\nif (typeof window.crypto !== 'undefined' && typeof window.crypto.getRandomValues === 'function') {\n  window.crypto.getRandomValues(iv);\n} else {\n  // Fallback for demonstration, NOT cryptographically secure in production for IV\n  for (let i = 0; i < iv.length; i++) iv[i] = Math.floor(Math.random() * 256);\n}\n\nmsrCrypto.subtle.generateKey(\n  {\n    name: \"AES-CBC\",\n    length: 256, // For AES-256\n  },\n  true, // key is extractable\n  [\"encrypt\", \"decrypt\"]\n)\n.then(function(key) {\n  console.log(\"AES-CBC Key generated successfully.\");\n  // 2. Encrypt some data\n  const dataToEncrypt = new TextEncoder().encode(\"Hello, msrcrypto, this is a secret message!\");\n\n  return msrCrypto.subtle.encrypt(\n    {\n      name: \"AES-CBC\",\n      iv: iv,\n    },\n    key,\n    dataToEncrypt\n  );\n})\n.then(function(encryptedData) {\n  console.log(\"Data encrypted successfully (ArrayBuffer):\");\n  // In IE8/9, this might be a regular Array, convert for consistent logging if needed\n  console.log(new Uint8Array(encryptedData));\n  // Further steps would involve decrypting or sending the data\n})\n.catch(function(error) {\n  console.error(\"Encryption failed:\", error);\n});","lang":"javascript","description":"This quickstart demonstrates how to generate an AES-CBC key and encrypt a plain text message using the `msrCrypto.subtle` API, mimicking the Web Crypto API. It highlights the promise-based asynchronous operations."},"warnings":[{"fix":"Rewrite cryptographic operations to use the `.then().catch()` Promise syntax instead of assigning `onComplete` and `onError` handlers.","message":"The API significantly changed in version 1.4 from event-based callbacks (common in IE11 native crypto) to Promise-based returns, aligning with the modern Web Crypto API specification. Code using `cryptoOperation.onComplete` or `cryptoOperation.onError` will break.","severity":"breaking","affected_versions":">=1.4"},{"fix":"Upgrade to version 1.4.1 or higher immediately to apply critical security patches and ensure correct elliptic curve cryptography.","message":"Version 1.4.1 included critical bug fixes for the elliptic curve module, addressing erroneous calculations that could theoretically leak private data, correcting the NIST p-521 curve definition, and preventing rare ECDSA failures. Users on older versions are exposed to these vulnerabilities.","severity":"breaking","affected_versions":"<1.4.1"},{"fix":"Access the `catch` method using bracket notation: `promise['catch'](function(error) { ... });`.","message":"In Internet Explorer 8 (IE8), `catch` is a reserved JavaScript keyword. Directly calling `promise.catch()` will throw a `SyntaxError`.","severity":"gotcha","affected_versions":"all"},{"fix":"Implement logic to convert between Typed Arrays and regular Arrays based on browser capabilities, or use regular Arrays universally if targeting IE8/9. A common workaround is a simple `Uint8Array` wrapper for regular `Array`s when Typed Arrays are not supported.","message":"IE8 and IE9 do not support Typed Arrays (e.g., `ArrayBuffer`, `Uint8Array`). When using these browsers, `msrCrypto` expects and returns regular JavaScript Arrays for input and output data. For IE10 and up, it uses `ArrayBuffer`.","severity":"gotcha","affected_versions":"all"},{"fix":"Disable automatic web worker usage if bundling, or ensure that the bundled script's path is correctly resolvable by `new Worker()`. The `1.6` version (under `@dashdot/msrcrypto`) disables automatic web-worker usage by default to mitigate this.","message":"Automatic web worker usage (for offloading crypto work) can fail if `msrCrypto` is bundled into a larger JavaScript file. The library attempts to determine its own path to instantiate new workers (`new Worker(pathToJavaScriptFile)`), and bundling breaks this path resolution.","severity":"gotcha","affected_versions":"all"},{"fix":"Obtain cryptographically secure random bytes from a trusted source (e.g., a server-side crypto API over HTTPS) and use `window.msrCrypto.initPrng(randomBytesArray)` to seed the PRNG before any other crypto calls on affected browsers. Modern browsers will use `window.crypto.getRandomValues` to seed it automatically.","message":"For older browsers (IE8, 9, 10) lacking `window.crypto.getRandomValues`, `msrCrypto`'s internal Pseudo-Random Number Generator (PRNG) requires explicit seeding with cryptographically secure random bytes (e.g., 48 bytes) via `msrCrypto.initPrng()` for secure operation. Without this, cryptographic operations may not be truly random.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Update your code to use the Promise-based `.then()` and `.catch()` syntax for cryptographic operations.","cause":"Attempting to use the pre-1.4 event-based API (`onComplete`, `onError`) after upgrading to version 1.4 or higher, which uses Promises.","error":"TypeError: cryptoOperation.onComplete is not a function"},{"fix":"Use bracket notation to access the `catch` method: `promise['catch'](function(error) { /* handle error */ });`.","cause":"Calling `promise.catch()` directly in Internet Explorer 8, where `catch` is a reserved keyword.","error":"SyntaxError: Expected identifier, string or number"},{"fix":"Ensure `msrcrypto.js` is included in your HTML using a `<script>` tag before any code attempts to access `msrCrypto`. Verify the script path is correct and accessible.","cause":"The `msrcrypto.js` script was not loaded via a `<script>` tag, or it was loaded in a module environment without being exposed globally, or the script failed to load.","error":"ReferenceError: msrCrypto is not defined"},{"fix":"Provide input data as regular JavaScript Arrays and handle returned data as regular Arrays when targeting IE8/9. For IE10+, `ArrayBuffer` is used. You may need to write compatibility layers.","cause":"Attempting to use Typed Arrays (like `Uint8Array` or `ArrayBuffer`) as input or expecting them as output in IE8 or IE9, which do not support them.","error":"TypeError: Object doesn't support property or method 'fill' (or similar errors related to Typed Arrays in IE8/9)"},{"fix":"Modify your CSP to allow worker scripts. For example, add `worker-src 'self' blob:` or `script-src 'self' blob:` depending on how your workers are loaded. Alternatively, bundle `msrCrypto` in a way that disables web workers, or use a version that has web workers disabled by default (e.g., `@dashdot/msrcrypto@1.6`).","cause":"The Content Security Policy (CSP) of your application is preventing the creation of Web Workers, which `msrCrypto` tries to use for performance.","error":"SecurityError: Failed to create a new Worker: Script resource is blocked by Content Security Policy."}],"ecosystem":"npm"}