Skip to content

Latest commit

 

History

History
196 lines (145 loc) · 11.7 KB

File metadata and controls

196 lines (145 loc) · 11.7 KB

Overview

The Microsoft Research JavaScript Cryptography Library (msrCrypto) has been developed for use with cloud services in an HTML5 compliant and forward-looking manner. The algorithms are exposed via the W3C Web Cryptography API.

The library currently supports RSA encryption (OAEP) and digital signature (PSS); AES-CBC and GCM encrypt/decrypt; SHA-256/384/512, HMAC with supported hash functions; PRNG (AES-CTR based) as specified by NIST; ECDH; ECDSA; and KDF (Concat). The library is tested on IE8, 9, 10, 11, Microsoft Edge and latest Firefox, Chrome, Opera, and Safari browsers.

This library includes big-number integer arithmetic to support the aforementioned cryptographic algorithms. It supports unsigned big integer arithmetic with addition, subtraction, multiplication, division, reduction, inversion, GCD, extended Euclidean algorithm (EEA), Montgomery multiplication, and modular exponentiation. It provides useful utility functions, such as endianness management and conversion routines. The big integer library is likely to change in future releases. Future updates to this library may change the programming interfaces.

This library has no run-time dependencies.

Recommended Usage

It is recommended that this library be used as a polyfill for the native Web Crypto API supported in modern browsers. It is strongly advised that you used the native browser crypto whenever available. It will be more thoroughly tested, more secure, and have significantly better performance.
It is not recommended to use this library in a server type application.

To select native crypto, when available, you can use the following code:

// Select native crypto if supported
var crypto =  window.crypto /*native*/ || window.msCrypto /*IE11 native*/ || window.msrCrypto; /*polyfill*/

// Call crypto functions
crypto.subtle.encrypt(...);

The library is exposed only under the name msrCrypto; it does not assign crypto or CryptoKey to the global scope automatically. Some libraries (for example, jose) expect a top-level CryptoKey to be available and will fail to recognize keys if it is missing. If you are using msrCrypto as a polyfill in an environment without native Web Crypto, assign both globals yourself:

// Only install the polyfill where native Web Crypto is not available.
if (!window.crypto || !window.crypto.subtle) {
    window.crypto = window.msrCrypto;             // exposes crypto.subtle, crypto.getRandomValues, etc.
    window.CryptoKey = window.msrCrypto.CryptoKey; // top-level CryptoKey constructor
}

Use globalThis instead of window in non-browser environments.

Keys returned by msrCrypto.subtle are instances of msrCrypto.CryptoKey. Once CryptoKey is assigned to the global scope, key instanceof CryptoKey evaluates to true, which satisfies the polyfill detection used by consumers such as jose.

Library Files

Full library /dist/msrcrypto.js
Minified library /dist/msrcrypto.min.js

Supported Algorithms

Encryption/Decryption:

  • RSA-OAEP
  • AES-GCM
  • AES-CBC (no longer recommended. Use AES-GCM. We continue support for compatibility)

Digital Signature

  • RSA-PSS
  • RSA-PKCSv1.15
  • HMAC
  • ECDSA

Hash

  • SHA-1 (no longer recommended. Use SHA-2. We continue support for compatibility)
  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512

Derive Key/Bits

  • ECDH
  • PBKDF2
  • Concat-KDF
  • HKDF

Wrap/Unwrap Key

  • AES-GCM, AES-CBC, AES-KW, RSA-OAEP

Supported ECC curves:

  • P-256, P-384, P-521, BN-254, NUMSP256D1, NUMSP256T1, NUMSP384D1, NUMSP384T1

Building the Library

While this library has npm build dependencies, it has no run-time dependencies.

You may build the library from the source files. The library is built using esbuild to concatenate many individual JavaScript files (in src/) into a single library file.
Run npm install from a command terminal to install the required npm packages. The fullBuild list in build.mjs contains the scripts included in the build. You may remove scripts to create a subset of the library that supports fewer algorithms. Be aware, many scripts have dependencies on other scripts to function properly.

Building from Visual Studio Code:

These steps require that git, Node.js, and Visual Studio Code are installed on your system.

  1. Clone the repo to a local folder git clone https://github.com/microsoft/MSR-JavaScript-Crypto.git
  2. Open Visual Studio Code, select menu File->Open Folder... and open the cloned MSR-JavaScript-Crypto folder.
  3. After the project has loaded, select menu Terminal->New Terminal to open a terminal window.
  4. At the terminal prompt, run npm install to install the required Node.js modules to the project's node_modules folder.

    You may need to reload the project for the build tools work properly:
    Select menu View->Command Palette... (or F1) then enter Developer: Reload Window

  5. Build the project: menu View->Command Palette... (or F1) then enter Tasks: Run Build Task.

    Alternately you can use the ctrl+shift+b keyboard shortcut.

  6. The newly built library files will appear in the dist directory as msrcrypto.js and msrcrypto.min.js.

Building from the command line:

These steps require that git and Node.js are installed on your system.

  1. Clone the repo to a local folder git clone https://github.com/microsoft/MSR-JavaScript-Crypto.git
  2. cd MSR-JavaScript-Crypto to enter the project directory.
  3. npm install to install the required Node.js modules to the project's node_modules folder.
  4. npm run build to build the library files.
  5. The newly built library files will appear in the dist directory as msrcrypto.js and msrcrypto.min.js.

Additional Utilities

msrCrypto supplies a few data conversion functions that are not part of the Web Cryptography API spec.
.textToBytes(String) converts a string to an Array of UTF-8 encoded bytes.
.bytesToText(Array|ArrayBuffer|TypedArray) converts UTF-8 bytes into a string.
.toBase64(Array|ArrayBuffer|TypedArray) converts byte data to a base-64 string.
.fromBase64(String) converts a base-64 string into an Array of bytes.

Limitations and Security

Native crypto
Developers should always use native platform crypto when available. Native crypto will have improved performance and offer additional security and memory protection not available in JavaScript. Modern browsers support the Web Crypto API.

Secret/private key data
Secret key data is stored in JavaScript's memory and is potentially accessible to other scripts, applications, browser extensions, and developer tools. While key data may be stored outside of JavaScripts memory, the key data will be required in-memory by the algorithms running in JavaScript.

Side-channel protection
We have taken steps to prevent side-channel vulnerabilities where practical in the library. This library is meant to run on many platforms with many JavaScript engines and we cannot control the side-channel prevention measures employed in either the engines or the underlying platforms.

HTTPS
When this library is used as part of an html application, HTTPS should always be used when connecting to the server. HTTPS will allow your secret keys and data to be transmitted to client across a secure connection.

Browser Compatibility

msrCrypto.js is compatible with IE8 and newer browsers; latest versions of Chrome, Firefox, Safari, and Opera.
Browser web crypto uses Typed-Arrays for input and output of data. msrCrypto can use either Typed-Arrays or regular Arrays.

Known issues:

IE8:

"Catch" is a reserved keyword. Calling the Promise.catch() function will throw an error.
To use the catch() function use the promise["catch"]() form.

IE8/9:

No Typed Array Support (ArrayBuffer, UInt8Array, etc...).
You must use regular Arrays for inputting data into msrCrypto when using IE8/9.
Results will be returned as regular Arrays as well. For IE10 and newer, results will be returned as an ArrayBuffer.
A workaround is to create a simple Uint8Array wrapper for an Array when Typed Arrays are not supported. You wont' get any actual Uint8Array functionality, but you can pass arguments without having to have special cases for your code.

if (!Uint8Array) {
	var Uint8Array = function (array) {
		return array;
	}
}

var data = new Uint8Array(dataArray);

IE11

IE11 supports the Web Crypto API, but was based on a pre-release version of the spec and was never updated. So it uses event based calls instead of Promises and a few other quirks of the API. In the /dist folder there is a IE11PromiseWrapper.js file. This shim can be loaded in IE11 and allow you to call the native Web Crypto API using the Promise based calling scheme. This shim also corrects some of the quirks in the IE11 API.

Random Number Generator (PRNG):

Many of msrCrypto's crypto algorithms require random numbers. Random numbers for cryptography need to be obtained from a cryptographically secure random number generator. This is not available on older browsers (IE10, IE9, & IE8).

msrCrypto has its own secure pseudo random number generator (PRNG) written in JavaScript. However, the PRNG needs to be initialized with some bytes of random entropy that it cannot obtain on older browsers. It is important that this entropy is obtained from a secure random source - such as from a crypto API on the server and sent with the web application over a secure HTTPS connection.

Newer browsers use Crypto.getRandomValues() to obtain cryptographically strong random values. msrCrypto's PRNG will seed itself with this when available.

Once the entropy is obtained initialize the PRNG before calling any functions. 48 random bytes is recommended.

msrCrypto.initPrng(<randomArrayOf48Bytes>);

API Documentation

Since this library uses the standard Web Cryptography API we used to recommend the official Microsoft documentation for the Web Crypto API in Microsoft Edge browser. I can no longer find that documentation.
A good source for documentation is:
MDN Web Docs Subtle Crypto
W3C Web Cryptography API

msrCrypto uses identical calls as these documents with the addition of allowing both regular JavaScript Arrays and Typed-Arrays for data input and output.

Changelog

See CHANGELOG.md for the history of notable changes across versions.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.