diff options
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | packages/iso-webcrypto/.npmignore | 7 | ||||
-rw-r--r-- | packages/iso-webcrypto/README.md | 24 | ||||
-rw-r--r-- | packages/iso-webcrypto/package.json | 40 | ||||
-rwxr-xr-x | packages/iso-webcrypto/src/browser.ts | 12 | ||||
-rw-r--r-- | packages/iso-webcrypto/src/node.ts | 13 | ||||
-rw-r--r-- | packages/iso-webcrypto/src/types.ts | 194 | ||||
-rw-r--r-- | packages/iso-webcrypto/tsconfig.json | 8 |
8 files changed, 299 insertions, 0 deletions
diff --git a/package.json b/package.json index e581db6..6e74f4c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "docs": "npm run bootstrap:ci && typedoc --tsconfig tsconfigdoc.json", "test": "lerna run test", "build:types": "lerna run build --scope=@simplewebauthn/typescript-types", + "build:iso-webcrypto": "lerna run compile --scope=@simplewebauthn/iso-webcrypto", "build:browser": "lerna run build --scope=@simplewebauthn/browser", "build:server": "lerna run build --scope=@simplewebauthn/server", "dev:server": "lerna exec npm run test:watch --scope=@simplewebauthn/server", diff --git a/packages/iso-webcrypto/.npmignore b/packages/iso-webcrypto/.npmignore new file mode 100644 index 0000000..d2360e9 --- /dev/null +++ b/packages/iso-webcrypto/.npmignore @@ -0,0 +1,7 @@ +src +node_modules +coverage +.gitignore +tsconfig.json +*.config.js +__mocks__ diff --git a/packages/iso-webcrypto/README.md b/packages/iso-webcrypto/README.md new file mode 100644 index 0000000..3d1c10c --- /dev/null +++ b/packages/iso-webcrypto/README.md @@ -0,0 +1,24 @@ +# @simplewebauthn/iso-webcrypto + + +[](https://www.npmjs.com/package/@simplewebauthn/iso-webcrypto) + +A small library for accessing a runtime's WebCrypto API. Supports browsers, and Node projects using ESM and/or CommonJS. + +## Install + +```sh +npm install --save @simplewebauthn/iso-webcrypto +``` + +## Usage + +```ts +import WebCrypto from '@simplewebauthn/iso-webcrypto'; + +WebCrypto.randomUUID (); // => '43e16416-7a2a-4c00-b2e8-1ea7a57adfb9' +``` + +## Acknowledgements + +Thank you to Fabio Spampinato and their [tiny-webcrypto](https://github.com/fabiospampinato/tiny-webcrypto) project that all but solves the issue of isomorphic WebCrypto use across browsers and Node. I forked that project and made this one to add in support for Node libraries written in TypeScript that transpile to CommonJS modules. diff --git a/packages/iso-webcrypto/package.json b/packages/iso-webcrypto/package.json new file mode 100644 index 0000000..75ac048 --- /dev/null +++ b/packages/iso-webcrypto/package.json @@ -0,0 +1,40 @@ +{ + "name": "@simplewebauthn/iso-webcrypto", + "version": "6.2.1", + "description": "A small library for accessing a runtime's WebCrypto API", + "main": "dist/node.js", + "types": "./dist/node.d.ts", + "exports": { + "node": "./dist/node.js", + "default": "./dist/browser.js" + }, + "author": "Matthew Miller <matthew@millerti.me>", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/MasterKale/SimpleWebAuthn.git", + "directory": "packages/iso-webcrypto" + }, + "homepage": "https://github.com/MasterKale/SimpleWebAuthn/tree/master/packages/iso-webcrypto#readme", + "publishConfig": { + "access": "public" + }, + "scripts": { + "build": "tsex compile", + "build:watch": "tsex compile --watch", + "prepublish": "npm run build" + }, + "keywords": [ + "typescript", + "isomorphic", + "webcrypto", + "browser", + "node" + ], + "devDependencies": { + "@simplewebauthn/typescript-types": "*", + "@types/node": "^18.11.9", + "tsex": "^1.0.4", + "typescript": "^4.9.3" + } +} diff --git a/packages/iso-webcrypto/src/browser.ts b/packages/iso-webcrypto/src/browser.ts new file mode 100755 index 0000000..ebd01a5 --- /dev/null +++ b/packages/iso-webcrypto/src/browser.ts @@ -0,0 +1,12 @@ + +/* IMPORT */ + +import type {Crypto} from './types'; + +/* MAIN */ + +const WebCrypto: Crypto = crypto; + +/* EXPORT */ + +export default WebCrypto; diff --git a/packages/iso-webcrypto/src/node.ts b/packages/iso-webcrypto/src/node.ts new file mode 100644 index 0000000..0887ebc --- /dev/null +++ b/packages/iso-webcrypto/src/node.ts @@ -0,0 +1,13 @@ + +/* IMPORT */ + +import crypto from 'node:crypto'; +import type {Crypto} from './types'; + +/* MAIN */ + +const WebCrypto = crypto.webcrypto as unknown as Crypto; //TSC + +/* EXPORT */ + +export default WebCrypto; diff --git a/packages/iso-webcrypto/src/types.ts b/packages/iso-webcrypto/src/types.ts new file mode 100644 index 0000000..adc4f13 --- /dev/null +++ b/packages/iso-webcrypto/src/types.ts @@ -0,0 +1,194 @@ + +// The following as been basically copy/pasted from lib.dom.d.ts + +/* HELPERS */ + +type AlgorithmIdentifier = Algorithm | string; +type BufferSource = ArrayBufferView | ArrayBuffer; +type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki"; +type KeyType = "private" | "public" | "secret"; +type KeyUsage = "decrypt" | "deriveBits" | "deriveKey" | "encrypt" | "sign" | "unwrapKey" | "verify" | "wrapKey"; +type HashAlgorithmIdentifier = AlgorithmIdentifier; +type NamedCurve = string; + +interface Algorithm { + name: string; +} + +interface AesCbcParams extends Algorithm { + iv: BufferSource; +} + +interface AesCtrParams extends Algorithm { + counter: BufferSource; + length: number; +} + +interface AesDerivedKeyParams extends Algorithm { + length: number; +} + +interface AesGcmParams extends Algorithm { + additionalData?: BufferSource; + iv: BufferSource; + tagLength?: number; +} + +interface AesKeyGenParams extends Algorithm { + length: number; +} + +interface EcKeyGenParams extends Algorithm { + namedCurve: NamedCurve; +} + +interface EcKeyImportParams extends Algorithm { + namedCurve: NamedCurve; +} + +interface EcdhKeyDeriveParams extends Algorithm { + public: CryptoKey; +} + +interface EcdsaParams extends Algorithm { + hash: HashAlgorithmIdentifier; +} + +interface HkdfParams extends Algorithm { + hash: HashAlgorithmIdentifier; + info: BufferSource; + salt: BufferSource; +} + +interface HmacKeyGenParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; +} + +interface HmacImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; +} + +interface Pbkdf2Params extends Algorithm { + hash: HashAlgorithmIdentifier; + iterations: number; + salt: BufferSource; +} + +interface RsaHashedImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; +} + +interface RsaKeyGenParams extends Algorithm { + modulusLength: number; + publicExponent: Uint8Array; +} + +interface RsaOaepParams extends Algorithm { + label?: BufferSource; +} + +interface RsaPssParams extends Algorithm { + saltLength: number; +} + +interface KeyAlgorithm { + name: string; +} + +interface AesKeyAlgorithm extends KeyAlgorithm { + length: number; +} + +// interface EcKeyAlgorithm extends KeyAlgorithm { +// namedCurve: NamedCurve; +// } + +// interface HmacKeyAlgorithm extends KeyAlgorithm { +// hash: KeyAlgorithm; +// length: number; +// } + +// interface RsaKeyAlgorithm extends KeyAlgorithm { +// modulusLength: number; +// publicExponent: Uint8Array; +// } + +// interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm { +// hash: KeyAlgorithm; +// } + +interface RsaHashedKeyGenParams extends RsaKeyGenParams { + hash: HashAlgorithmIdentifier; +} + +interface CryptoKey { + readonly algorithm: KeyAlgorithm; + readonly extractable: boolean; + readonly type: KeyType; + readonly usages: KeyUsage[]; +} + +interface CryptoKeyPair { + privateKey: CryptoKey; + publicKey: CryptoKey; +} + +interface JsonWebKey { + alg?: string; + crv?: string; + d?: string; + dp?: string; + dq?: string; + e?: string; + ext?: boolean; + k?: string; + key_ops?: string[]; + kty?: string; + n?: string; + oth?: RsaOtherPrimesInfo[]; + p?: string; + q?: string; + qi?: string; + use?: string; + x?: string; + y?: string; +} + +interface RsaOtherPrimesInfo { + d?: string; + r?: string; + t?: string; +} + +interface SubtleCrypto { + decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>; + deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; + digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise<ArrayBuffer>; + encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>; + exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>; + generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair>; + generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; + generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair | CryptoKey>; + importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; + importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; + sign(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>; + unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; + verify(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, signature: BufferSource, data: BufferSource): Promise<boolean>; + wrapKey(format: KeyFormat, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams): Promise<ArrayBuffer>; +} + +/* MAIN */ + +interface Crypto { + readonly subtle: SubtleCrypto; + getRandomValues<T extends ArrayBufferView | null>(array: T): T; + randomUUID(): string; +} + +/* EXPORT */ + +export type {Crypto}; diff --git a/packages/iso-webcrypto/tsconfig.json b/packages/iso-webcrypto/tsconfig.json new file mode 100644 index 0000000..c4c12d3 --- /dev/null +++ b/packages/iso-webcrypto/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "tsex/tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "preserveValueImports": false, + } +} |