diff options
author | vnugent <public@vaughnnugent.com> | 2024-01-01 10:56:02 -0500 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2024-01-01 10:56:02 -0500 |
commit | 1a82a909c5c4d0262d69a8a543e902ff6533a4b2 (patch) | |
tree | 7a0a296ae09209f5214e42917a46ad90f22c38d9 /lib/vnlib.browser/src/webcrypto.ts | |
parent | 35a5763d675a68ec5e36e05584481b49e1c41ce0 (diff) |
swallow vnlib.browser
Diffstat (limited to 'lib/vnlib.browser/src/webcrypto.ts')
-rw-r--r-- | lib/vnlib.browser/src/webcrypto.ts | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/vnlib.browser/src/webcrypto.ts b/lib/vnlib.browser/src/webcrypto.ts new file mode 100644 index 0000000..d2c7640 --- /dev/null +++ b/lib/vnlib.browser/src/webcrypto.ts @@ -0,0 +1,97 @@ +// Copyright (c) 2023 Vaughn Nugent +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import { isArrayBuffer, isPlainObject, isString } from 'lodash-es'; +import { ArrayBuffToBase64, Base64ToUint8Array, ArrayToHexString } from './binhelpers'; + +const crypto = window?.crypto?.subtle || {}; + +/** + * Signs the dataBuffer using the specified key and hmac algorithm by its name eg. 'SHA-256' + * @param {ArrayBuffer | String} dataBuffer The data to sign, either as an ArrayBuffer or a base64 string + * @param {ArrayBuffer | String} keyBuffer The raw key buffer, or a base64 encoded string + * @param {String} alg The name of the hmac algorithm to use eg. 'SHA-256' + * @param {String} [toBase64 = false] The output format, the array buffer data, or true for base64 string + * @returns {Promise<ArrayBuffer | String>} The signature as an ArrayBuffer or a base64 string + */ +export const hmacSignAsync = async (keyBuffer: ArrayBuffer | string, dataBuffer: ArrayBuffer | string, alg : string, toBase64 = false) +: Promise<ArrayBuffer | string> => { + // Check key argument type + const rawKeyBuffer = isString(keyBuffer) ? Base64ToUint8Array(keyBuffer as string) : keyBuffer as ArrayBuffer; + + // Check data argument type + const rawDataBuffer = isString(dataBuffer) ? Base64ToUint8Array(dataBuffer as string) : dataBuffer as ArrayBuffer; + + // Get the key + const hmacKey = await crypto.importKey('raw', rawKeyBuffer, { name: 'HMAC', hash: alg }, false, ['sign']); + + // Sign hmac data + const digest = await crypto.sign('HMAC', hmacKey, rawDataBuffer); + + // Encode to base64 if needed + return toBase64 ? ArrayBuffToBase64(digest) : digest; +} +/** + * @function decryptAsync Decrypts syncrhonous or asyncrhonsous en encypted data + * asynchronously. + * @param {any} data The encrypted data to decrypt. (base64 string or ArrayBuffer) + * @param {any} privKey The key to use for decryption (base64 String or ArrayBuffer). + * @param {Object} algorithm The algorithm object to use for decryption. + * @param {Boolean} toBase64 If true, the decrypted data will be returned as a base64 string. + * @returns {Promise} The decrypted data. + */ +export const decryptAsync = async ( + algorithm: AlgorithmIdentifier, + privKey: BufferSource | CryptoKey | JsonWebKey, + data: string | ArrayBuffer, + toBase64 = false): Promise<string | ArrayBuffer> => +{ + // Check data argument type and decode if needed + const dataBuffer = isString(data) ? Base64ToUint8Array(data as string) : data as ArrayBuffer; + + let privateKey = privKey + // Check key argument type + if (privKey instanceof CryptoKey) { + privateKey = privKey + } + // If key is binary data, then import it as raw data + else if (isArrayBuffer(privKey)) { + privateKey = await crypto.importKey('raw', privKey, algorithm, true, ['decrypt']) + } + // If the key is an object, then import it as a jwk + else if (isPlainObject(privKey)) { + privateKey = await crypto.importKey('jwk', privKey as JsonWebKey, algorithm, true, ['decrypt']) + } + + // Decrypt the data and return it + const decrypted = await crypto.decrypt(algorithm, privateKey as CryptoKey, dataBuffer) + return toBase64 ? ArrayBuffToBase64(decrypted) : decrypted +} + +export const getRandomHex = (size: number) : string => { + // generate a new random secret and store it + const randBuffer = new Uint8Array(size) + // generate random id directly on the window.crypto object + window.crypto.getRandomValues(randBuffer) + // Store the id in the session as hex + return ArrayToHexString(randBuffer) +} + +//default export subtle crypto +export default crypto;
\ No newline at end of file |