Remove internal, unused RandomBuffer
(#1593)
The changes do not affect the public API: `RandomBuffer` was used internally for secure randomness generation before `crypto.getRandomValues` was made available to WebWorkers, requiring generating randomness in the main thread. As a result of the change, the internal `getRandomBytes()` and some functions that use it are no longer async.
This commit is contained in:
parent
9175b76887
commit
126ab53840
|
@ -367,8 +367,7 @@ export async function getPrefixRandom(algo) {
|
||||||
* Generating a session key for the specified symmetric algorithm
|
* Generating a session key for the specified symmetric algorithm
|
||||||
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
|
||||||
* @param {module:enums.symmetric} algo - Symmetric encryption algorithm
|
* @param {module:enums.symmetric} algo - Symmetric encryption algorithm
|
||||||
* @returns {Promise<Uint8Array>} Random bytes as a string to be used as a key.
|
* @returns {Uint8Array} Random bytes as a string to be used as a key.
|
||||||
* @async
|
|
||||||
*/
|
*/
|
||||||
export function generateSessionKey(algo) {
|
export function generateSessionKey(algo) {
|
||||||
const { keySize } = getCipher(algo);
|
const { keySize } = getCipher(algo);
|
||||||
|
|
|
@ -50,14 +50,13 @@ hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
||||||
* Create padding with secure random data
|
* Create padding with secure random data
|
||||||
* @private
|
* @private
|
||||||
* @param {Integer} length - Length of the padding in bytes
|
* @param {Integer} length - Length of the padding in bytes
|
||||||
* @returns {Promise<Uint8Array>} Random padding.
|
* @returns {Uint8Array} Random padding.
|
||||||
* @async
|
|
||||||
*/
|
*/
|
||||||
async function getPKCS1Padding(length) {
|
function getPKCS1Padding(length) {
|
||||||
const result = new Uint8Array(length);
|
const result = new Uint8Array(length);
|
||||||
let count = 0;
|
let count = 0;
|
||||||
while (count < length) {
|
while (count < length) {
|
||||||
const randomBytes = await getRandomBytes(length - count);
|
const randomBytes = getRandomBytes(length - count);
|
||||||
for (let i = 0; i < randomBytes.length; i++) {
|
for (let i = 0; i < randomBytes.length; i++) {
|
||||||
if (randomBytes[i] !== 0) {
|
if (randomBytes[i] !== 0) {
|
||||||
result[count++] = randomBytes[i];
|
result[count++] = randomBytes[i];
|
||||||
|
@ -72,10 +71,9 @@ async function getPKCS1Padding(length) {
|
||||||
* @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1}
|
* @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1}
|
||||||
* @param {Uint8Array} message - Message to be encoded
|
* @param {Uint8Array} message - Message to be encoded
|
||||||
* @param {Integer} keyLength - The length in octets of the key modulus
|
* @param {Integer} keyLength - The length in octets of the key modulus
|
||||||
* @returns {Promise<Uint8Array>} EME-PKCS1 padded message.
|
* @returns {Uint8Array} EME-PKCS1 padded message.
|
||||||
* @async
|
|
||||||
*/
|
*/
|
||||||
export async function emeEncode(message, keyLength) {
|
export function emeEncode(message, keyLength) {
|
||||||
const mLength = message.length;
|
const mLength = message.length;
|
||||||
// length checking
|
// length checking
|
||||||
if (mLength > keyLength - 11) {
|
if (mLength > keyLength - 11) {
|
||||||
|
@ -83,7 +81,7 @@ export async function emeEncode(message, keyLength) {
|
||||||
}
|
}
|
||||||
// Generate an octet string PS of length k - mLen - 3 consisting of
|
// Generate an octet string PS of length k - mLen - 3 consisting of
|
||||||
// pseudo-randomly generated nonzero octets
|
// pseudo-randomly generated nonzero octets
|
||||||
const PS = await getPKCS1Padding(keyLength - mLength - 3);
|
const PS = getPKCS1Padding(keyLength - mLength - 3);
|
||||||
// Concatenate PS, the message M, and other padding to form an
|
// Concatenate PS, the message M, and other padding to form an
|
||||||
// encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M.
|
// encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M.
|
||||||
const encoded = new Uint8Array(keyLength);
|
const encoded = new Uint8Array(keyLength);
|
||||||
|
|
|
@ -41,7 +41,7 @@ export async function encrypt(data, p, g, y) {
|
||||||
g = new BigInteger(g);
|
g = new BigInteger(g);
|
||||||
y = new BigInteger(y);
|
y = new BigInteger(y);
|
||||||
|
|
||||||
const padded = await emeEncode(data, p.byteLength());
|
const padded = emeEncode(data, p.byteLength());
|
||||||
const m = new BigInteger(padded);
|
const m = new BigInteger(padded);
|
||||||
|
|
||||||
// OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ*
|
// OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ*
|
||||||
|
|
|
@ -182,7 +182,7 @@ class Curve {
|
||||||
case 'node':
|
case 'node':
|
||||||
return nodeGenKeyPair(this.name);
|
return nodeGenKeyPair(this.name);
|
||||||
case 'curve25519': {
|
case 'curve25519': {
|
||||||
const privateKey = await getRandomBytes(32);
|
const privateKey = getRandomBytes(32);
|
||||||
privateKey[0] = (privateKey[0] & 127) | 64;
|
privateKey[0] = (privateKey[0] & 127) | 64;
|
||||||
privateKey[31] &= 248;
|
privateKey[31] &= 248;
|
||||||
const secretKey = privateKey.slice().reverse();
|
const secretKey = privateKey.slice().reverse();
|
||||||
|
@ -191,7 +191,7 @@ class Curve {
|
||||||
return { publicKey, privateKey };
|
return { publicKey, privateKey };
|
||||||
}
|
}
|
||||||
case 'ed25519': {
|
case 'ed25519': {
|
||||||
const privateKey = await getRandomBytes(32);
|
const privateKey = getRandomBytes(32);
|
||||||
const keyPair = nacl.sign.keyPair.fromSeed(privateKey);
|
const keyPair = nacl.sign.keyPair.fromSeed(privateKey);
|
||||||
const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]);
|
const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]);
|
||||||
return { publicKey, privateKey };
|
return { publicKey, privateKey };
|
||||||
|
@ -199,7 +199,7 @@ class Curve {
|
||||||
}
|
}
|
||||||
const indutnyCurve = await getIndutnyCurve(this.name);
|
const indutnyCurve = await getIndutnyCurve(this.name);
|
||||||
keyPair = await indutnyCurve.genKeyPair({
|
keyPair = await indutnyCurve.genKeyPair({
|
||||||
entropy: util.uint8ArrayToString(await getRandomBytes(32))
|
entropy: util.uint8ArrayToString(getRandomBytes(32))
|
||||||
});
|
});
|
||||||
return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) };
|
return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTraili
|
||||||
async function genPublicEphemeralKey(curve, Q) {
|
async function genPublicEphemeralKey(curve, Q) {
|
||||||
switch (curve.type) {
|
switch (curve.type) {
|
||||||
case 'curve25519': {
|
case 'curve25519': {
|
||||||
const d = await getRandomBytes(32);
|
const d = getRandomBytes(32);
|
||||||
const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d);
|
const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d);
|
||||||
let { publicKey } = nacl.box.keyPair.fromSecretKey(secretKey);
|
let { publicKey } = nacl.box.keyPair.fromSecretKey(secretKey);
|
||||||
publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]);
|
publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]);
|
||||||
|
|
|
@ -136,7 +136,7 @@ export async function validateParams(oid, Q, d) {
|
||||||
switch (curve.type) {
|
switch (curve.type) {
|
||||||
case 'web':
|
case 'web':
|
||||||
case 'node': {
|
case 'node': {
|
||||||
const message = await getRandomBytes(8);
|
const message = getRandomBytes(8);
|
||||||
const hashAlgo = enums.hash.sha256;
|
const hashAlgo = enums.hash.sha256;
|
||||||
const hashed = await hash.digest(hashAlgo, message);
|
const hashed = await hash.digest(hashAlgo, message);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -433,7 +433,7 @@ async function nodeEncrypt(data, n, e) {
|
||||||
async function bnEncrypt(data, n, e) {
|
async function bnEncrypt(data, n, e) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
n = new BigInteger(n);
|
n = new BigInteger(n);
|
||||||
data = new BigInteger(await emeEncode(data, n.byteLength()));
|
data = new BigInteger(emeEncode(data, n.byteLength()));
|
||||||
e = new BigInteger(e);
|
e = new BigInteger(e);
|
||||||
if (data.gte(n)) {
|
if (data.gte(n)) {
|
||||||
throw new Error('Message size cannot exceed modulus size');
|
throw new Error('Message size cannot exceed modulus size');
|
||||||
|
|
|
@ -26,88 +26,18 @@ import util from '../util';
|
||||||
|
|
||||||
const nodeCrypto = util.getNodeCrypto();
|
const nodeCrypto = util.getNodeCrypto();
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer for secure random numbers
|
|
||||||
*/
|
|
||||||
class RandomBuffer {
|
|
||||||
constructor() {
|
|
||||||
this.buffer = null;
|
|
||||||
this.size = null;
|
|
||||||
this.callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize buffer
|
|
||||||
* @param {Integer} size - size of buffer
|
|
||||||
*/
|
|
||||||
init(size, callback) {
|
|
||||||
this.buffer = new Uint8Array(size);
|
|
||||||
this.size = 0;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concat array of secure random numbers to buffer
|
|
||||||
* @param {Uint8Array} buf
|
|
||||||
*/
|
|
||||||
set(buf) {
|
|
||||||
if (!this.buffer) {
|
|
||||||
throw new Error('RandomBuffer is not initialized');
|
|
||||||
}
|
|
||||||
if (!(buf instanceof Uint8Array)) {
|
|
||||||
throw new Error('Invalid type: buf not an Uint8Array');
|
|
||||||
}
|
|
||||||
const freeSpace = this.buffer.length - this.size;
|
|
||||||
if (buf.length > freeSpace) {
|
|
||||||
buf = buf.subarray(0, freeSpace);
|
|
||||||
}
|
|
||||||
// set buf with offset old size of buffer
|
|
||||||
this.buffer.set(buf, this.size);
|
|
||||||
this.size += buf.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take numbers out of buffer and copy to array
|
|
||||||
* @param {Uint8Array} buf - The destination array
|
|
||||||
*/
|
|
||||||
async get(buf) {
|
|
||||||
if (!this.buffer) {
|
|
||||||
throw new Error('RandomBuffer is not initialized');
|
|
||||||
}
|
|
||||||
if (!(buf instanceof Uint8Array)) {
|
|
||||||
throw new Error('Invalid type: buf not an Uint8Array');
|
|
||||||
}
|
|
||||||
if (this.size < buf.length) {
|
|
||||||
if (!this.callback) {
|
|
||||||
throw new Error('Random number buffer depleted');
|
|
||||||
}
|
|
||||||
// Wait for random bytes from main context, then try again
|
|
||||||
await this.callback();
|
|
||||||
return this.get(buf);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < buf.length; i++) {
|
|
||||||
buf[i] = this.buffer[--this.size];
|
|
||||||
// clear buffer value
|
|
||||||
this.buffer[this.size] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve secure random byte array of the specified length
|
* Retrieve secure random byte array of the specified length
|
||||||
* @param {Integer} length - Length in bytes to generate
|
* @param {Integer} length - Length in bytes to generate
|
||||||
* @returns {Promise<Uint8Array>} Random byte array.
|
* @returns {Uint8Array} Random byte array.
|
||||||
* @async
|
|
||||||
*/
|
*/
|
||||||
export async function getRandomBytes(length) {
|
export function getRandomBytes(length) {
|
||||||
const buf = new Uint8Array(length);
|
const buf = new Uint8Array(length);
|
||||||
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
||||||
crypto.getRandomValues(buf);
|
crypto.getRandomValues(buf);
|
||||||
} else if (nodeCrypto) {
|
} else if (nodeCrypto) {
|
||||||
const bytes = nodeCrypto.randomBytes(buf.length);
|
const bytes = nodeCrypto.randomBytes(buf.length);
|
||||||
buf.set(bytes);
|
buf.set(bytes);
|
||||||
} else if (randomBuffer.buffer) {
|
|
||||||
await randomBuffer.get(buf);
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No secure random number generator available.');
|
throw new Error('No secure random number generator available.');
|
||||||
}
|
}
|
||||||
|
@ -137,5 +67,3 @@ export async function getRandomBigInteger(min, max) {
|
||||||
const r = new BigInteger(await getRandomBytes(bytes + 8));
|
const r = new BigInteger(await getRandomBytes(bytes + 8));
|
||||||
return r.mod(modulus).add(min);
|
return r.mod(modulus).add(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const randomBuffer = new RandomBuffer();
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ export class Message {
|
||||||
pkeskPacketCopy.read(serialisedPKESK);
|
pkeskPacketCopy.read(serialisedPKESK);
|
||||||
const randomSessionKey = {
|
const randomSessionKey = {
|
||||||
sessionKeyAlgorithm,
|
sessionKeyAlgorithm,
|
||||||
sessionKey: await crypto.generateSessionKey(sessionKeyAlgorithm)
|
sessionKey: crypto.generateSessionKey(sessionKeyAlgorithm)
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey);
|
await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey);
|
||||||
|
@ -345,7 +345,7 @@ export class Message {
|
||||||
enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) :
|
enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
const sessionKeyData = await crypto.generateSessionKey(algo);
|
const sessionKeyData = crypto.generateSessionKey(algo);
|
||||||
return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName };
|
return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ class AEADEncryptedDataPacket {
|
||||||
this.cipherAlgorithm = sessionKeyAlgorithm;
|
this.cipherAlgorithm = sessionKeyAlgorithm;
|
||||||
|
|
||||||
const { ivLength } = crypto.getAEADMode(this.aeadAlgorithm);
|
const { ivLength } = crypto.getAEADMode(this.aeadAlgorithm);
|
||||||
this.iv = await crypto.random.getRandomBytes(ivLength); // generate new random IV
|
this.iv = crypto.random.getRandomBytes(ivLength); // generate new random IV
|
||||||
this.chunkSizeByte = config.aeadChunkSizeByte;
|
this.chunkSizeByte = config.aeadChunkSizeByte;
|
||||||
const data = this.packets.write();
|
const data = this.packets.write();
|
||||||
this.encrypted = await this.crypt('encrypt', key, data);
|
this.encrypted = await this.crypt('encrypt', key, data);
|
||||||
|
|
|
@ -283,13 +283,13 @@ class SecretKeyPacket extends PublicKeyPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.s2k = new S2K(config);
|
this.s2k = new S2K(config);
|
||||||
this.s2k.salt = await crypto.random.getRandomBytes(8);
|
this.s2k.salt = crypto.random.getRandomBytes(8);
|
||||||
const cleartext = crypto.serializeParams(this.algorithm, this.privateParams);
|
const cleartext = crypto.serializeParams(this.algorithm, this.privateParams);
|
||||||
this.symmetric = enums.symmetric.aes256;
|
this.symmetric = enums.symmetric.aes256;
|
||||||
const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric);
|
const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric);
|
||||||
|
|
||||||
const { blockSize } = crypto.getCipher(this.symmetric);
|
const { blockSize } = crypto.getCipher(this.symmetric);
|
||||||
this.iv = await crypto.random.getRandomBytes(blockSize);
|
this.iv = crypto.random.getRandomBytes(blockSize);
|
||||||
|
|
||||||
if (config.aeadProtect) {
|
if (config.aeadProtect) {
|
||||||
this.s2kUsage = 253;
|
this.s2kUsage = 253;
|
||||||
|
|
|
@ -179,18 +179,18 @@ class SymEncryptedSessionKeyPacket {
|
||||||
this.sessionKeyEncryptionAlgorithm = algo;
|
this.sessionKeyEncryptionAlgorithm = algo;
|
||||||
|
|
||||||
this.s2k = new S2K(config);
|
this.s2k = new S2K(config);
|
||||||
this.s2k.salt = await crypto.random.getRandomBytes(8);
|
this.s2k.salt = crypto.random.getRandomBytes(8);
|
||||||
|
|
||||||
const { blockSize, keySize } = crypto.getCipher(algo);
|
const { blockSize, keySize } = crypto.getCipher(algo);
|
||||||
const encryptionKey = await this.s2k.produceKey(passphrase, keySize);
|
const encryptionKey = await this.s2k.produceKey(passphrase, keySize);
|
||||||
|
|
||||||
if (this.sessionKey === null) {
|
if (this.sessionKey === null) {
|
||||||
this.sessionKey = await crypto.generateSessionKey(this.sessionKeyAlgorithm);
|
this.sessionKey = crypto.generateSessionKey(this.sessionKeyAlgorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.version === 5) {
|
if (this.version === 5) {
|
||||||
const mode = crypto.getAEADMode(this.aeadAlgorithm);
|
const mode = crypto.getAEADMode(this.aeadAlgorithm);
|
||||||
this.iv = await crypto.random.getRandomBytes(mode.ivLength); // generate new random IV
|
this.iv = crypto.random.getRandomBytes(mode.ivLength); // generate new random IV
|
||||||
const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]);
|
const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]);
|
||||||
const modeInstance = await mode(algo, encryptionKey);
|
const modeInstance = await mode(algo, encryptionKey);
|
||||||
this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData);
|
this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData);
|
||||||
|
|
|
@ -242,7 +242,7 @@ module.exports = () => describe('API functional testing', function() {
|
||||||
await Promise.all(symmAlgoNames.map(async function(algoName) {
|
await Promise.all(symmAlgoNames.map(async function(algoName) {
|
||||||
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
||||||
const { blockSize } = crypto.getCipher(algo);
|
const { blockSize } = crypto.getCipher(algo);
|
||||||
const symmKey = await crypto.generateSessionKey(algo);
|
const symmKey = crypto.generateSessionKey(algo);
|
||||||
const IV = new Uint8Array(blockSize);
|
const IV = new Uint8Array(blockSize);
|
||||||
const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config);
|
const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config);
|
||||||
const text = util.uint8ArrayToString(await crypto.mode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize)));
|
const text = util.uint8ArrayToString(await crypto.mode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize)));
|
||||||
|
@ -269,8 +269,8 @@ module.exports = () => describe('API functional testing', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Asymmetric using RSA with eme_pkcs1 padding', async function () {
|
it('Asymmetric using RSA with eme_pkcs1 padding', function () {
|
||||||
const symmKey = await crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
const symmKey = crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
||||||
return crypto.publicKeyEncrypt(algoRSA, RSAPublicParams, symmKey).then(RSAEncryptedData => {
|
return crypto.publicKeyEncrypt(algoRSA, RSAPublicParams, symmKey).then(RSAEncryptedData => {
|
||||||
return crypto.publicKeyDecrypt(
|
return crypto.publicKeyDecrypt(
|
||||||
algoRSA, RSAPublicParams, RSAPrivateParams, RSAEncryptedData
|
algoRSA, RSAPublicParams, RSAPrivateParams, RSAEncryptedData
|
||||||
|
@ -280,8 +280,8 @@ module.exports = () => describe('API functional testing', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Asymmetric using Elgamal with eme_pkcs1 padding', async function () {
|
it('Asymmetric using Elgamal with eme_pkcs1 padding', function () {
|
||||||
const symmKey = await crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
const symmKey = crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
||||||
return crypto.publicKeyEncrypt(algoElGamal, elGamalPublicParams, symmKey).then(ElgamalEncryptedData => {
|
return crypto.publicKeyEncrypt(algoElGamal, elGamalPublicParams, symmKey).then(ElgamalEncryptedData => {
|
||||||
return crypto.publicKeyDecrypt(
|
return crypto.publicKeyDecrypt(
|
||||||
algoElGamal, elGamalPublicParams, elGamalPrivateParams, ElgamalEncryptedData
|
algoElGamal, elGamalPublicParams, elGamalPrivateParams, ElgamalEncryptedData
|
||||||
|
|
|
@ -45,8 +45,8 @@ module.exports = () => describe('Symmetric AES-GCM (experimental)', function() {
|
||||||
this.skip(); // eslint-disable-line no-invalid-this
|
this.skip(); // eslint-disable-line no-invalid-this
|
||||||
}
|
}
|
||||||
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
||||||
const key = await crypto.generateSessionKey(algo);
|
const key = crypto.generateSessionKey(algo);
|
||||||
const iv = await crypto.random.getRandomBytes(crypto.mode.gcm.ivLength);
|
const iv = crypto.random.getRandomBytes(crypto.mode.gcm.ivLength);
|
||||||
|
|
||||||
const nativeEncryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'encrypt') : sinonSandbox.spy(nodeCrypto, 'createCipheriv');
|
const nativeEncryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'encrypt') : sinonSandbox.spy(nodeCrypto, 'createCipheriv');
|
||||||
const nativeDecryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'decrypt') : sinonSandbox.spy(nodeCrypto, 'createDecipheriv');
|
const nativeDecryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'decrypt') : sinonSandbox.spy(nodeCrypto, 'createDecipheriv');
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module.exports = () => describe('Crypto', function () {
|
module.exports = () => describe('Crypto', function () {
|
||||||
require('./cipher')();
|
require('./cipher')();
|
||||||
require('./hash')();
|
require('./hash')();
|
||||||
require('./random.js')();
|
|
||||||
require('./crypto.js')();
|
require('./crypto.js')();
|
||||||
require('./elliptic.js')();
|
require('./elliptic.js')();
|
||||||
require('./ecdh.js')();
|
require('./ecdh.js')();
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
const random = require('../../src/crypto/random');
|
|
||||||
|
|
||||||
const chai = require('chai');
|
|
||||||
|
|
||||||
const { expect } = chai;
|
|
||||||
|
|
||||||
module.exports = () => describe('Random Buffer', function() {
|
|
||||||
let randomBuffer;
|
|
||||||
|
|
||||||
before(function() {
|
|
||||||
randomBuffer = new random.randomBuffer.constructor();
|
|
||||||
expect(randomBuffer).to.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Throw error if not initialized', async function () {
|
|
||||||
expect(randomBuffer.set.bind(randomBuffer)).to.throw('RandomBuffer is not initialized');
|
|
||||||
await expect(randomBuffer.get(new Uint8Array(1))).to.eventually.be.rejectedWith('RandomBuffer is not initialized');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Initialization', function () {
|
|
||||||
randomBuffer.init(5);
|
|
||||||
expect(randomBuffer.buffer).to.exist;
|
|
||||||
expect(randomBuffer.buffer).to.have.length(5);
|
|
||||||
expect(randomBuffer.size).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
function equal(buf, arr) {
|
|
||||||
for (let i = 0; i < buf.length; i++) {
|
|
||||||
if (buf[i] !== arr[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
it('Set Method', function () {
|
|
||||||
randomBuffer.init(5);
|
|
||||||
let buf = new Uint32Array(2);
|
|
||||||
expect(randomBuffer.set.bind(randomBuffer, buf)).to.throw('Invalid type: buf not an Uint8Array');
|
|
||||||
buf = new Uint8Array(2);
|
|
||||||
buf[0] = 1; buf[1] = 2;
|
|
||||||
randomBuffer.set(buf);
|
|
||||||
expect(equal(randomBuffer.buffer, [1,2,0,0,0])).to.be.true;
|
|
||||||
expect(randomBuffer.size).to.equal(2);
|
|
||||||
randomBuffer.set(buf);
|
|
||||||
expect(equal(randomBuffer.buffer, [1,2,1,2,0])).to.be.true;
|
|
||||||
expect(randomBuffer.size).to.equal(4);
|
|
||||||
randomBuffer.set(buf);
|
|
||||||
expect(equal(randomBuffer.buffer, [1,2,1,2,1])).to.be.true;
|
|
||||||
expect(randomBuffer.size).to.equal(5);
|
|
||||||
randomBuffer.init(1);
|
|
||||||
buf = new Uint8Array(2);
|
|
||||||
buf[0] = 1; buf[1] = 2;
|
|
||||||
randomBuffer.set(buf);
|
|
||||||
expect(buf).to.to.have.property('0', 1);
|
|
||||||
expect(randomBuffer.size).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Get Method', async function () {
|
|
||||||
randomBuffer.init(5);
|
|
||||||
let buf = new Uint8Array(5);
|
|
||||||
buf[0] = 1; buf[1] = 2; buf[2] = 5; buf[3] = 7; buf[4] = 8;
|
|
||||||
randomBuffer.set(buf);
|
|
||||||
buf = new Uint32Array(2);
|
|
||||||
await expect(randomBuffer.get(buf)).to.eventually.be.rejectedWith('Invalid type: buf not an Uint8Array');
|
|
||||||
buf = new Uint8Array(2);
|
|
||||||
randomBuffer.get(buf);
|
|
||||||
expect(equal(randomBuffer.buffer, [1,2,5,0,0])).to.be.true;
|
|
||||||
expect(randomBuffer.size).to.equal(3);
|
|
||||||
expect(buf).to.to.have.property('0', 8);
|
|
||||||
expect(buf).to.to.have.property('1', 7);
|
|
||||||
randomBuffer.get(buf);
|
|
||||||
expect(buf).to.to.have.property('0', 5);
|
|
||||||
expect(buf).to.to.have.property('1', 2);
|
|
||||||
expect(equal(randomBuffer.buffer, [1,0,0,0,0])).to.be.true;
|
|
||||||
expect(randomBuffer.size).to.equal(1);
|
|
||||||
await expect(randomBuffer.get(buf)).to.eventually.be.rejectedWith('Random number buffer depleted');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -65,7 +65,7 @@ module.exports = () => describe('basic RSA cryptography', function () {
|
||||||
it('sign and verify using generated key params', async function() {
|
it('sign and verify using generated key params', async function() {
|
||||||
const bits = 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const message = await random.getRandomBytes(64);
|
const message = random.getRandomBytes(64);
|
||||||
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, 'sha256');
|
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, 'sha256');
|
||||||
const hashed = await crypto.hash.digest(hashAlgo, message);
|
const hashed = await crypto.hash.digest(hashAlgo, message);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
|
@ -79,7 +79,7 @@ module.exports = () => describe('basic RSA cryptography', function () {
|
||||||
const bits = 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
const message = crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
||||||
const encrypted = await crypto.publicKey.rsa.encrypt(message, n, e);
|
const encrypted = await crypto.publicKey.rsa.encrypt(message, n, e);
|
||||||
const decrypted = await crypto.publicKey.rsa.decrypt(encrypted, n, e, d, p, q, u);
|
const decrypted = await crypto.publicKey.rsa.decrypt(encrypted, n, e, d, p, q, u);
|
||||||
expect(decrypted).to.deep.equal(message);
|
expect(decrypted).to.deep.equal(message);
|
||||||
|
@ -92,7 +92,7 @@ module.exports = () => describe('basic RSA cryptography', function () {
|
||||||
const bits = 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
const message = crypto.generateSessionKey(openpgp.enums.symmetric.aes256);
|
||||||
disableNative();
|
disableNative();
|
||||||
const encryptedBn = await crypto.publicKey.rsa.encrypt(message, n, e);
|
const encryptedBn = await crypto.publicKey.rsa.encrypt(message, n, e);
|
||||||
enableNative();
|
enableNative();
|
||||||
|
@ -108,7 +108,7 @@ module.exports = () => describe('basic RSA cryptography', function () {
|
||||||
const bits = 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await random.getRandomBytes(64);
|
const message = random.getRandomBytes(64);
|
||||||
const hashName = 'sha256';
|
const hashName = 'sha256';
|
||||||
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName);
|
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName);
|
||||||
const hashed = await crypto.hash.digest(hashAlgo, message);
|
const hashed = await crypto.hash.digest(hashAlgo, message);
|
||||||
|
@ -123,7 +123,7 @@ module.exports = () => describe('basic RSA cryptography', function () {
|
||||||
const bits = 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await random.getRandomBytes(64);
|
const message = random.getRandomBytes(64);
|
||||||
const hashName = 'sha256';
|
const hashName = 'sha256';
|
||||||
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName);
|
const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName);
|
||||||
const hashed = await crypto.hash.digest(hashAlgo, message);
|
const hashed = await crypto.hash.digest(hashAlgo, message);
|
||||||
|
|
|
@ -15,7 +15,7 @@ async function getRandomBN(min, max) {
|
||||||
|
|
||||||
const modulus = max.sub(min);
|
const modulus = max.sub(min);
|
||||||
const bytes = modulus.byteLength();
|
const bytes = modulus.byteLength();
|
||||||
const r = new BN(await random.getRandomBytes(bytes + 8));
|
const r = new BN(random.getRandomBytes(bytes + 8));
|
||||||
return r.mod(modulus).add(min);
|
return r.mod(modulus).add(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2419,7 +2419,7 @@ aOU=
|
||||||
|
|
||||||
it('should encrypt using custom session key and decrypt using session key', async function () {
|
it('should encrypt using custom session key and decrypt using session key', async function () {
|
||||||
const sessionKey = {
|
const sessionKey = {
|
||||||
data: await crypto.generateSessionKey(openpgp.enums.symmetric.aes256),
|
data: crypto.generateSessionKey(openpgp.enums.symmetric.aes256),
|
||||||
algorithm: 'aes256'
|
algorithm: 'aes256'
|
||||||
};
|
};
|
||||||
const encOpt = {
|
const encOpt = {
|
||||||
|
@ -2442,7 +2442,7 @@ aOU=
|
||||||
|
|
||||||
it('should encrypt using custom session key and decrypt using private key', async function () {
|
it('should encrypt using custom session key and decrypt using private key', async function () {
|
||||||
const sessionKey = {
|
const sessionKey = {
|
||||||
data: await crypto.generateSessionKey(openpgp.enums.symmetric.aes128),
|
data: crypto.generateSessionKey(openpgp.enums.symmetric.aes128),
|
||||||
algorithm: 'aes128'
|
algorithm: 'aes128'
|
||||||
};
|
};
|
||||||
const encOpt = {
|
const encOpt = {
|
||||||
|
@ -3140,9 +3140,9 @@ aOU=
|
||||||
await stream.loadStreamsPonyfill();
|
await stream.loadStreamsPonyfill();
|
||||||
const ReadableStream = useNativeStream ? global.ReadableStream : stream.ReadableStream;
|
const ReadableStream = useNativeStream ? global.ReadableStream : stream.ReadableStream;
|
||||||
const data = new ReadableStream({
|
const data = new ReadableStream({
|
||||||
async pull(controller) {
|
pull(controller) {
|
||||||
if (i++ < 4) {
|
if (i++ < 4) {
|
||||||
const randomBytes = await random.getRandomBytes(10);
|
const randomBytes = random.getRandomBytes(10);
|
||||||
controller.enqueue(randomBytes);
|
controller.enqueue(randomBytes);
|
||||||
plaintext.push(randomBytes.slice());
|
plaintext.push(randomBytes.slice());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -977,7 +977,7 @@ module.exports = () => describe('Streaming', function() {
|
||||||
if (test === currentTest && i < (expectedType === 'web' ? 100 : 500)) {
|
if (test === currentTest && i < (expectedType === 'web' ? 100 : 500)) {
|
||||||
i++;
|
i++;
|
||||||
if (i === 4) await dataArrivedPromise;
|
if (i === 4) await dataArrivedPromise;
|
||||||
const randomBytes = await random.getRandomBytes(1024);
|
const randomBytes = random.getRandomBytes(1024);
|
||||||
controller.enqueue(randomBytes);
|
controller.enqueue(randomBytes);
|
||||||
plaintext.push(randomBytes);
|
plaintext.push(randomBytes);
|
||||||
} else {
|
} else {
|
||||||
|
@ -997,7 +997,7 @@ module.exports = () => describe('Streaming', function() {
|
||||||
if (test === currentTest && i < (expectedType === 'web' ? 100 : 500)) {
|
if (test === currentTest && i < (expectedType === 'web' ? 100 : 500)) {
|
||||||
i++;
|
i++;
|
||||||
if (i === 4) await dataArrivedPromise;
|
if (i === 4) await dataArrivedPromise;
|
||||||
const randomBytes = await random.getRandomBytes(1024);
|
const randomBytes = random.getRandomBytes(1024);
|
||||||
plaintext.push(randomBytes);
|
plaintext.push(randomBytes);
|
||||||
if (!this.push(randomBytes)) break;
|
if (!this.push(randomBytes)) break;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user