Socket
Socket
Sign inDemoInstall

@privy-io/crypto

Package Overview
Dependencies
0
Maintainers
4
Versions
5
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.1 to 0.0.2

dist/webcrypto.d.ts

11

dist/buffers.d.ts

@@ -1,5 +0,8 @@

/// <reference types="node" />
export declare const concatBuffers: (...inBuffers: ArrayBufferView[]) => Buffer;
export declare const bufferFromUInt64: (uint64Value: number) => Buffer;
export declare const uint64FromBuffer: (inputBuffer: Buffer, startOffset: number) => [number, number];
export declare const concatBuffers: (...inBuffers: ArrayBufferView[]) => Uint8Array;
export declare const bufferFromUInt64: (uint64Value: number) => Uint8Array;
export declare const uint64FromBuffer: (input: Uint8Array, startOffset: number) => [number, number];
/**
* Checks whether the two Uint8Arrays contain the same data. (same length and same bytes)
*/
export declare const buffersEqual: (a: Uint8Array, b: Uint8Array) => boolean;
//# sourceMappingURL=buffers.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uint64FromBuffer = exports.bufferFromUInt64 = exports.concatBuffers = void 0;
exports.buffersEqual = exports.uint64FromBuffer = exports.bufferFromUInt64 = exports.concatBuffers = void 0;
// Concatenate Buffers (compatible with TypedArrays and DataViews)

@@ -26,3 +26,3 @@ var concatBuffers = function () {

});
return Buffer.from(concatBuf);
return concatBuf;
};

@@ -41,3 +41,3 @@ exports.concatBuffers = concatBuffers;

uint64DataView.setBigUint64(0, BigInt(uint64Value), false); // Big endian.
return Buffer.from(uint64DataView.buffer);
return new Uint8Array(uint64Buf);
};

@@ -47,6 +47,6 @@ exports.bufferFromUInt64 = bufferFromUInt64;

// Returns the (uint64Value, endOffset) as a tuple.
var uint64FromBuffer = function (inputBuffer, startOffset) {
var uint64FromBuffer = function (input, startOffset) {
// Create a new buffer containing a copy of the bytes to read.
var endOffset = startOffset + UINT64_SIZE_BYTES;
var uint64Buf = inputBuffer.slice(startOffset, endOffset);
var uint64Buf = input.slice(startOffset, endOffset);
var uint64DataView = new DataView(uint64Buf.buffer, uint64Buf.byteOffset, UINT64_SIZE_BYTES);

@@ -59,2 +59,9 @@ // Read the integer from the buffer in big-endian because that is the format used to write it.

exports.uint64FromBuffer = uint64FromBuffer;
/**
* Checks whether the two Uint8Arrays contain the same data. (same length and same bytes)
*/
var buffersEqual = function (a, b) {
return a.byteLength === b.byteLength && a.every(function (byte, i) { return byte === b[i]; });
};
exports.buffersEqual = buffersEqual;
//# sourceMappingURL=buffers.js.map

@@ -1,33 +0,70 @@

/// <reference types="node" />
/**
* Utility function to create md5 hashes of data.
* Useful for hashing encrypted file contents when
* uploading to the cloud for integrity checks.
* The following key, nonce, and IV constants
* refer to NIST-recommended lengths.
*/
export declare const IV_LENGTH_12_BYTES = 12;
export declare const COMMITMENT_NONCE_LENGTH_32_BYTES = 32;
export declare const AUTH_TAG_LENGTH_16_BYTES = 16;
/**
* Cryptographically-secure pseudo-random number generator.
*
* @param {Buffer} data - Data to hash
* @returns {string} Hex representation of md5 hash
* @param {number} byteLength the number of random bytes to return
* @returns {Uint8Array} random bytes as Uint8Array
*/
export declare function md5Hash(data: Buffer): string;
export declare function csprng(lengthInBytes: number): Buffer;
interface AESEncryptConfig {
ivLengthInBytes: number;
authTagLengthInBytes: number;
}
export declare function aes256gcmEncrypt(plaintext: Buffer, dataKey: Buffer, config: AESEncryptConfig): {
ciphertext: Buffer;
initializationVector: Buffer;
authenticationTag: any;
};
export declare function aes256gcmDecrypt(ciphertext: Buffer, dataKey: Buffer, initializationVector: Buffer, authenticationTag: Buffer): Buffer;
export declare function csprng(byteLength: number): Uint8Array;
/**
* This is only used to encrypt the AES secret key so that
* the only way to decrypt it is with the RSA private key.
* The RSA private key is stored in an HSM and is thus never
* exposed to the Privy server or any clients.
* Generates a new 256 bit key for AES-GCM encryption.
*
* The next iteration of Privy's crypto code will be using ECC
* and thus moving away from the less secure RSA+SHA1.
* @returns {Promise<CryptoKey>} promise resolving to a CryptoKey
*/
export declare function rsaOaepSha1Encrypt(plaintext: Buffer, publicKey: Buffer): Buffer;
export {};
export declare function generateAESGCMEncryptionKey(): Promise<CryptoKey>;
/**
* Imports a 256 bit key for AES-GCM decryption.
*
* @param {BufferSource} key Uint8Array of the AES key
* @returns {Promise<CryptoKey>} promise resolving to the imported CryptoKey
*/
export declare function importAESGCMDecryptionKey(key: BufferSource): Promise<CryptoKey>;
/**
* Imports a 2048 bit public key in DER format for AES-GCM decryption.
*
* @param {BufferSource} key Uint8Array of the RSA public key in DER format
* @returns {Promise<CryptoKey>} promise resolving to the imported CryptoKey
*/
export declare function importRSAOAEPEncryptionKey(key: BufferSource): Promise<CryptoKey>;
/**
* Performs AES-GCM encryption on the given plaintext
* using the given initialization vector and key.
*
* @param {BufferSource} pt the plaintext data to encrypt
* @param {BufferSource} iv the initialization vector
* @param {CryptoKey} key the secret encryption key
* @returns {Promise<Uint8Array>} promise resolving to the encrypted bytes
*/
export declare function aesGCMEncrypt(pt: BufferSource, iv: BufferSource, key: CryptoKey): Promise<Uint8Array>;
/**
* Performs AES-GCM decryption on the given ciphertext
* using the given initialization vector and key.
*
* @param {BufferSource} ct the ciphertext data to decrypt
* @param {BufferSource} iv the initialization vector
* @param {CryptoKey} key the secret encryption key
* @returns {Promise<Uint8Array>} promise resolving to the decrypted bytes
*/
export declare function aesGCMDecrypt(ct: BufferSource, iv: BufferSource, key: CryptoKey): Promise<Uint8Array>;
/**
* Performs RSA-OAEP encryption of key with a wrapping key (i.e., RSA public key).
*
* @param {CryptoKey} key key to encrypt
* @param {CryptoKey} wrappingKey RSA public key to use for encrypting key
* @returns {Promise<Uint8Array>} promise resolving to the encrypted bytes
*/
export declare function rsaOaepWrapKey(key: CryptoKey, wrappingKey: CryptoKey): Promise<Uint8Array>;
/**
* Hashes data using SHA256.
*
* @param {BufferSource} data data to hash
* @returns {Promise<Uint8Array>} promise resolving to hashed bytes
*/
export declare function sha256(data: BufferSource): Promise<Uint8Array>;
//# sourceMappingURL=crypto.d.ts.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.rsaOaepSha1Encrypt = exports.aes256gcmDecrypt = exports.aes256gcmEncrypt = exports.csprng = exports.md5Hash = void 0;
var webcrypto = __importStar(require("webcrypto"));
var AES_256_GCM = 'aes-256-gcm';
var SHA1 = 'sha1';
exports.sha256 = exports.rsaOaepWrapKey = exports.aesGCMDecrypt = exports.aesGCMEncrypt = exports.importRSAOAEPEncryptionKey = exports.importAESGCMDecryptionKey = exports.generateAESGCMEncryptionKey = exports.csprng = exports.AUTH_TAG_LENGTH_16_BYTES = exports.COMMITMENT_NONCE_LENGTH_32_BYTES = exports.IV_LENGTH_12_BYTES = void 0;
var errors_1 = require("./errors");
var webcrypto_1 = require("./webcrypto");
/**
* Utility function to create md5 hashes of data.
* Useful for hashing encrypted file contents when
* uploading to the cloud for integrity checks.
* The following key, nonce, and IV constants
* refer to NIST-recommended lengths.
*/
// Used for serialization / deserialization logic.
exports.IV_LENGTH_12_BYTES = 12;
exports.COMMITMENT_NONCE_LENGTH_32_BYTES = 32;
exports.AUTH_TAG_LENGTH_16_BYTES = 16;
// https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
var RAW_FORMAT = 'raw';
var SPKI_FORMAT = 'spki';
var EXTRACTABLE = true;
var NOT_EXTRACTABLE = false;
var ENCRYPT_ONLY = ['encrypt'];
var DECRYPT_ONLY = ['decrypt'];
var WRAP_KEY_ONLY = ['wrapKey'];
// https://developer.mozilla.org/en-US/docs/Web/API/AesKeyGenParams
// https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams
var AES_GCM = 'AES-GCM';
var AES_KEY_LENGTH_32_BYTES = 32;
var AES_KEY_LENGTH_256_BITS = AES_KEY_LENGTH_32_BYTES * 8;
var AUTH_TAG_LENGTH_128_BITS = exports.AUTH_TAG_LENGTH_16_BYTES * 8;
// https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
var RSA_OAEP = 'RSA-OAEP';
var RSA_OAEP_ALGORITHM = Object.freeze({
name: RSA_OAEP,
hash: 'SHA-1',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
});
// https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams
function aesGCMParams(iv) {
return {
iv: iv,
name: AES_GCM,
tagLength: AUTH_TAG_LENGTH_128_BITS,
};
}
/**
* Cryptographically-secure pseudo-random number generator.
*
* @param {Buffer} data - Data to hash
* @returns {string} Hex representation of md5 hash
* @param {number} byteLength the number of random bytes to return
* @returns {Uint8Array} random bytes as Uint8Array
*/
function md5Hash(data) {
return webcrypto.createHash('md5').update(data).digest('hex');
function csprng(byteLength) {
return webcrypto_1.crypto.getRandomValues(new Uint8Array(byteLength));
}
exports.md5Hash = md5Hash;
function csprng(lengthInBytes) {
// In node, this will be crypto.randomBytes, which is a CSPRNG.
//
// https://nodejs.org/api/crypto.html#cryptorandombytessize-callback
//
// In the browser, this will be crypto.getRandomValues, which
// MDN recommends against using to generate keys, preferring
// instead to use SubtleCrypto.generateKey.
//
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
//
return webcrypto.randomBytes(lengthInBytes);
}
exports.csprng = csprng;
function aes256gcmEncrypt(plaintext, dataKey, config) {
var initializationVector = csprng(config.ivLengthInBytes);
var cipher = webcrypto.createCipheriv(AES_256_GCM, dataKey, initializationVector);
var ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
var authenticationTag = cipher.getAuthTag();
return { ciphertext: ciphertext, initializationVector: initializationVector, authenticationTag: authenticationTag };
/**
* Generates a new 256 bit key for AES-GCM encryption.
*
* @returns {Promise<CryptoKey>} promise resolving to a CryptoKey
*/
function generateAESGCMEncryptionKey() {
return webcrypto_1.crypto.subtle.generateKey({
name: AES_GCM,
length: AES_KEY_LENGTH_256_BITS,
}, EXTRACTABLE, ENCRYPT_ONLY);
}
exports.aes256gcmEncrypt = aes256gcmEncrypt;
function aes256gcmDecrypt(ciphertext, dataKey, initializationVector, authenticationTag) {
var decipher = webcrypto.createDecipheriv(AES_256_GCM, dataKey, initializationVector);
decipher.setAuthTag(authenticationTag);
return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
exports.generateAESGCMEncryptionKey = generateAESGCMEncryptionKey;
/**
* Imports a 256 bit key for AES-GCM decryption.
*
* @param {BufferSource} key Uint8Array of the AES key
* @returns {Promise<CryptoKey>} promise resolving to the imported CryptoKey
*/
function importAESGCMDecryptionKey(key) {
if (key.byteLength !== AES_KEY_LENGTH_32_BYTES) {
throw new errors_1.CryptoError("key must be 32 bytes but was ".concat(key.byteLength, " bytes"));
}
return webcrypto_1.crypto.subtle.importKey(RAW_FORMAT, key, AES_GCM, NOT_EXTRACTABLE, DECRYPT_ONLY);
}
exports.aes256gcmDecrypt = aes256gcmDecrypt;
exports.importAESGCMDecryptionKey = importAESGCMDecryptionKey;
/**
* This is only used to encrypt the AES secret key so that
* the only way to decrypt it is with the RSA private key.
* The RSA private key is stored in an HSM and is thus never
* exposed to the Privy server or any clients.
* Imports a 2048 bit public key in DER format for AES-GCM decryption.
*
* The next iteration of Privy's crypto code will be using ECC
* and thus moving away from the less secure RSA+SHA1.
* @param {BufferSource} key Uint8Array of the RSA public key in DER format
* @returns {Promise<CryptoKey>} promise resolving to the imported CryptoKey
*/
function rsaOaepSha1Encrypt(plaintext, publicKey) {
return webcrypto.publicEncrypt({
key: publicKey,
oaepHash: SHA1,
}, plaintext);
function importRSAOAEPEncryptionKey(key) {
return webcrypto_1.crypto.subtle.importKey(SPKI_FORMAT, key, RSA_OAEP_ALGORITHM, NOT_EXTRACTABLE, WRAP_KEY_ONLY);
}
exports.rsaOaepSha1Encrypt = rsaOaepSha1Encrypt;
exports.importRSAOAEPEncryptionKey = importRSAOAEPEncryptionKey;
/**
* Performs AES-GCM encryption on the given plaintext
* using the given initialization vector and key.
*
* @param {BufferSource} pt the plaintext data to encrypt
* @param {BufferSource} iv the initialization vector
* @param {CryptoKey} key the secret encryption key
* @returns {Promise<Uint8Array>} promise resolving to the encrypted bytes
*/
function aesGCMEncrypt(pt, iv, key) {
return __awaiter(this, void 0, void 0, function () {
var ct;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, webcrypto_1.crypto.subtle.encrypt(aesGCMParams(iv), key, pt)];
case 1:
ct = _a.sent();
return [2 /*return*/, new Uint8Array(ct)];
}
});
});
}
exports.aesGCMEncrypt = aesGCMEncrypt;
/**
* Performs AES-GCM decryption on the given ciphertext
* using the given initialization vector and key.
*
* @param {BufferSource} ct the ciphertext data to decrypt
* @param {BufferSource} iv the initialization vector
* @param {CryptoKey} key the secret encryption key
* @returns {Promise<Uint8Array>} promise resolving to the decrypted bytes
*/
function aesGCMDecrypt(ct, iv, key) {
return __awaiter(this, void 0, void 0, function () {
var pt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, webcrypto_1.crypto.subtle.decrypt(aesGCMParams(iv), key, ct)];
case 1:
pt = _a.sent();
return [2 /*return*/, new Uint8Array(pt)];
}
});
});
}
exports.aesGCMDecrypt = aesGCMDecrypt;
/**
* Performs RSA-OAEP encryption of key with a wrapping key (i.e., RSA public key).
*
* @param {CryptoKey} key key to encrypt
* @param {CryptoKey} wrappingKey RSA public key to use for encrypting key
* @returns {Promise<Uint8Array>} promise resolving to the encrypted bytes
*/
function rsaOaepWrapKey(key, wrappingKey) {
return __awaiter(this, void 0, void 0, function () {
var ct;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, webcrypto_1.crypto.subtle.wrapKey(RAW_FORMAT, key, wrappingKey, { name: RSA_OAEP })];
case 1:
ct = _a.sent();
return [2 /*return*/, new Uint8Array(ct)];
}
});
});
}
exports.rsaOaepWrapKey = rsaOaepWrapKey;
/**
* Hashes data using SHA256.
*
* @param {BufferSource} data data to hash
* @returns {Promise<Uint8Array>} promise resolving to hashed bytes
*/
function sha256(data) {
return __awaiter(this, void 0, void 0, function () {
var hash;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, webcrypto_1.crypto.subtle.digest('SHA-256', data)];
case 1:
hash = _a.sent();
return [2 /*return*/, new Uint8Array(hash)];
}
});
});
}
exports.sha256 = sha256;
//# sourceMappingURL=crypto.js.map

@@ -1,2 +0,1 @@

/// <reference types="node" />
/**

@@ -15,18 +14,16 @@ * This is only used to encrypt the AES secret key so that

* Returns the ciphertext.
*
* @param {BufferEncoding} [encoding] - Optional encoding which converts the ciphertext to a string using the given encoding.
*/
ciphertext(): Buffer;
ciphertext(encoding: BufferEncoding): string;
ciphertext(): Uint8Array;
/**
* Returns the wrapper key id.
*
* @param {BufferEncoding} [encoding] - Optional encoding which converts the wrapper key id to a string using the given encoding.
*/
wrapperKeyId(): Buffer;
wrapperKeyId(encoding: BufferEncoding): string;
wrapperKeyId(): Uint8Array;
/**
* Returns the commitment id which is (a sha256 hash).
*/
commitmentId(): Uint8Array;
}
export interface EncryptConfig {
wrapperKey: Buffer;
wrapperKeyId: Buffer;
wrapperKey: Uint8Array;
wrapperKeyId: Uint8Array;
}

@@ -37,8 +34,8 @@ export declare class Encryption {

*
* @param {Buffer} plaintext - The plaintext data to encrypt.
* @param plaintext - The plaintext data to encrypt.
* @param {EncryptConfig} config - An object to configure encryption.
* * wrapperKey - (Buffer) The wrapper key (RSA public key in PEM format).
* * wrapperKeyId - (Buffer) The metadata ID of the RSA public key.
* * wrapperKey - (Uint8Array) The wrapper key (RSA public key in DER format).
* * wrapperKeyId - (Uint8Array) The metadata ID of the RSA public key.
*/
constructor(plaintext: Buffer, config: EncryptConfig);
constructor(plaintext: Uint8Array, config: EncryptConfig);
/**

@@ -49,6 +46,7 @@ * Encrypts the given plaintext data.

*
* 1. Generate a single-use secret key (aka data key)
* 1. Generate a secret key (aka, data key) and initialization vector
* 2. Encrypt (AES-256-GCM) plaintext data using data key
* 3. Encrypt (RSA-OAEP-SHA1) data key with wrapper key (RSA public key)
* 4. Serialize the following components into a single buffer:
* 3. Generate and encrypt a nonce used for data integrity checks
* 4. Encrypt (RSA-OAEP-SHA1) data key with wrapper key (RSA public key)
* 5. Serialize the following components into a single buffer:
* * Privy crypto version (0x0001 in this case)

@@ -59,4 +57,5 @@ * * wrapper key id

* * encrypted data
* * authentication tag from AES-256-GCM
* 5. Return an EncryptionResult object
* * encrypted nonce
* 6. Generate the commitment id (sha256 hash) for (nonce || plaintext)
* 7. Return an EncryptionResult object
*

@@ -70,7 +69,8 @@ * @returns a Promise that resolves to an EncryptionResult

* Returns the plaintext.
*
* @param {BufferEncoding} [encoding] - Optional encoding which converts the plaintext to a string using the given encoding.
*/
plaintext(): Buffer;
plaintext(encoding: BufferEncoding): string;
plaintext(): Uint8Array;
/**
* Returns the commitment nonce.
*/
commitmentNonce(): Uint8Array;
}

@@ -81,27 +81,29 @@ export declare class Decryption {

*
* @param {Buffer} serialized - The serialized encrypted data to decrypt.
* @param serialized - The serialized encrypted data to decrypt.
*/
constructor(serialized: Buffer);
constructor(serialized: Uint8Array);
/**
* Returns the wrapper key id.
*
* @param {BufferEncoding} [encoding] - Optional encoding which converts the wrapper key id to a string using the given encoding.
*/
wrapperKeyId(): Buffer;
wrapperKeyId(encoding: BufferEncoding): string;
wrapperKeyId(): Uint8Array;
/**
* Returns the encrypted data key.
*
* @param {BufferEncoding} [encoding] - Optional encoding which converts the encrypted data key to a string using the given encoding.
*/
encryptedDataKey(): Buffer;
encryptedDataKey(encoding: BufferEncoding): string;
encryptedDataKey(): Uint8Array;
/**
* Decrypts the encrypted data using the given data key.
*
* @param {Buffer} dataKey - The secret key used to encrypt the data.
* @returns DecryptionResult containing the plaintext data
* @param {Uint8Array} dataKeyTypedArray - The secret key used to encrypt the data.
* @returns DecryptionResult containing the plaintext data.
*/
decrypt(dataKey: Buffer): Promise<DecryptionResult>;
decrypt(dataKeyTypedArray: Uint8Array): Promise<DecryptionResult>;
/**
* Performs a data integrity check to verify that the decrypted data matches the given commitment id.
*
* @params {DecryptionResult} decryptionResult containing the plaintext data.
* @param {Uint8Array} commitmentId - Commitment hash used to perform optional data integrity check.
* @returns True if commitment id matches hash calculated from the decryptionResult, false otherwise.
*/
verify(decryptionResult: DecryptionResult, commitmentId: Uint8Array): Promise<boolean>;
}
//# sourceMappingURL=x0.d.ts.map

@@ -44,6 +44,2 @@ "use strict";

var crypto_1 = require("../crypto");
// NIST recommended lengths
var IV_LENGTH_IN_BYTES = 12;
var AUTH_TAG_LENGTH_IN_BYTES = 16;
var DATA_KEY_LENGTH_IN_BYTES = 32;
/**

@@ -64,22 +60,25 @@ * This is only used to encrypt the AES secret key so that

*/
function EncryptionResult(ciphertext, wrapperKeyId) {
function EncryptionResult(ciphertext, wrapperKeyId, commitmentId) {
this._ciphertext = ciphertext;
this._wrapperKeyId = wrapperKeyId;
this._commitmentId = commitmentId;
}
EncryptionResult.prototype.ciphertext = function (encoding) {
if (encoding !== undefined) {
return this._ciphertext.toString(encoding);
}
else {
return this._ciphertext;
}
/**
* Returns the ciphertext.
*/
EncryptionResult.prototype.ciphertext = function () {
return this._ciphertext;
};
EncryptionResult.prototype.wrapperKeyId = function (encoding) {
if (encoding !== undefined) {
return this._wrapperKeyId.toString(encoding);
}
else {
return this._wrapperKeyId;
}
/**
* Returns the wrapper key id.
*/
EncryptionResult.prototype.wrapperKeyId = function () {
return this._wrapperKeyId;
};
/**
* Returns the commitment id which is (a sha256 hash).
*/
EncryptionResult.prototype.commitmentId = function () {
return this._commitmentId;
};
return EncryptionResult;

@@ -92,6 +91,6 @@ }());

*
* @param {Buffer} plaintext - The plaintext data to encrypt.
* @param plaintext - The plaintext data to encrypt.
* @param {EncryptConfig} config - An object to configure encryption.
* * wrapperKey - (Buffer) The wrapper key (RSA public key in PEM format).
* * wrapperKeyId - (Buffer) The metadata ID of the RSA public key.
* * wrapperKey - (Uint8Array) The wrapper key (RSA public key in DER format).
* * wrapperKeyId - (Uint8Array) The metadata ID of the RSA public key.
*/

@@ -108,14 +107,16 @@ function Encryption(plaintext, config) {

* || wrapperKeyIdLengthInBytes (BigUint64)
* || wrapperKeyId (Buffer)
* || wrapperKeyId (Uint8Array)
* || encryptedDataKeyLengthInBytes (BigUint64)
* || encryptedDataKey (Buffer)
* || initializationVector (buffer) (12 bytes)
* || encryptedDataKey (Uint8Array)
* || initializationVector (Uint8Array) (12 bytes)
* || encryptedDataLengthInBytes (BigUint64)
* || encryptedData (Buffer)
* || authenticationTag (Buffer) (16 bytes)
* || encryptedData (Uint8Array)
* || dataAuthenticationTag (Uint8Array) (16 bytes)
* || encryptedNonce (32 bytes)
* || nonceAuthenticationTag (Uint8Array) (16 bytes)
*
* @internal
*/
Encryption.prototype._serialize = function (ciphertext, encryptedDataKey, authenticationTag, initializationVector, wrapperKeyId) {
return (0, buffers_1.concatBuffers)((0, version_1.cryptoVersionToBuffer)(version_1.CryptoVersion.x0), (0, buffers_1.bufferFromUInt64)(wrapperKeyId.length), wrapperKeyId, (0, buffers_1.bufferFromUInt64)(encryptedDataKey.length), encryptedDataKey, initializationVector, (0, buffers_1.bufferFromUInt64)(ciphertext.length), ciphertext, authenticationTag);
Encryption.prototype._serialize = function (encryptedData, encryptedDataKey, encryptedNonce, dataInitializationVector, nonceInitializationVector, wrapperKeyId) {
return (0, buffers_1.concatBuffers)((0, version_1.cryptoVersionToBuffer)(version_1.CryptoVersion.x0), (0, buffers_1.bufferFromUInt64)(wrapperKeyId.byteLength), wrapperKeyId, (0, buffers_1.bufferFromUInt64)(encryptedDataKey.byteLength), encryptedDataKey, dataInitializationVector, (0, buffers_1.bufferFromUInt64)(encryptedData.byteLength - crypto_1.AUTH_TAG_LENGTH_16_BYTES), encryptedData, nonceInitializationVector, encryptedNonce);
};

@@ -127,6 +128,7 @@ /**

*
* 1. Generate a single-use secret key (aka data key)
* 1. Generate a secret key (aka, data key) and initialization vector
* 2. Encrypt (AES-256-GCM) plaintext data using data key
* 3. Encrypt (RSA-OAEP-SHA1) data key with wrapper key (RSA public key)
* 4. Serialize the following components into a single buffer:
* 3. Generate and encrypt a nonce used for data integrity checks
* 4. Encrypt (RSA-OAEP-SHA1) data key with wrapper key (RSA public key)
* 5. Serialize the following components into a single buffer:
* * Privy crypto version (0x0001 in this case)

@@ -137,4 +139,5 @@ * * wrapper key id

* * encrypted data
* * authentication tag from AES-256-GCM
* 5. Return an EncryptionResult object
* * encrypted nonce
* 6. Generate the commitment id (sha256 hash) for (nonce || plaintext)
* 7. Return an EncryptionResult object
*

@@ -145,23 +148,36 @@ * @returns a Promise that resolves to an EncryptionResult

return __awaiter(this, void 0, void 0, function () {
var dataKey, _a, ciphertext, initializationVector, authenticationTag, encryptedDataKey, serialized;
return __generator(this, function (_b) {
dataKey = (0, crypto_1.csprng)(DATA_KEY_LENGTH_IN_BYTES);
try {
_a = (0, crypto_1.aes256gcmEncrypt)(this._plaintext, dataKey, {
ivLengthInBytes: IV_LENGTH_IN_BYTES,
authTagLengthInBytes: AUTH_TAG_LENGTH_IN_BYTES,
}), ciphertext = _a.ciphertext, initializationVector = _a.initializationVector, authenticationTag = _a.authenticationTag;
encryptedDataKey = (0, crypto_1.rsaOaepSha1Encrypt)(dataKey, this._config.wrapperKey);
serialized = this._serialize(ciphertext, encryptedDataKey, authenticationTag, initializationVector, this._config.wrapperKeyId);
// 5. Return the encryption result
return [2 /*return*/, new EncryptionResult(serialized, this._config.wrapperKeyId)];
var dataKey, dataInitializationVector, encryptedData, nonce, nonceInitializationVector, encryptedNonce, wrapperKey, encryptedDataKey, serialized, commitmentId, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 7, , 8]);
return [4 /*yield*/, (0, crypto_1.generateAESGCMEncryptionKey)()];
case 1:
dataKey = _a.sent();
dataInitializationVector = (0, crypto_1.csprng)(crypto_1.IV_LENGTH_12_BYTES);
return [4 /*yield*/, (0, crypto_1.aesGCMEncrypt)(this._plaintext, dataInitializationVector, dataKey)];
case 2:
encryptedData = _a.sent();
nonce = (0, crypto_1.csprng)(crypto_1.IV_LENGTH_12_BYTES);
nonceInitializationVector = (0, crypto_1.csprng)(crypto_1.IV_LENGTH_12_BYTES);
return [4 /*yield*/, (0, crypto_1.aesGCMEncrypt)(nonce, nonceInitializationVector, dataKey)];
case 3:
encryptedNonce = _a.sent();
return [4 /*yield*/, (0, crypto_1.importRSAOAEPEncryptionKey)(this._config.wrapperKey)];
case 4:
wrapperKey = _a.sent();
return [4 /*yield*/, (0, crypto_1.rsaOaepWrapKey)(dataKey, wrapperKey)];
case 5:
encryptedDataKey = _a.sent();
serialized = this._serialize(encryptedData, encryptedDataKey, encryptedNonce, dataInitializationVector, nonceInitializationVector, this._config.wrapperKeyId);
return [4 /*yield*/, (0, crypto_1.sha256)((0, buffers_1.concatBuffers)(nonce, this._plaintext))];
case 6:
commitmentId = _a.sent();
// 7. Return an EncryptionResult object
return [2 /*return*/, new EncryptionResult(serialized, this._config.wrapperKeyId, commitmentId)];
case 7:
error_1 = _a.sent();
throw new errors_1.CryptoError('Failed to encrypt plaintext', error_1);
case 8: return [2 /*return*/];
}
catch (error) {
throw new errors_1.CryptoError('Failed to encrypt plaintext', error);
}
finally {
// Always clear the secret data key from memory
dataKey.fill(0);
}
return [2 /*return*/];
});

@@ -178,13 +194,18 @@ });

*/
function DecryptionResult(plaintext) {
function DecryptionResult(plaintext, commitmentNonce) {
this._plaintext = plaintext;
this._commitmentNonce = commitmentNonce;
}
DecryptionResult.prototype.plaintext = function (encoding) {
if (encoding !== undefined) {
return this._plaintext.toString(encoding);
}
else {
return this._plaintext;
}
/**
* Returns the plaintext.
*/
DecryptionResult.prototype.plaintext = function () {
return this._plaintext;
};
/**
* Returns the commitment nonce.
*/
DecryptionResult.prototype.commitmentNonce = function () {
return this._commitmentNonce;
};
return DecryptionResult;

@@ -197,20 +218,18 @@ }());

*
* @param {Buffer} serialized - The serialized encrypted data to decrypt.
* @param serialized - The serialized encrypted data to decrypt.
*/
function Decryption(serialized) {
var _a = this._deserializeEncryptedData(serialized), cryptoVersion = _a.cryptoVersion, wrapperKeyId = _a.wrapperKeyId, encryptedDataKey = _a.encryptedDataKey, initializationVector = _a.initializationVector, ciphertext = _a.ciphertext, authenticationTag = _a.authenticationTag;
var _a = this._deserializeEncryptedData(serialized), cryptoVersion = _a.cryptoVersion, wrapperKeyId = _a.wrapperKeyId, encryptedDataKey = _a.encryptedDataKey, dataInitializationVector = _a.dataInitializationVector, ciphertext = _a.ciphertext, nonceInitializationVector = _a.nonceInitializationVector, encryptedNonce = _a.encryptedNonce;
if (cryptoVersion !== version_1.CryptoVersion.x0) {
throw new errors_1.CryptoError("Invalid PrivyCrypto version for engine: expected ".concat(version_1.CryptoVersion.x0, " but got ").concat(cryptoVersion));
}
else if (initializationVector.length !== IV_LENGTH_IN_BYTES) {
throw new errors_1.CryptoError("Invalid initialization vector length: expected ".concat(IV_LENGTH_IN_BYTES, " but got ").concat(initializationVector.length));
if (dataInitializationVector.length !== crypto_1.IV_LENGTH_12_BYTES) {
throw new errors_1.CryptoError("Invalid initialization vector length: expected ".concat(crypto_1.IV_LENGTH_12_BYTES, " but got ").concat(dataInitializationVector.length));
}
else if (authenticationTag.length !== AUTH_TAG_LENGTH_IN_BYTES) {
throw new errors_1.CryptoError("Invalid authentication tag length: expected ".concat(AUTH_TAG_LENGTH_IN_BYTES, " but got ").concat(authenticationTag.length));
}
this._wrapperKeyId = wrapperKeyId;
this._encryptedDataKey = encryptedDataKey;
this._initializationVector = initializationVector;
this._dataInitializationVector = dataInitializationVector;
this._ciphertext = ciphertext;
this._authenticationTag = authenticationTag;
this._nonceInitializationVector = nonceInitializationVector;
this._encryptedNonce = encryptedNonce;
}

@@ -236,13 +255,22 @@ /**

offset += encryptedDataKeyLength;
// Read initialization vector.
var initializationVector = serializedEncryptedData.slice(offset, offset + IV_LENGTH_IN_BYTES);
offset += IV_LENGTH_IN_BYTES;
// Read data initialization vector.
var dataInitializationVector = serializedEncryptedData.slice(offset, offset + crypto_1.IV_LENGTH_12_BYTES);
offset += crypto_1.IV_LENGTH_12_BYTES;
// Read encrypted data length.
var _c = (0, buffers_1.uint64FromBuffer)(serializedEncryptedData, offset), encryptedDataLength = _c[0], encryptedDataOffset = _c[1];
offset = encryptedDataOffset;
var encryptedDataAndAuthTagLength = encryptedDataLength + crypto_1.AUTH_TAG_LENGTH_16_BYTES;
// Read encrypted data.
var ciphertext = serializedEncryptedData.slice(offset, offset + encryptedDataLength);
offset += encryptedDataLength;
// Read authentication tag.
var authenticationTag = serializedEncryptedData.slice(offset);
var ciphertext = serializedEncryptedData.slice(offset, offset + encryptedDataAndAuthTagLength);
offset += encryptedDataAndAuthTagLength;
// Check if nonce is included (for backwards compatibility) and deserialize if so.
var encryptedNonce = new Uint8Array(0);
var nonceInitializationVector = new Uint8Array(0);
if (offset < serializedEncryptedData.length) {
// Read data initialization vector.
nonceInitializationVector = serializedEncryptedData.slice(offset, offset + crypto_1.IV_LENGTH_12_BYTES);
offset += crypto_1.IV_LENGTH_12_BYTES;
// Read encrypted nonce.
encryptedNonce = serializedEncryptedData.slice(offset, offset + crypto_1.COMMITMENT_NONCE_LENGTH_32_BYTES + crypto_1.AUTH_TAG_LENGTH_16_BYTES);
}
return {

@@ -252,22 +280,19 @@ cryptoVersion: cryptoVersion,

encryptedDataKey: encryptedDataKey,
initializationVector: initializationVector,
dataInitializationVector: dataInitializationVector,
ciphertext: ciphertext,
authenticationTag: authenticationTag,
nonceInitializationVector: nonceInitializationVector,
encryptedNonce: encryptedNonce,
};
};
Decryption.prototype.wrapperKeyId = function (encoding) {
if (encoding !== undefined) {
return this._wrapperKeyId.toString(encoding);
}
else {
return this._wrapperKeyId;
}
/**
* Returns the wrapper key id.
*/
Decryption.prototype.wrapperKeyId = function () {
return this._wrapperKeyId;
};
Decryption.prototype.encryptedDataKey = function (encoding) {
if (encoding !== undefined) {
return this._encryptedDataKey.toString(encoding);
}
else {
return this._encryptedDataKey;
}
/**
* Returns the encrypted data key.
*/
Decryption.prototype.encryptedDataKey = function () {
return this._encryptedDataKey;
};

@@ -277,21 +302,54 @@ /**

*
* @param {Buffer} dataKey - The secret key used to encrypt the data.
* @returns DecryptionResult containing the plaintext data
* @param {Uint8Array} dataKeyTypedArray - The secret key used to encrypt the data.
* @returns DecryptionResult containing the plaintext data.
*/
Decryption.prototype.decrypt = function (dataKey) {
Decryption.prototype.decrypt = function (dataKeyTypedArray) {
return __awaiter(this, void 0, void 0, function () {
var plaintext;
var dataKey, plaintext, commitmentNonce, error_2;
return __generator(this, function (_a) {
try {
plaintext = (0, crypto_1.aes256gcmDecrypt)(this._ciphertext, dataKey, this._initializationVector, this._authenticationTag);
return [2 /*return*/, new DecryptionResult(plaintext)];
switch (_a.label) {
case 0:
_a.trys.push([0, 4, , 5]);
return [4 /*yield*/, (0, crypto_1.importAESGCMDecryptionKey)(dataKeyTypedArray)];
case 1:
dataKey = _a.sent();
return [4 /*yield*/, (0, crypto_1.aesGCMDecrypt)(this._ciphertext, this._dataInitializationVector, dataKey)];
case 2:
plaintext = _a.sent();
return [4 /*yield*/, (0, crypto_1.aesGCMDecrypt)(this._encryptedNonce, this._nonceInitializationVector, dataKey)];
case 3:
commitmentNonce = _a.sent();
return [2 /*return*/, new DecryptionResult(plaintext, commitmentNonce)];
case 4:
error_2 = _a.sent();
if (error_2 instanceof errors_1.CryptoError) {
throw error_2;
}
else {
throw new errors_1.CryptoError('Failed to decrypt the encrypted data', error_2);
}
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
catch (error) {
throw new errors_1.CryptoError('Failed to decrypt the encrypted data', error);
});
});
};
/**
* Performs a data integrity check to verify that the decrypted data matches the given commitment id.
*
* @params {DecryptionResult} decryptionResult containing the plaintext data.
* @param {Uint8Array} commitmentId - Commitment hash used to perform optional data integrity check.
* @returns True if commitment id matches hash calculated from the decryptionResult, false otherwise.
*/
Decryption.prototype.verify = function (decryptionResult, commitmentId) {
return __awaiter(this, void 0, void 0, function () {
var hash;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, crypto_1.sha256)((0, buffers_1.concatBuffers)(decryptionResult.commitmentNonce(), decryptionResult.plaintext()))];
case 1:
hash = _a.sent();
// Return whether the hash matches the commitmentId.
return [2 /*return*/, (0, buffers_1.buffersEqual)(hash, commitmentId)];
}
finally {
// Always clear the secret data key from memory
dataKey.fill(0);
}
return [2 /*return*/];
});

@@ -298,0 +356,0 @@ });

export { CryptoError } from './errors';
export { CryptoVersion } from './version';
export { CryptoEngine } from './engines';
export { md5Hash } from './crypto';
//# sourceMappingURL=index.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.md5Hash = exports.CryptoEngine = exports.CryptoVersion = exports.CryptoError = void 0;
exports.CryptoEngine = exports.CryptoVersion = exports.CryptoError = void 0;
// Expose CryptoError error

@@ -13,5 +13,2 @@ var errors_1 = require("./errors");

Object.defineProperty(exports, "CryptoEngine", { enumerable: true, get: function () { return engines_1.CryptoEngine; } });
// Expose md5 utility
var crypto_1 = require("./crypto");
Object.defineProperty(exports, "md5Hash", { enumerable: true, get: function () { return crypto_1.md5Hash; } });
//# sourceMappingURL=index.js.map

@@ -1,2 +0,1 @@

/// <reference types="node" />
export declare const CRYPTO_VERSION_LENGTH_IN_BYTES = 2;

@@ -6,4 +5,4 @@ export declare enum CryptoVersion {

}
export declare function cryptoVersionFromBuffer(serialized: Buffer): CryptoVersion;
export declare function cryptoVersionToBuffer(version: CryptoVersion): Buffer;
export declare function cryptoVersionFromBuffer(serialized: Uint8Array): CryptoVersion;
export declare function cryptoVersionToBuffer(version: CryptoVersion): Uint8Array;
//# sourceMappingURL=version.d.ts.map

@@ -17,4 +17,4 @@ "use strict";

function cryptoVersionFromBuffer(serialized) {
var versionBuffer = serialized.slice(0, exports.CRYPTO_VERSION_LENGTH_IN_BYTES);
var version = versionBuffer.readUInt16BE();
var versionDataView = new DataView(serialized.buffer, serialized.byteOffset, serialized.byteLength);
var version = versionDataView.getUint16(0, false); // Big endian.
switch (version) {

@@ -29,7 +29,7 @@ case CryptoVersion.x0:

function cryptoVersionToBuffer(version) {
var cryptoVersionBuffer = Buffer.alloc(exports.CRYPTO_VERSION_LENGTH_IN_BYTES);
cryptoVersionBuffer.writeUInt16BE(version);
return cryptoVersionBuffer;
var cryptoVersionBuffer = new ArrayBuffer(exports.CRYPTO_VERSION_LENGTH_IN_BYTES);
new DataView(cryptoVersionBuffer).setUint16(0, version, false); // Big endian.
return new Uint8Array(cryptoVersionBuffer);
}
exports.cryptoVersionToBuffer = cryptoVersionToBuffer;
//# sourceMappingURL=version.js.map
{
"name": "@privy-io/crypto",
"version": "0.0.1",
"version": "0.0.2",
"description": "Privy encryption and decryption library",

@@ -15,4 +15,3 @@ "main": "dist/index.js",

"prettier": "prettier --check \"src/**/*.ts\"",
"test": "jest",
"version": "git add package.json package-lock.json && git commit -m \"@privy-io/crypto@${npm_package_version}\""
"test": "jest"
},

@@ -29,3 +28,3 @@ "keywords": [

"author": "",
"license": "ISC",
"license": "MIT",
"devDependencies": {

@@ -36,7 +35,3 @@ "@types/jest": "^27.4.0",

"typescript": "^4.5.5"
},
"dependencies": {
"events": "3.3.0",
"webcrypto": "0.1.1"
}
}

@@ -30,2 +30,5 @@ # @privy-io/crypto

const ciphertext = encryptionResult.ciphertext();
// Commitment id's are computed from the hash of a nonce concatenated with the
// plaintext. Can be used for an optional data integrity check.
const commitmentId = encryptionResult.commitmentId();

@@ -39,6 +42,10 @@ // Decryption

privyDecryption.wrapperKeyId('utf8'),
privyDecryption.encryptedDataKey('base64')
privyDecryption.encryptedDataKey('base64'),
);
const decryptionResult = await privyDecryption.decrypt(decryptedDataKey);
// Optional data integrity check.
if (!(await privyDecryption.verify(decryptionResult, commitmentId))) {
throw 'Data integrity check failed.';
}

@@ -45,0 +52,0 @@ // {"ssn": "123-45-6789"}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc