Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6a58923
chore: update build scripts and dependencies
ljoy913 Jun 17, 2026
2dc7095
Update HashAlgorithmIdentifier handling to support string format
ljoy913 Jun 17, 2026
6a4978d
ECDH and ECDSA key generation and export use fixed lengths instead of…
ljoy913 Jun 18, 2026
677a02f
Add CryptoKey object
ljoy913 Jun 19, 2026
94f23f2
Fix HMAC and AES key generation
ljoy913 Jun 25, 2026
8c44b3e
Add IE8 compatibility fixes
ljoy913 Jun 25, 2026
97d1203
Add npm publishing metadata and release workflow
ljoy913 Jun 25, 2026
2851904
Remove VS Code workspace file
ljoy913 Jun 25, 2026
1c65270
Remove .vscode folder from repo
ljoy913 Jun 25, 2026
2026717
Simplify build to a single-stage bundle
ljoy913 Jun 25, 2026
8542f6e
Restructure: rename scripts/ to src/ and separate tests
ljoy913 Jun 25, 2026
961469b
Remove dead kdf.js and fix concat.js header
ljoy913 Jun 25, 2026
5c82c26
Remove dead curves_NUMS_old.js
ljoy913 Jun 25, 2026
fb621fa
Remove dead testInterface debug hook
ljoy913 Jun 25, 2026
71a85b7
Remove legacy IntelliSense file and broken test pages
ljoy913 Jun 25, 2026
3b91fa8
Fix lib filename casing in README build steps
ljoy913 Jun 25, 2026
5c48946
Rename testVectors/ to vectors/
ljoy913 Jun 25, 2026
280f5a5
Rename definitions/ to types/ for TypeScript declarations
ljoy913 Jun 25, 2026
e6c19c9
Move vectors under tests/ and rename lib/ to dist/
ljoy913 Jun 25, 2026
cd70b51
Fix concrete bugs in TypeScript declarations
ljoy913 Jun 25, 2026
46c991f
Rewrite msrCrypto type declarations (fuller pass)
ljoy913 Jun 25, 2026
6a6b573
Accept a string algorithm identifier for WebCrypto parity
ljoy913 Jun 25, 2026
0f0d262
Reject instead of throwing synchronously in subtle operations
ljoy913 Jun 25, 2026
519daad
Use DOMException for WebCrypto error parity
ljoy913 Jun 25, 2026
68ca034
Add error-handling test module for WebCrypto parity
ljoy913 Jun 25, 2026
f323c4f
Wire Test.CryptoKey.js into the SubtleTests harness
ljoy913 Jun 25, 2026
7781f7c
Document why QUnit 1.23.1 is vendored and pinned
ljoy913 Jun 25, 2026
e3dbdc4
Release 1.7.0: WebCrypto parity and tooling
ljoy913 Jun 25, 2026
6eb5c56
Build dist for 1.7.0
ljoy913 Jun 25, 2026
dfefae1
Rename tests/ to test/
ljoy913 Jun 25, 2026
043cd08
Remove dead code and clarify JWK byte serializer name
ljoy913 Jun 25, 2026
1e9eabf
Remove dead wrapKey module
ljoy913 Jun 25, 2026
9afa965
Honor requested key usages in RSA generateKey
ljoy913 Jun 25, 2026
a0a1cb7
Add Stop button to Subtle test harness
ljoy913 Jun 25, 2026
34ed498
Improve IE8 compatibility and expand test coverage
ljoy913 Jun 26, 2026
3bce2b1
Harden worker dispatch and fix ReDoS; build/CI cleanup
ljoy913 Jun 26, 2026
f54ec57
Preserve error name across web worker boundary so rejections keep DOM…
ljoy913 Jun 26, 2026
9ba6b90
Guard worker onmessage against missing data payload
ljoy913 Jun 26, 2026
2b44488
Convert subtle public API docs to JSDoc and rename CryptoKey params
ljoy913 Jun 26, 2026
f4f5b68
Consolidate 1.7.0 changelog, add breaking-changes/build notes, bump e…
ljoy913 Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Publishes @microsoft/msrcrypto to npm.
#
# Dormant until you cut a release: it runs only when a GitHub Release is
# published or a v* tag is pushed. It builds, verifies the package contents,
# then publishes with npm provenance (supply-chain attestation).
#
# Note: the QUnit suite (test/SubtleTests.html) is a manual, real-browser
# harness (it targets IE8+ behavior) and is intentionally not run here.
#
# Prerequisites (one-time, when you are ready to publish):
# - Add an npm automation token as the repository secret NPM_TOKEN, OR
# configure npm Trusted Publishing (OIDC) and drop the NODE_AUTH_TOKEN env.
# - The `id-token: write` permission below is required for --provenance.
name: Publish

on:
release:
types: [published]
push:
tags:
- "v*"

permissions:
contents: read
id-token: write # required for npm --provenance

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 22
registry-url: https://registry.npmjs.org

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build

- name: Verify package contents
run: npm pack --dry-run

- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# npm packages loaded on user's system
# Installed dependencies
node_modules/

# This gets re-built by gulp with each build.
scripts/subtle.js
# OS / editor artifacts
.DS_Store

/.history
/.DS_Store
# Local test comparison page
test/hmac-export-compare.html
14 changes: 0 additions & 14 deletions .vscode/settings.json

This file was deleted.

21 changes: 0 additions & 21 deletions .vscode/tasks.json

This file was deleted.

125 changes: 125 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.7.0] - 2026-06-26

### Breaking Changes

- Errors for invalid input and unsupported algorithms are now delivered as a
rejected promise instead of being thrown synchronously. Code relying on a
synchronous `try`/`catch` around `SubtleCrypto` calls must move to
`.catch()`/`await`.
- Error objects changed shape: failures are now `DOMException`s with
specification names (e.g. `OperationError`, `DataError`) rather than plain
`Error`s. Code inspecting `error.message` or custom error fields may need to
switch to `error.name`.
- `getRandomValues` now throws `QuotaExceededError` for requests larger than
65,536 bytes and `TypeMismatchError` for floating-point typed arrays, where
previously such calls may have succeeded.
- `generateKey` validation is stricter: AES rejects key lengths other than 128,
192, or 256 bits, and HMAC interprets `length` as bits. Inputs accepted by
earlier versions may now be rejected.
- Built output moved from `lib/` to `dist/` and type declarations from
`definitions/` to `types/`. Imports by package name are unaffected, but deep
paths such as `@microsoft/msrcrypto/lib/...` must be updated.
- The minimum supported Node.js version is now 18.

### Added

- TypeScript declarations ([`types/msrCrypto.d.ts`](types/msrCrypto.d.ts)) were
rewritten to describe the library's own `MsrCrypto` surface and to resolve for
the `@microsoft/msrcrypto` import specifier (via `export =`).
- An `Errors` test module that asserts the public APIs reject/throw with the
correct error names, plus the previously-unwired `CryptoKey` test module.
- npm package metadata (`keywords`, `author`, `homepage`, `bugs`, `exports`,
`sideEffects`, `publishConfig`) and a `prepublishOnly` build guard.
- Dormant GitHub Actions release workflow that builds, verifies the package,
and publishes to npm with provenance on tagged releases.

### Changed

- `SubtleCrypto` algorithm parameters now accept a string `AlgorithmIdentifier`
(e.g. `"SHA-256"`) in addition to an object, matching the W3C Web Crypto spec.
- `SubtleCrypto` methods now surface invalid input and unsupported algorithms as
a rejected promise instead of throwing synchronously, per the Web Crypto
contract. Missing or wrong-type arguments reject with a `TypeError`.
- Errors raised by the library are now `DOMException`s with specification names
(`NotSupportedError`, `OperationError`, `InvalidAccessError`, `DataError`),
falling back to an `Error` carrying the name and legacy code on engines
without a `DOMException` constructor (e.g. IE8).
- `getRandomValues` now throws `QuotaExceededError` for requests larger than
65,536 bytes and `TypeMismatchError` for floating-point typed arrays.
- The library version is now injected into the bundle from `package.json` at
build time, eliminating version drift between the package and the bundle.
- The build system was migrated to [esbuild](https://esbuild.github.io/) (driven
by `build.mjs`), producing the unminified and minified bundles, and the
minimum supported Node.js version was raised to 18.
- Repository layout: built output moved from `lib/` to `dist/`, type
declarations from `definitions/` to `types/`, and sources under `src/`. The
published `main`/`types` paths are resolved through `package.json`, so
installs via the package name are unaffected; only deep paths such as
`@microsoft/msrcrypto/lib/...` changed.

### Fixed

- HMAC `generateKey` now honors the optional `length` parameter correctly (bits,
not bytes) and zeroes the unused trailing bits of the final byte for
non-byte-aligned lengths, matching native Web Crypto behavior.
- AES `generateKey` (CBC, GCM, KW) now rejects key lengths other than 128, 192,
or 256 bits instead of accepting any multiple of 8.
- Removed a stray `console.log` that leaked exported key material during
`wrapKey`.
- Fixed an error in the worker result path that threw when assigning to the
read-only `DOMException.code` property.
- `SubtleCrypto.generateKey` for RSA algorithms now honors the requested key
usages (routing each usage to the public or private key it applies to)
instead of forcing a fixed pair. Generating an `RSA-OAEP` key with
`["wrapKey", "unwrapKey"]` now yields keys usable with `wrapKey`/`unwrapKey`.

### Removed

- Dead, unreachable `wrapKey.js` module (legacy JWE-style key wrapping that was
never dispatched) and its orphaned JWK byte-serializer helper. The public
`wrapKey`/`unwrapKey` continue to work via the standard
export-then-encrypt / decrypt-then-import path.

## [1.6.0]

- Automatic web-worker usage is disabled by default. When enabled, it may cause
problems when the library is bundled with other scripts.
- `raw` key import support for HMAC & ECDH.
- `spki` public key import for RSA.
- `wrapKey` support for AES-CBC, AES-GCM, RSA-OAEP.
- PBKDF2 key derivation algorithm.
- Additional side-channel protection.
- Moved source to GitHub.

## [1.5.0]

- Added support for streaming input/output data to crypto calls.
- Allow concurrent crypto calls of the same type at the same time.
- Added `raw` keyImport/keyExport format for HMAC, AES-CBC, AES-GCM.
- Added `IE11PromiseWrapper.js` to wrap the IE11 non-standard Web Crypto API so
it behaves like the current standard Promise-based API.
- Removed RSASSA-PKCS1-v1_5 encrypt/decrypt algorithm (obsolete, no longer
supported by modern browsers).
- Added TypeScript definitions (`msrCrypto.d.ts`).
- Moved the Promise polyfill outside of the library so the built-in browser
version can be used when available.

## [1.4.0]

- Updated the API to the latest Web Crypto API spec and modern browser
implementations.
- Promises are now supported; the IE11-style event callbacks were removed. This
is a breaking change for code using the pre-1.4 `onComplete`/`onError`
calling conventions.

[1.7.0]: https://github.com/microsoft/MSR-JavaScript-Crypto/releases/tag/v1.7.0
[1.6.0]: https://github.com/microsoft/MSR-JavaScript-Crypto/releases/tag/v1.6.0
[1.5.0]: https://github.com/microsoft/MSR-JavaScript-Crypto/releases/tag/v1.5.0
[1.4.0]: https://github.com/microsoft/MSR-JavaScript-Crypto/releases/tag/v1.4.0
109 changes: 24 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,24 @@ var crypto = window.crypto /*native*/ || window.msCrypto /*IE11 native*/ || win
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`](https://github.com/panva/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:
```javascript
// 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 [`/lib/msrCrypto.js`](https://github.com/microsoft/MSR-JavaScript-Crypto/blob/master/lib/msrcrypto.js)
Minified library [`/lib/msrCrypto.min.js`](https://github.com/microsoft/MSR-JavaScript-Crypto/blob/master/lib/msrcrypto.min.js)
Full library [`/dist/msrcrypto.js`](https://github.com/microsoft/MSR-JavaScript-Crypto/blob/master/dist/msrcrypto.js)
Minified library [`/dist/msrcrypto.min.js`](https://github.com/microsoft/MSR-JavaScript-Crypto/blob/master/dist/msrcrypto.min.js)


## Supported Algorithms
Expand Down Expand Up @@ -64,8 +78,8 @@ Supported ECC curves:

>_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 [gulp](https://gulpjs.com/) from npm to concatenate many individual JavaScript files into a single library file.
Run `npm install` from a command terminal to install the required _npm_ packages. `gulpfile.js` contains a list of 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.
You may build the library from the source files. The library is built using [esbuild](https://esbuild.github.io/) 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](https://git-scm.com/downloads), [Node.js](https://nodejs.org/en/), and [Visual Studio Code](https://code.visualstudio.com/) are installed on your system._
Expand All @@ -78,15 +92,15 @@ Run `npm install` from a command terminal to install the required _npm_ packages
>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 `lib` directory as `msrCrypto.js` and `msrCrypto.min.js`.
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](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/en/) 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](https://nodejs.org/en/) modules to the project's `node_modules` folder.
4. `node_modules\.bin\gulp` to build the library files.
5. The newly built library files will appear in the `lib` directory as `msrCrypto.js` and `msrCrypto.min.js`.
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
Expand Down Expand Up @@ -137,7 +151,7 @@ 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 `/lib` 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.
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):

Expand All @@ -163,84 +177,9 @@ A good source for documentation is:

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

## Updates

#### Changes with version 1.6

Automatic web-worker usage is disabled by default.
When enabled, it may cause problems when the library is bundled with other scripts.

raw key import support for HMAC & ECDH.

spki public key import for RSA.

wrapKey support for AES-CBC, AES-GCM, RSA-OAEP.

PBKDF2 key derivation algorithm.

Includes additional side-channel protection.

Moved source to GitHub.

#### Changes with version 1.5

Added support for streaming input/output data to crypto calls.
See Samples/StreamSample.html for an example on how to use this feature.

Now allow concurrent crypto calls of the same type at the same time. Before, concurrent
crypto operations that shared code would possibly return incorrect results.
Now, for example, you could perform multiple encryptions at the same time with streaming.
## Changelog

Added 'raw' keyImport/keyExport format for hmac, AES-CBC, AES-GCM.

Added IE11PromiseWrapper.js script to wrap the IE11 non-standard WebCrypto api and make
it function the same as current standard WebCrypto api. Your WebCrypto code should now
work with msrCrypto, IE11-WebCrypto, and the current standard WebCrypto with minimal
special case code.

Removed RSASSA-PKCS1-v1_5 encrypt/decrypt algorithm. (considered less secure and obsolete)
It is no longer supported by WebCrypto in modern browsers.

Added TypeScript d.ts file. msrCrypto.d.ts for using with type script.

Moved the Promise polyfill outside of the msrCrypto library so you can use the built-in
browser version when available.

#### Changes with version 1.4

The API has been updated to support the latest Web Crypto API spec and be compatible with the
implementation on the latest browsers.

Promises are now supported and the IE11 based events are removed. Crypto calls are now in the
form:

```javascript
// NEW STYLE with Promises
msrCrypto.subtle.encrypt(<parameters>).then(
function(encryptionResult) {
//... do something here with the result
},
function(error) {
//... handle error
}
);
```

This will break code that uses the pre-1.4 calling conventions:
```javascript
// OLD STYLE with events (before version 1.4)
var cryptoOperation = msrCrypto.subtle.encrypt(<parameters>);

cryptoOperation.onComplete =
function(encryptionResult) {
//... do something here with the result
};

cryptoOperation.onError =
function(encryptionResult) {
//... handle error
};
```
See [CHANGELOG.md](CHANGELOG.md) for the history of notable changes across versions.

## Contributing

Expand Down
Loading
Loading