Don't export default objects / namespaces

Import individual functions, instead.
This commit is contained in:
Daniel Huigens 2020-06-26 19:46:06 +02:00
parent f276e1ef51
commit b3e08fdc26
40 changed files with 1746 additions and 1845 deletions

View File

@ -24,7 +24,7 @@
* @module cleartext
*/
import armor from './encoding/armor';
import { armor, unarmor } from './encoding/armor';
import enums from './enums';
import util from './util';
import { PacketList, LiteralDataPacket, SignaturePacket } from './packet';
@ -140,7 +140,7 @@ export class CleartextMessage {
text: this.text,
data: this.signature.packets.write()
};
return armor.encode(enums.armor.signed, body);
return armor(enums.armor.signed, body);
}
/**
@ -162,7 +162,7 @@ export class CleartextMessage {
* @static
*/
export async function readArmoredCleartextMessage(armoredText) {
const input = await armor.decode(armoredText);
const input = await unarmor(armoredText);
if (input.type !== enums.armor.signed) {
throw new Error('No cleartext signed message.');
}

View File

@ -23,10 +23,17 @@
* @module crypto/aes_kw
*/
import cipher from './cipher';
import * as cipher from './cipher';
import util from '../util';
function wrap(key, data) {
/**
* AES key wrap
* @function
* @param {String} key
* @param {String} data
* @returns {Uint8Array}
*/
export function wrap(key, data) {
const aes = new cipher["aes" + (key.length * 8)](key);
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
const P = unpack(data);
@ -58,7 +65,15 @@ function wrap(key, data) {
return pack(A, R);
}
function unwrap(key, data) {
/**
* AES key unwrap
* @function
* @param {String} key
* @param {String} data
* @returns {Uint8Array}
* @throws {Error}
*/
export function unwrap(key, data) {
const aes = new cipher["aes" + (key.length * 8)](key);
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
const C = unpack(data);
@ -131,23 +146,3 @@ function pack() {
}
return new Uint8Array(buffer);
}
export default {
/**
* AES key wrap
* @function
* @param {String} key
* @param {String} data
* @returns {Uint8Array}
*/
wrap,
/**
* AES key unwrap
* @function
* @param {String} key
* @param {String} data
* @returns {Uint8Array}
* @throws {Error}
*/
unwrap
};

View File

@ -27,7 +27,7 @@
import { AES_CFB } from 'asmcrypto.js/dist_es8/aes/cfb';
import stream from 'web-stream-tools';
import cipher from './cipher';
import * as cipher from './cipher';
import config from '../config';
import util from '../util';
@ -38,7 +38,6 @@ const Buffer = util.getNodeBuffer();
const knownAlgos = nodeCrypto ? nodeCrypto.getCiphers() : [];
const nodeAlgos = {
idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */
'3des': knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined,
tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined,
cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined,
blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined,
@ -48,8 +47,7 @@ const nodeAlgos = {
/* twofish is not implemented in OpenSSL */
};
export default {
encrypt: function(algo, key, plaintext, iv) {
export async function encrypt(algo, key, plaintext, iv) {
if (util.getNodeCrypto() && nodeAlgos[algo]) { // Node crypto library.
return nodeEncrypt(algo, key, plaintext, iv);
}
@ -80,9 +78,9 @@ export default {
return ciphertext.subarray(0, j);
};
return stream.transform(plaintext, process, process);
},
}
decrypt: async function(algo, key, ciphertext, iv) {
export async function decrypt(algo, key, ciphertext, iv) {
if (util.getNodeCrypto() && nodeAlgos[algo]) { // Node crypto library.
return nodeDecrypt(algo, key, ciphertext, iv);
}
@ -114,7 +112,6 @@ export default {
};
return stream.transform(ciphertext, process, process);
}
};
function aesEncrypt(algo, key, pt, iv) {
if (

View File

@ -432,7 +432,7 @@ function des_removePadding(message, padding) {
// added by Recurity Labs
function TripleDES(key) {
export function TripleDES(key) {
this.key = [];
for (let i = 0; i < 3; i++) {
@ -459,7 +459,7 @@ TripleDES.blockSize = TripleDES.prototype.blockSize = 8;
// This is "original" DES
function DES(key) {
export function DES(key) {
this.key = key;
this.encrypt = function(block, padding) {
@ -472,5 +472,3 @@ function DES(key) {
return des(keys, block, false, 0, null, padding);
};
}
export default { DES, TripleDES };

View File

@ -9,12 +9,11 @@
*/
import aes from './aes';
import des from './des.js';
import cast5 from './cast5';
import twofish from './twofish';
import blowfish from './blowfish';
import { DES, TripleDES } from './des.js';
import Cast5 from './cast5';
import TF from './twofish';
import BF from './blowfish';
export default {
/**
* AES-128 encryption and decryption (ID 7)
* @function
@ -24,7 +23,7 @@ export default {
* @returns {Object}
* @requires asmcrypto.js
*/
aes128: aes(128),
export const aes128 = aes(128);
/**
* AES-128 Block Cipher (ID 8)
* @function
@ -34,7 +33,7 @@ export default {
* @returns {Object}
* @requires asmcrypto.js
*/
aes192: aes(192),
export const aes192 = aes(192);
/**
* AES-128 Block Cipher (ID 9)
* @function
@ -44,9 +43,9 @@ export default {
* @returns {Object}
* @requires asmcrypto.js
*/
aes256: aes(256),
export const aes256 = aes(256);
// Not in OpenPGP specifications
des: des.DES,
export const des = DES;
/**
* Triple DES Block Cipher (ID 2)
* @function
@ -54,8 +53,7 @@ export default {
* @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67}
* @returns {Object}
*/
tripledes: des.TripleDES,
'3des': des.TripleDES,
export const tripledes = TripleDES;
/**
* CAST-128 Block Cipher (ID 3)
* @function
@ -63,7 +61,7 @@ export default {
* @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm}
* @returns {Object}
*/
cast5: cast5,
export const cast5 = Cast5;
/**
* Twofish Block Cipher (ID 10)
* @function
@ -71,7 +69,7 @@ export default {
* @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH}
* @returns {Object}
*/
twofish: twofish,
export const twofish = TF;
/**
* Blowfish Block Cipher (ID 4)
* @function
@ -79,13 +77,12 @@ export default {
* @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH}
* @returns {Object}
*/
blowfish: blowfish,
export const blowfish = BF;
/**
* Not implemented
* @function
* @throws {Error}
*/
idea: function() {
export const idea = function() {
throw new Error('IDEA symmetric-key algorithm not implemented');
}
};

View File

@ -33,17 +33,17 @@
*/
import publicKey from './public_key';
import cipher from './cipher';
import random from './random';
import * as cipher from './cipher';
import { getRandomBytes } from './random';
import type_ecdh_symkey from '../type/ecdh_symkey';
import KDFParams from '../type/kdf_params';
import type_mpi from '../type/mpi';
import enums from '../enums';
import util from '../util';
import OID from '../type/oid';
import Curve from './public_key/elliptic/curves';
import { Curve } from './public_key/elliptic/curves';
function constructParams(types, data) {
export function constructParams(types, data) {
return types.map(function(type, i) {
if (data && data[i]) {
return new type(data[i]);
@ -52,7 +52,6 @@ function constructParams(types, data) {
});
}
export default {
/**
* Encrypts data using specified algorithm and public key parameters.
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
@ -64,8 +63,8 @@ export default {
* module:type/ecdh_symkey>} encrypted session key parameters
* @async
*/
publicKeyEncrypt: async function(algo, publicParams, data, fingerprint) {
const types = this.getEncSessionKeyParamTypes(algo);
export async function publicKeyEncrypt(algo, publicParams, data, fingerprint) {
const types = getEncSessionKeyParamTypes(algo);
switch (algo) {
case enums.publicKey.rsaEncrypt:
case enums.publicKey.rsaEncryptSign: {
@ -87,7 +86,7 @@ export default {
default:
return [];
}
},
}
/**
* Decrypts data using specified algorithm and private key parameters.
@ -102,7 +101,7 @@ export default {
* @returns {Uint8Array} decrypted data
* @async
*/
publicKeyDecrypt: async function(algo, publicKeyParams, privateKeyParams, data_params, fingerprint) {
export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, data_params, fingerprint) {
switch (algo) {
case enums.publicKey.rsaEncryptSign:
case enums.publicKey.rsaEncrypt: {
@ -129,7 +128,7 @@ export default {
default:
throw new Error('Invalid public key encryption algorithm.');
}
},
}
/**
* Parse public key material in binary form to get the key parameters
@ -138,7 +137,7 @@ export default {
* @returns {Object} key parameters referenced by name
* @returns { read: Number, publicParams: Object } number of read bytes plus key parameters referenced by name
*/
parsePublicKeyParams: function(algo, bytes) {
export function parsePublicKeyParams(algo, bytes) {
let read = 0;
switch (algo) {
case enums.publicKey.rsaEncrypt:
@ -182,7 +181,7 @@ export default {
default:
throw new Error('Invalid public key encryption algorithm.');
}
},
}
/**
* Parse private key material in binary form to get the key parameters
@ -191,7 +190,7 @@ export default {
* @param {Object} publicParams (ECC only) public params, needed to format some private params
* @returns { read: Number, privateParams: Object } number of read bytes plus the key parameters referenced by name
*/
parsePrivateKeyParams: function(algo, bytes, publicParams) {
export function parsePrivateKeyParams(algo, bytes, publicParams) {
let read = 0;
switch (algo) {
case enums.publicKey.rsaEncrypt:
@ -223,13 +222,13 @@ export default {
default:
throw new Error('Invalid public key encryption algorithm.');
}
},
}
/** Returns the types comprising the encrypted session key of an algorithm
* @param {module:enums.publicKey} algo The public key algorithm
* @returns {Array<Object>} The array of types
*/
getEncSessionKeyParamTypes: function(algo) {
export function getEncSessionKeyParamTypes(algo) {
switch (algo) {
// Algorithm-Specific Fields for RSA encrypted session keys:
// - MPI of RSA encrypted value m**e mod n.
@ -250,7 +249,7 @@ export default {
default:
throw new Error('Invalid public key encryption algorithm.');
}
},
}
/**
* Convert params to MPI and serializes them in the proper order
@ -258,13 +257,13 @@ export default {
* @param {Object} params The key parameters indexed by name
* @returns {Uint8Array} The array containing the MPIs
*/
serializeKeyParams: function(algo, params) {
export function serializeKeyParams(algo, params) {
const orderedParams = Object.keys(params).map(name => {
const param = params[name];
return util.isUint8Array(param) ? util.uint8ArrayToMpi(param) : param.write();
});
return util.concatUint8Array(orderedParams);
},
}
/**
* Generate algorithm-specific key parameters
@ -274,7 +273,7 @@ export default {
* @returns { publicParams, privateParams: {Object} } The parameters referenced by name
* @async
*/
generateParams: function(algo, bits, oid) {
export function generateParams(algo, bits, oid) {
switch (algo) {
case enums.publicKey.rsaEncrypt:
case enums.publicKey.rsaEncryptSign:
@ -309,7 +308,7 @@ export default {
default:
throw new Error('Invalid public key algorithm.');
}
},
}
/**
* Validate algorithm-specific key parameters
@ -319,7 +318,7 @@ export default {
* @returns {Promise<Boolean>} whether the parameters are valid
* @async
*/
validateParams: async function(algo, publicParams, privateParams) {
export async function validateParams(algo, publicParams, privateParams) {
if (!publicParams || !privateParams) {
throw new Error('Missing key parameters');
}
@ -356,7 +355,7 @@ export default {
default:
throw new Error('Invalid public key algorithm.');
}
},
}
/**
* Generates a random byte prefix for the specified algorithm
@ -365,11 +364,11 @@ export default {
* @returns {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated.
* @async
*/
getPrefixRandom: async function(algo) {
const prefixrandom = await random.getRandomBytes(cipher[algo].blockSize);
export async function getPrefixRandom(algo) {
const prefixrandom = await getRandomBytes(cipher[algo].blockSize);
const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
return util.concat([prefixrandom, repeat]);
},
}
/**
* Generating a session key for the specified symmetric algorithm
@ -378,9 +377,6 @@ export default {
* @returns {Uint8Array} Random bytes as a string to be used as a key
* @async
*/
generateSessionKey: function(algo) {
return random.getRandomBytes(cipher[algo].keySize);
},
constructParams: constructParams
};
export function generateSessionKey(algo) {
return getRandomBytes(cipher[algo].keySize);
}

View File

@ -9,19 +9,19 @@
* @module crypto
*/
import cipher from './cipher';
import * as cipher from './cipher';
import hash from './hash';
import cfb from './cfb';
import * as cfb from './cfb';
import gcm from './gcm';
import eax from './eax';
import ocb from './ocb';
import publicKey from './public_key';
import signature from './signature';
import random from './random';
import pkcs1 from './pkcs1';
import pkcs5 from './pkcs5';
import crypto from './crypto';
import aes_kw from './aes_kw';
import * as signature from './signature';
import * as random from './random';
import * as pkcs1 from './pkcs1';
import * as pkcs5 from './pkcs5';
import * as crypto from './crypto';
import * as aes_kw from './aes_kw';
// TODO move cfb and gcm to cipher
const mod = {

View File

@ -22,7 +22,7 @@
* @module crypto/ocb
*/
import ciphers from './cipher';
import * as ciphers from './cipher';
import util from '../util';

View File

@ -25,14 +25,9 @@
* @module crypto/pkcs1
*/
import random from './random';
import { getRandomBytes } from './random';
import hash from './hash';
/** @namespace */
const eme = {};
/** @namespace */
const emsa = {};
/**
* ASN1 object identifiers for hashes
* @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2}
@ -62,7 +57,7 @@ async function getPkcs1Padding(length) {
const result = new Uint8Array(length);
let count = 0;
while (count < length) {
const randomBytes = await random.getRandomBytes(length - count);
const randomBytes = await getRandomBytes(length - count);
for (let i = 0; i < randomBytes.length; i++) {
if (randomBytes[i] !== 0) {
result[count++] = randomBytes[i];
@ -80,7 +75,7 @@ async function getPkcs1Padding(length) {
* @returns {Promise<Uint8Array>} EME-PKCS1 padded message
* @async
*/
eme.encode = async function(message, keyLength) {
export async function emeEncode(message, keyLength) {
const mLength = message.length;
// length checking
if (mLength > keyLength - 11) {
@ -98,7 +93,7 @@ eme.encode = async function(message, keyLength) {
// 0x00 bytes
encoded.set(message, keyLength - mLength);
return encoded;
};
}
/**
* Decode a EME-PKCS1-v1_5 padded message
@ -106,7 +101,7 @@ eme.encode = async function(message, keyLength) {
* @param {Uint8Array} encoded encoded message bytes
* @returns {Uint8Array} message
*/
eme.decode = function(encoded) {
export function emeDecode(encoded) {
let i = 2;
while (encoded[i] !== 0 && i < encoded.length) {
i++;
@ -117,7 +112,7 @@ eme.decode = function(encoded) {
return encoded.subarray(i);
}
throw new Error('Decryption error');
};
}
/**
* Create a EMSA-PKCS1-v1_5 padded message
@ -127,7 +122,7 @@ eme.decode = function(encoded) {
* @param {Integer} emLen intended length in octets of the encoded message
* @returns {Uint8Array} encoded message
*/
emsa.encode = async function(algo, hashed, emLen) {
export async function emsaEncode(algo, hashed, emLen) {
let i;
if (hashed.length !== hash.getHashByteLength(algo)) {
throw new Error('Invalid hash length');
@ -155,6 +150,4 @@ emsa.encode = async function(algo, hashed, emLen) {
EM.set(hashPrefix, emLen - tLen);
EM.set(hashed, emLen - hashed.length);
return EM;
};
export default { eme, emsa };
}

View File

@ -28,7 +28,7 @@ import util from '../util';
* @param {Uint8Array} message message to pad
* @returns {Uint8Array} padded message
*/
function encode(message) {
export function encode(message) {
const c = 8 - (message.length % 8);
const padded = new Uint8Array(message.length + c).fill(c);
padded.set(message);
@ -40,7 +40,7 @@ function encode(message) {
* @param {Uint8Array} message message to remove padding from
* @returns {Uint8Array} message without padding
*/
function decode(message) {
export function decode(message) {
const len = message.length;
if (len > 0) {
const c = message[len - 1];
@ -54,5 +54,3 @@ function decode(message) {
}
throw new Error('Invalid padding');
}
export default { encode, decode };

View File

@ -21,9 +21,9 @@
* @requires util
* @module crypto/public_key/dsa
*/
import random from '../random';
import { getRandomBigInteger } from '../random';
import util from '../../util';
import prime from './prime';
import { isProbablePrime } from './prime';
/*
TODO regarding the hash function, read:
@ -31,7 +31,6 @@ import prime from './prime';
https://tools.ietf.org/html/rfc4880#section-14
*/
export default {
/**
* DSA Sign function
* @param {Integer} hash_algo
@ -43,7 +42,7 @@ export default {
* @returns {{ r: Uint8Array, s: Uint8Array }}
* @async
*/
sign: async function(hash_algo, hashed, g, p, q, x) {
export async function sign(hash_algo, hashed, g, p, q, x) {
const BigInteger = await util.getBigInteger();
const one = new BigInteger(1);
p = new BigInteger(p);
@ -70,7 +69,7 @@ export default {
// or s = 0 if signatures are generated properly.
while (true) {
// See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
k = await random.getRandomBigInteger(one, q); // returns in [1, q-1]
k = await getRandomBigInteger(one, q); // returns in [1, q-1]
r = g.modExp(k, p).imod(q); // (g**k mod p) mod q
if (r.isZero()) {
continue;
@ -87,7 +86,7 @@ export default {
r: r.toUint8Array('be', q.byteLength()),
s: s.toUint8Array('be', q.byteLength())
};
},
}
/**
* DSA Verify function
@ -102,7 +101,7 @@ export default {
* @returns {boolean}
* @async
*/
verify: async function(hash_algo, r, s, hashed, g, p, q, y) {
export async function verify(hash_algo, r, s, hashed, g, p, q, y) {
const BigInteger = await util.getBigInteger();
const zero = new BigInteger(0);
r = new BigInteger(r);
@ -133,7 +132,7 @@ export default {
const t2 = y.modExp(u2, p); // y**u2 mod p
const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q
return v.equal(r);
},
}
/**
* Validate DSA parameters
@ -145,7 +144,7 @@ export default {
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
validateParams: async function (p, q, g, y, x) {
export async function validateParams(p, q, g, y, x) {
const BigInteger = await util.getBigInteger();
p = new BigInteger(p);
q = new BigInteger(q);
@ -177,7 +176,7 @@ export default {
*/
const qSize = new BigInteger(q.bitLength());
const n150 = new BigInteger(150);
if (qSize.lt(n150) || !(await prime.isProbablePrime(q, null, 32))) {
if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) {
return false;
}
@ -189,7 +188,7 @@ export default {
*/
x = new BigInteger(x);
const two = new BigInteger(2);
const r = await random.getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q
const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q
const rqx = q.mul(r).add(x);
if (!y.equal(g.modExp(rqx, p))) {
return false;
@ -197,4 +196,3 @@ export default {
return true;
}
};

View File

@ -23,10 +23,9 @@
*/
import util from '../../util';
import random from '../random';
import pkcs1 from '../pkcs1';
import { getRandomBigInteger } from '../random';
import { emeEncode, emeDecode } from '../pkcs1';
export default {
/**
* ElGamal Encryption function
* Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA)
@ -37,23 +36,23 @@ export default {
* @returns {{ c1: Uint8Array, c2: Uint8Array }}
* @async
*/
encrypt: async function(data, p, g, y) {
export async function encrypt(data, p, g, y) {
const BigInteger = await util.getBigInteger();
p = new BigInteger(p);
g = new BigInteger(g);
y = new BigInteger(y);
const padded = await pkcs1.eme.encode(data, p.byteLength());
const padded = await emeEncode(data, p.byteLength());
const m = new BigInteger(padded);
// OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ*
// hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2]
const k = await random.getRandomBigInteger(new BigInteger(1), p.dec());
const k = await getRandomBigInteger(new BigInteger(1), p.dec());
return {
c1: g.modExp(k, p).toUint8Array(),
c2: y.modExp(k, p).imul(m).imod(p).toUint8Array()
};
},
}
/**
* ElGamal Encryption function
@ -64,7 +63,7 @@ export default {
* @returns {Uint8Array} unpadded message
* @async
*/
decrypt: async function(c1, c2, p, x) {
export async function decrypt(c1, c2, p, x) {
const BigInteger = await util.getBigInteger();
c1 = new BigInteger(c1);
c2 = new BigInteger(c2);
@ -72,8 +71,8 @@ export default {
x = new BigInteger(x);
const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p);
return pkcs1.eme.decode(padded.toUint8Array('be', p.byteLength()));
},
return emeDecode(padded.toUint8Array('be', p.byteLength()));
}
/**
* Validate ElGamal parameters
@ -84,7 +83,7 @@ export default {
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
validateParams: async function (p, g, y, x) {
export async function validateParams(p, g, y, x) {
const BigInteger = await util.getBigInteger();
p = new BigInteger(p);
g = new BigInteger(g);
@ -136,7 +135,7 @@ export default {
*/
x = new BigInteger(x);
const two = new BigInteger(2);
const r = await random.getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1
const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1
const rqx = p.dec().imul(r).iadd(x);
if (!y.equal(g.modExp(rqx, p))) {
return false;
@ -144,4 +143,3 @@ export default {
return true;
}
};

View File

@ -28,7 +28,7 @@
*/
import nacl from 'tweetnacl/nacl-fast-light.js';
import random from '../../random';
import { getRandomBytes } from '../../random';
import enums from '../../../enums';
import util from '../../../util';
import OID from '../../../type/oid';
@ -186,7 +186,7 @@ class Curve {
case 'node':
return nodeGenKeyPair(this.name);
case 'curve25519': {
const privateKey = await random.getRandomBytes(32);
const privateKey = await getRandomBytes(32);
privateKey[0] = (privateKey[0] & 127) | 64;
privateKey[31] &= 248;
const secretKey = privateKey.slice().reverse();
@ -195,7 +195,7 @@ class Curve {
return { publicKey, privateKey };
}
case 'ed25519': {
const privateKey = await random.getRandomBytes(32);
const privateKey = await getRandomBytes(32);
const keyPair = nacl.sign.keyPair.fromSeed(privateKey);
const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]);
return { publicKey, privateKey };
@ -203,7 +203,7 @@ class Curve {
}
const indutnyCurve = await getIndutnyCurve(this.name);
keyPair = await indutnyCurve.genKeyPair({
entropy: util.uint8ArrayToStr(await random.getRandomBytes(32))
entropy: util.uint8ArrayToStr(await getRandomBytes(32))
});
return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) };
}
@ -291,10 +291,8 @@ async function validateStandardParams(algo, oid, Q, d) {
return true;
}
export default Curve;
export {
curves, webCurves, nodeCurves, generate, getPreferredHashAlgo, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams
Curve, curves, webCurves, nodeCurves, generate, getPreferredHashAlgo, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams
};
//////////////////////////

View File

@ -30,14 +30,14 @@
*/
import nacl from 'tweetnacl/nacl-fast-light.js';
import Curve, { jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams } from './curves';
import aes_kw from '../../aes_kw';
import cipher from '../../cipher';
import random from '../../random';
import { Curve, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams } from './curves';
import * as aes_kw from '../../aes_kw';
import * as cipher from '../../cipher';
import { getRandomBytes } from '../../random';
import hash from '../../hash';
import enums from '../../../enums';
import util from '../../../util';
import pkcs5 from '../../pkcs5';
import * as pkcs5 from '../../pkcs5';
import MPI from '../../../type/mpi';
import { keyFromPublic, keyFromPrivate, getIndutnyCurve } from './indutnyKey';
@ -52,7 +52,7 @@ const nodeCrypto = util.getNodeCrypto();
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
async function validateParams(oid, Q, d) {
export async function validateParams(oid, Q, d) {
return validateStandardParams(enums.publicKey.ecdh, oid, Q, d);
}
@ -102,7 +102,7 @@ async function kdf(hash_algo, X, length, param, stripLeading = false, stripTrail
async function genPublicEphemeralKey(curve, Q) {
switch (curve.type) {
case 'curve25519': {
const d = await random.getRandomBytes(32);
const d = await getRandomBytes(32);
const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d);
let { publicKey } = nacl.box.keyPair.fromSecretKey(secretKey);
publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]);
@ -134,7 +134,7 @@ async function genPublicEphemeralKey(curve, Q) {
* @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>}
* @async
*/
async function encrypt(oid, kdfParams, data, Q, fingerprint) {
export async function encrypt(oid, kdfParams, data, Q, fingerprint) {
const m = new MPI(pkcs5.encode(data));
const curve = new Curve(oid);
@ -196,7 +196,7 @@ async function genPrivateEphemeralKey(curve, V, Q, d) {
* @returns {Promise<Uint8Array>} Value derived from session key
* @async
*/
async function decrypt(oid, kdfParams, V, C, Q, d, fingerprint) {
export async function decrypt(oid, kdfParams, V, C, Q, d, fingerprint) {
const curve = new Curve(oid);
const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
@ -387,5 +387,3 @@ async function nodePublicEphemeralKey(curve, Q) {
const publicKey = new Uint8Array(sender.getPublicKey());
return { publicKey, sharedKey };
}
export default { encrypt, decrypt, genPublicEphemeralKey, genPrivateEphemeralKey, buildEcdhParam, kdf, webPublicEphemeralKey, webPrivateEphemeralKey, ellipticPublicEphemeralKey, ellipticPrivateEphemeralKey, nodePublicEphemeralKey, nodePrivateEphemeralKey, validateParams };

View File

@ -26,9 +26,9 @@
import enums from '../../../enums';
import util from '../../../util';
import random from '../../random';
import { getRandomBytes } from '../../random';
import hash from '../../hash';
import Curve, { webCurves, privateToJwk, rawPublicToJwk, validateStandardParams } from './curves';
import { Curve, webCurves, privateToJwk, rawPublicToJwk, validateStandardParams } from './curves';
import { getIndutnyCurve, keyFromPrivate, keyFromPublic } from './indutnyKey';
const webCrypto = util.getWebCrypto();
@ -46,7 +46,7 @@ const nodeCrypto = util.getNodeCrypto();
* s: Uint8Array}} Signature of the message
* @async
*/
async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
export async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
const curve = new Curve(oid);
if (message && !util.isStream(message)) {
const keyPair = { publicKey, privateKey };
@ -91,7 +91,7 @@ async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
* @returns {Boolean}
* @async
*/
async function verify(oid, hash_algo, signature, message, publicKey, hashed) {
export async function verify(oid, hash_algo, signature, message, publicKey, hashed) {
const curve = new Curve(oid);
if (message && !util.isStream(message)) {
switch (curve.type) {
@ -125,7 +125,7 @@ async function verify(oid, hash_algo, signature, message, publicKey, hashed) {
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
async function validateParams(oid, Q, d) {
export async function validateParams(oid, Q, d) {
const curve = new Curve(oid);
// Reject curves x25519 and ed25519
if (curve.keyType !== enums.publicKey.ecdsa) {
@ -137,7 +137,7 @@ async function validateParams(oid, Q, d) {
switch (curve.type) {
case 'web':
case 'node': {
const message = await random.getRandomBytes(8);
const message = await getRandomBytes(8);
const hashAlgo = enums.hash.sha256;
const hashed = await hash.digest(hashAlgo, message);
try {
@ -152,8 +152,6 @@ async function validateParams(oid, Q, d) {
}
}
export default { sign, verify, ellipticVerify, ellipticSign, validateParams };
//////////////////////////
// //

View File

@ -42,7 +42,7 @@ nacl.hash = bytes => new Uint8Array(sha512().update(bytes).digest());
* S: Uint8Array}} Signature of the message
* @async
*/
async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
export async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]);
const signature = nacl.sign.detached(hashed, secretKey);
// EdDSA signature params are returned in little-endian format
@ -64,11 +64,10 @@ async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
* @returns {Boolean}
* @async
*/
async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) {
export async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) {
const signature = util.concatUint8Array([R, S]);
return nacl.sign.detached.verify(hashed, signature, publicKey.subarray(1));
}
/**
* Validate EdDSA parameters
* @param {module:type/oid} oid Elliptic curve object identifier
@ -77,7 +76,7 @@ async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) {
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
async function validateParams(oid, Q, k) {
export async function validateParams(oid, Q, k) {
// Check whether the given curve is supported
if (oid.getName() !== 'ed25519') {
return false;
@ -91,5 +90,3 @@ async function validateParams(oid, Q, k) {
const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix
return util.equalsUint8Array(Q, dG);
}
export default { sign, verify, validateParams };

View File

@ -24,11 +24,11 @@
* @module crypto/public_key/elliptic
*/
import Curve, { generate, getPreferredHashAlgo } from './curves';
import ecdsa from './ecdsa';
import eddsa from './eddsa';
import ecdh from './ecdh';
import { Curve, generate, getPreferredHashAlgo } from './curves';
import * as ecdsa from './ecdsa';
import * as eddsa from './eddsa';
import * as ecdh from './ecdh';
export default {
export {
Curve, ecdh, ecdsa, eddsa, generate, getPreferredHashAlgo
};

View File

@ -9,10 +9,10 @@
*/
import nacl from 'tweetnacl/nacl-fast-light.js';
import rsa from './rsa';
import elgamal from './elgamal';
import elliptic from './elliptic';
import dsa from './dsa';
import * as rsa from './rsa';
import * as elgamal from './elgamal';
import * as elliptic from './elliptic';
import * as dsa from './dsa';
export default {
/** @see module:crypto/public_key/rsa */

View File

@ -22,11 +22,7 @@
*/
import util from '../../util';
import random from '../random';
export default {
randomProbablePrime, isProbablePrime, fermat, millerRabin, divisionTest
};
import { getRandomBigInteger } from '../random';
/**
* Probabilistic random number generator
@ -36,7 +32,7 @@ export default {
* @returns BigInteger
* @async
*/
async function randomProbablePrime(bits, e, k) {
export async function randomProbablePrime(bits, e, k) {
const BigInteger = await util.getBigInteger();
const one = new BigInteger(1);
const min = one.leftShift(new BigInteger(bits - 1));
@ -49,7 +45,7 @@ async function randomProbablePrime(bits, e, k) {
*/
const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2];
const n = await random.getRandomBigInteger(min, min.leftShift(one));
const n = await getRandomBigInteger(min, min.leftShift(one));
let i = n.mod(thirty).toNumber();
do {
@ -72,7 +68,7 @@ async function randomProbablePrime(bits, e, k) {
* @returns {boolean}
* @async
*/
async function isProbablePrime(n, e, k) {
export async function isProbablePrime(n, e, k) {
if (e && !n.dec().gcd(e).isOne()) {
return false;
}
@ -97,13 +93,13 @@ async function isProbablePrime(n, e, k) {
* @param {BigInteger} b Optional Fermat test base
* @returns {boolean}
*/
async function fermat(n, b) {
export async function fermat(n, b) {
const BigInteger = await util.getBigInteger();
b = b || new BigInteger(2);
return b.modExp(n.dec(), n).isOne();
}
async function divisionTest(n) {
export async function divisionTest(n) {
const BigInteger = await util.getBigInteger();
return smallPrimes.every(m => {
return n.mod(new BigInteger(m)) !== 0;
@ -232,7 +228,7 @@ const smallPrimes = [
* @returns {boolean}
* @async
*/
async function millerRabin(n, k, rand) {
export async function millerRabin(n, k, rand) {
const BigInteger = await util.getBigInteger();
const len = n.bitLength();
@ -248,7 +244,7 @@ async function millerRabin(n, k, rand) {
const d = n.rightShift(new BigInteger(s));
for (; k > 0; k--) {
const a = rand ? rand() : await random.getRandomBigInteger(new BigInteger(2), n1);
const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1);
let x = a.modExp(d, n);
if (x.isOne() || x.equal(n1)) {

View File

@ -24,11 +24,11 @@
* @module crypto/public_key/rsa
*/
import prime from './prime';
import random from '../random';
import { randomProbablePrime } from './prime';
import { getRandomBigInteger } from '../random';
import config from '../../config';
import util from '../../util';
import pkcs1 from '../pkcs1';
import { emsaEncode, emeEncode, emeDecode } from '../pkcs1';
import enums from '../../enums';
const webCrypto = util.getWebCrypto();
@ -73,7 +73,6 @@ const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function (
}) : undefined;
/* eslint-enable no-invalid-this */
export default {
/** Create signature
* @param {module:enums.hash} hash_algo Hash algorithm
* @param {Uint8Array} data message
@ -87,20 +86,20 @@ export default {
* @returns {Uint8Array} RSA Signature
* @async
*/
sign: async function(hash_algo, data, n, e, d, p, q, u, hashed) {
export async function sign(hash_algo, data, n, e, d, p, q, u, hashed) {
if (data && !util.isStream(data)) {
if (util.getWebCrypto()) {
try {
return await this.webSign(enums.read(enums.webHash, hash_algo), data, n, e, d, p, q, u);
return await webSign(enums.read(enums.webHash, hash_algo), data, n, e, d, p, q, u);
} catch (err) {
util.printDebugError(err);
}
} else if (util.getNodeCrypto()) {
return this.nodeSign(hash_algo, data, n, e, d, p, q, u);
return nodeSign(hash_algo, data, n, e, d, p, q, u);
}
}
return this.bnSign(hash_algo, n, d, hashed);
},
return bnSign(hash_algo, n, d, hashed);
}
/**
* Verify signature
@ -113,20 +112,20 @@ export default {
* @returns {Boolean}
* @async
*/
verify: async function(hash_algo, data, s, n, e, hashed) {
export async function verify(hash_algo, data, s, n, e, hashed) {
if (data && !util.isStream(data)) {
if (util.getWebCrypto()) {
try {
return await this.webVerify(enums.read(enums.webHash, hash_algo), data, s, n, e);
return await webVerify(enums.read(enums.webHash, hash_algo), data, s, n, e);
} catch (err) {
util.printDebugError(err);
}
} else if (util.getNodeCrypto()) {
return this.nodeVerify(hash_algo, data, s, n, e);
return nodeVerify(hash_algo, data, s, n, e);
}
}
return this.bnVerify(hash_algo, s, n, e, hashed);
},
return bnVerify(hash_algo, s, n, e, hashed);
}
/**
* Encrypt message
@ -136,12 +135,12 @@ export default {
* @returns {Uint8Array} RSA Ciphertext
* @async
*/
encrypt: async function(data, n, e) {
export async function encrypt(data, n, e) {
if (util.getNodeCrypto()) {
return this.nodeEncrypt(data, n, e);
return nodeEncrypt(data, n, e);
}
return bnEncrypt(data, n, e);
}
return this.bnEncrypt(data, n, e);
},
/**
* Decrypt RSA message
@ -155,12 +154,12 @@ export default {
* @returns {String} RSA Plaintext
* @async
*/
decrypt: async function(data, n, e, d, p, q, u) {
export async function decrypt(data, n, e, d, p, q, u) {
if (util.getNodeCrypto()) {
return this.nodeDecrypt(data, n, e, d, p, q, u);
return nodeDecrypt(data, n, e, d, p, q, u);
}
return bnDecrypt(data, n, e, d, p, q, u);
}
return this.bnDecrypt(data, n, e, d, p, q, u);
},
/**
* Generate a new random private key B bits long with public exponent E.
@ -175,7 +174,7 @@ export default {
* RSA private prime p, RSA private prime q, u = p ** -1 mod q
* @async
*/
generate: async function(bits, e) {
export async function generate(bits, e) {
const BigInteger = await util.getBigInteger();
e = new BigInteger(e);
@ -265,8 +264,8 @@ export default {
// RSA keygen fallback using 40 iterations of the Miller-Rabin test
// See https://stackoverflow.com/a/6330138 for justification
// Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST
let q = await prime.randomProbablePrime(bits - (bits >> 1), e, 40);
let p = await prime.randomProbablePrime(bits >> 1, e, 40);
let q = await randomProbablePrime(bits - (bits >> 1), e, 40);
let p = await randomProbablePrime(bits >> 1, e, 40);
if (q.lt(p)) {
[p, q] = [q, p];
@ -282,7 +281,7 @@ export default {
// dq: d.mod(q.subn(1)),
u: p.modInv(q).toUint8Array()
};
},
}
/**
* Validate RSA parameters
@ -295,7 +294,7 @@ export default {
* @returns {Promise<Boolean>} whether params are valid
* @async
*/
validateParams: async function (n, e, d, p, q, u) {
export async function validateParams(n, e, d, p, q, u) {
const BigInteger = await util.getBigInteger();
n = new BigInteger(n);
p = new BigInteger(p);
@ -323,7 +322,7 @@ export default {
* We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1)
*/
const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3));
const r = await random.getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q
const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q
const rde = r.mul(d).mul(e);
const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r);
@ -332,20 +331,20 @@ export default {
}
return true;
},
}
bnSign: async function (hash_algo, n, d, hashed) {
async function bnSign(hash_algo, n, d, hashed) {
const BigInteger = await util.getBigInteger();
n = new BigInteger(n);
const m = new BigInteger(await pkcs1.emsa.encode(hash_algo, hashed, n.byteLength()));
const m = new BigInteger(await emsaEncode(hash_algo, hashed, n.byteLength()));
d = new BigInteger(d);
if (m.gte(n)) {
throw new Error('Message size cannot exceed modulus size');
}
return m.modExp(d, n).toUint8Array('be', n.byteLength());
},
}
webSign: async function (hash_name, data, n, e, d, p, q, u) {
async function webSign(hash_name, data, n, e, d, p, q, u) {
/** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q.
* We swap them in privateToJwk, so it usually works out, but nevertheless,
* not all OpenPGP keys are compatible with this requirement.
@ -360,9 +359,9 @@ export default {
const key = await webCrypto.importKey("jwk", jwk, algo, false, ["sign"]);
// add hash field for ms edge support
return new Uint8Array(await webCrypto.sign({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, data));
},
}
nodeSign: async function (hash_algo, data, n, e, d, p, q, u) {
async function nodeSign(hash_algo, data, n, e, d, p, q, u) {
const { default: BN } = await import('bn.js');
const pBNum = new BN(p);
const qBNum = new BN(q);
@ -393,9 +392,9 @@ export default {
label: 'RSA PRIVATE KEY'
});
return new Uint8Array(sign.sign(pem));
},
}
bnVerify: async function (hash_algo, s, n, e, hashed) {
async function bnVerify(hash_algo, s, n, e, hashed) {
const BigInteger = await util.getBigInteger();
n = new BigInteger(n);
s = new BigInteger(s);
@ -404,11 +403,11 @@ export default {
throw new Error('Signature size cannot exceed modulus size');
}
const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength());
const EM2 = await pkcs1.emsa.encode(hash_algo, hashed, n.byteLength());
const EM2 = await emsaEncode(hash_algo, hashed, n.byteLength());
return util.equalsUint8Array(EM1, EM2);
},
}
webVerify: async function (hash_name, data, s, n, e) {
async function webVerify(hash_name, data, s, n, e) {
const jwk = publicToJwk(n, e);
const key = await webCrypto.importKey("jwk", jwk, {
name: "RSASSA-PKCS1-v1_5",
@ -416,9 +415,9 @@ export default {
}, false, ["verify"]);
// add hash field for ms edge support
return webCrypto.verify({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, s, data);
},
}
nodeVerify: async function (hash_algo, data, s, n, e) {
async function nodeVerify(hash_algo, data, s, n, e) {
const { default: BN } = await import('bn.js');
const verify = nodeCrypto.createVerify(enums.read(enums.hash, hash_algo));
@ -442,9 +441,9 @@ export default {
} catch (err) {
return false;
}
},
}
nodeEncrypt: async function (data, n, e) {
async function nodeEncrypt(data, n, e) {
const { default: BN } = await import('bn.js');
const keyObject = {
@ -462,20 +461,20 @@ export default {
key = { key: pem, padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
}
return new Uint8Array(nodeCrypto.publicEncrypt(key, data));
},
}
bnEncrypt: async function (data, n, e) {
async function bnEncrypt(data, n, e) {
const BigInteger = await util.getBigInteger();
n = new BigInteger(n);
data = new BigInteger(await pkcs1.eme.encode(data, n.byteLength()));
data = new BigInteger(await emeEncode(data, n.byteLength()));
e = new BigInteger(e);
if (data.gte(n)) {
throw new Error('Message size cannot exceed modulus size');
}
return data.modExp(e, n).toUint8Array('be', n.byteLength());
},
}
nodeDecrypt: async function (data, n, e, d, p, q, u) {
async function nodeDecrypt(data, n, e, d, p, q, u) {
const { default: BN } = await import('bn.js');
const pBNum = new BN(p);
@ -511,9 +510,9 @@ export default {
} catch (err) {
throw new Error('Decryption error');
}
},
}
bnDecrypt: async function(data, n, e, d, p, q, u) {
async function bnDecrypt(data, n, e, d, p, q, u) {
const BigInteger = await util.getBigInteger();
data = new BigInteger(data);
n = new BigInteger(n);
@ -531,7 +530,7 @@ export default {
let blinder;
let unblinder;
if (config.rsaBlinding) {
unblinder = (await random.getRandomBigInteger(new BigInteger(2), n)).mod(n);
unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n);
blinder = unblinder.modInv(n).modExp(e, n);
data = data.mul(blinder).mod(n);
}
@ -546,11 +545,8 @@ export default {
result = result.mul(unblinder).mod(n);
}
return pkcs1.eme.decode(result.toUint8Array('be', n.byteLength()));
},
prime: prime
};
return emeDecode(result.toUint8Array('be', n.byteLength()));
}
/** Convert Openpgp private key params to jwk key according to
* @link https://tools.ietf.org/html/rfc7517

View File

@ -94,14 +94,13 @@ class RandomBuffer {
}
}
export default {
/**
* Retrieve secure random byte array of the specified length
* @param {Integer} length Length in bytes to generate
* @returns {Uint8Array} Random byte array
* @async
*/
getRandomBytes: async function(length) {
export async function getRandomBytes(length) {
const buf = new Uint8Array(length);
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
crypto.getRandomValues(buf);
@ -110,13 +109,13 @@ export default {
} else if (nodeCrypto) {
const bytes = nodeCrypto.randomBytes(buf.length);
buf.set(bytes);
} else if (this.randomBuffer.buffer) {
await this.randomBuffer.get(buf);
} else if (randomBuffer.buffer) {
await randomBuffer.get(buf);
} else {
throw new Error('No secure random number generator available.');
}
return buf;
},
}
/**
* Create a secure random BigInteger that is greater than or equal to min and less than max.
@ -125,7 +124,7 @@ export default {
* @returns {module:BigInteger} Random BigInteger
* @async
*/
getRandomBigInteger: async function(min, max) {
export async function getRandomBigInteger(min, max) {
const BigInteger = await util.getBigInteger();
if (max.lt(min)) {
@ -138,9 +137,8 @@ export default {
// Using a while loop is necessary to avoid bias introduced by the mod operation.
// However, we request 64 extra random bits so that the bias is negligible.
// Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
const r = new BigInteger(await this.getRandomBytes(bytes + 8));
const r = new BigInteger(await getRandomBytes(bytes + 8));
return r.mod(modulus).add(min);
},
}
randomBuffer: new RandomBuffer()
};
export const randomBuffer = new RandomBuffer();

View File

@ -1,18 +1,15 @@
/**
* @fileoverview Provides functions for asymmetric signing and signature verification
* @requires crypto/crypto
* @requires crypto/public_key
* @requires enums
* @requires util
* @module crypto/signature
*/
import crypto from './crypto';
import publicKey from './public_key';
import enums from '../enums';
import util from '../util';
export default {
/**
* Verifies the signature provided for data using specified algorithms and public key parameters.
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
@ -27,7 +24,7 @@ export default {
* @returns {Boolean} True if signature is valid
* @async
*/
verify: async function(algo, hash_algo, msg_MPIs, publicParams, data, hashed) {
export async function verify(algo, hash_algo, msg_MPIs, publicParams, data, hashed) {
switch (algo) {
case enums.publicKey.rsaEncryptSign:
case enums.publicKey.rsaEncrypt:
@ -59,7 +56,7 @@ export default {
default:
throw new Error('Invalid signature algorithm.');
}
},
}
/**
* Creates a signature on data using specified algorithms and private key parameters.
@ -75,7 +72,7 @@ export default {
* @returns {Uint8Array} Signature
* @async
*/
sign: async function(algo, hash_algo, publicKeyParams, privateKeyParams, data, hashed) {
export async function sign(algo, hash_algo, publicKeyParams, privateKeyParams, data, hashed) {
if (!publicKeyParams || !privateKeyParams) {
throw new Error('Missing key parameters');
}
@ -122,4 +119,3 @@ export default {
throw new Error('Invalid signature algorithm.');
}
}
};

View File

@ -25,7 +25,7 @@
*/
import stream from 'web-stream-tools';
import base64 from './base64.js';
import * as base64 from './base64.js';
import enums from '../enums.js';
import config from '../config';
import util from '../util';
@ -233,7 +233,7 @@ function splitChecksum(text) {
* @async
* @static
*/
function dearmor(input) {
export function unarmor(input) {
return new Promise(async (resolve, reject) => {
try {
const reSplit = /^-----[^-]+-----$/m;
@ -359,7 +359,7 @@ function dearmor(input) {
* @returns {String | ReadableStream<String>} Armored text
* @static
*/
function armor(messagetype, body, partindex, parttotal, customComment) {
export function armor(messagetype, body, partindex, parttotal, customComment) {
let text;
let hash;
if (messagetype === enums.armor.signed) {
@ -426,8 +426,3 @@ function armor(messagetype, body, partindex, parttotal, customComment) {
return util.concat(result);
}
export default {
encode: armor,
decode: dearmor
};

View File

@ -41,7 +41,7 @@ if (Buffer) {
* @returns {String | ReadableStream<String>} radix-64 version of input string
* @static
*/
function encode(data) {
export function encode(data) {
let buf = new Uint8Array();
return stream.transform(data, value => {
buf = util.concatUint8Array([buf, value]);
@ -65,7 +65,7 @@ function encode(data) {
* @returns {Uint8Array | ReadableStream<Uint8Array>} binary array version of input string
* @static
*/
function decode(data) {
export function decode(data) {
let buf = '';
return stream.transform(data, value => {
buf += value;
@ -92,5 +92,3 @@ function decode(data) {
return decoded;
}, () => decodeChunk(buf));
}
export default { encode, decode };

View File

@ -126,7 +126,6 @@ export default {
plaintext: 0,
/** Not implemented! */
idea: 1,
'3des': 2,
tripledes: 2,
cast5: 3,
blowfish: 4,

View File

@ -98,7 +98,7 @@ export { default as stream } from 'web-stream-tools';
* @see module:encoding/armor
* @name module:openpgp.armor
*/
export { default as armor } from './encoding/armor';
export * from './encoding/armor';
/**
* @see module:enums

View File

@ -33,7 +33,7 @@ import * as helper from './helper';
import enums from '../enums';
import util from '../util';
import config from '../config';
import armor from '../encoding/armor';
import { unarmor } from '../encoding/armor';
/**
* Generates a new OpenPGP key. Supports RSA and ECC keys.
@ -283,7 +283,7 @@ export async function readKey(data) {
* @static
*/
export async function readArmoredKey(armoredKey) {
const input = await armor.decode(armoredKey);
const input = await unarmor(armoredKey);
if (!(input.type === enums.armor.publicKey || input.type === enums.armor.privateKey)) {
throw new Error('Armored text not of type key');
}
@ -321,7 +321,7 @@ export async function readKeys(data) {
* @static
*/
export async function readArmoredKeys(armoredKey) {
const input = await armor.decode(armoredKey);
const input = await unarmor(armoredKey);
if (!(input.type === enums.armor.publicKey || input.type === enums.armor.privateKey)) {
throw new Error('Armored text not of type key');
}

View File

@ -25,7 +25,7 @@
* @module key/Key
*/
import armor from '../encoding/armor';
import { armor, unarmor } from '../encoding/armor';
import {
PacketList,
PublicKeyPacket,
@ -280,7 +280,7 @@ class Key {
*/
armor() {
const type = this.isPublic() ? enums.armor.publicKey : enums.armor.privateKey;
return armor.encode(type, this.toPacketlist().write());
return armor(type, this.toPacketlist().write());
}
/**
@ -749,7 +749,7 @@ class Key {
const revocationSignature = await helper.getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date);
const packetlist = new PacketList();
packetlist.push(revocationSignature);
return armor.encode(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate');
return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate');
}
/**
@ -761,7 +761,7 @@ class Key {
* @async
*/
async applyRevocationCertificate(revocationCertificate) {
const input = await armor.decode(revocationCertificate);
const input = await unarmor(revocationCertificate);
const packetlist = new PacketList();
await packetlist.read(input.data, { SignaturePacket });
const revocationSignature = packetlist.findPacket(enums.packet.signature);

View File

@ -30,7 +30,7 @@
*/
import stream from 'web-stream-tools';
import armor from './encoding/armor';
import { armor, unarmor } from './encoding/armor';
import type_keyid from './type/keyid';
import config from './config';
import crypto from './crypto';
@ -607,7 +607,7 @@ export class Message {
* @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature
*/
async appendSignature(detachedSignature) {
await this.packets.read(util.isUint8Array(detachedSignature) ? detachedSignature : (await armor.decode(detachedSignature)).data, { SignaturePacket });
await this.packets.read(util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, { SignaturePacket });
}
/**
@ -623,7 +623,7 @@ export class Message {
* @returns {ReadableStream<String>} ASCII armor
*/
armor() {
return armor.encode(enums.armor.message, this.write());
return armor(enums.armor.message, this.write());
}
/**
@ -816,7 +816,7 @@ export async function readArmoredMessage(armoredText) {
if (streamType === 'node') {
armoredText = stream.nodeToWeb(armoredText);
}
const input = await armor.decode(armoredText);
const input = await unarmor(armoredText);
return readMessage(input.data, streamType);
}

View File

@ -29,8 +29,7 @@ import stream from 'web-stream-tools';
import enums from '../enums';
import util from '../util';
export default {
readSimpleLength: function(bytes) {
export function readSimpleLength(bytes) {
let len = 0;
let offset;
const type = bytes[0];
@ -51,7 +50,7 @@ export default {
len: len,
offset: offset
};
},
}
/**
* Encodes a given integer of length to the openpgp length specifier to a
@ -60,7 +59,7 @@ export default {
* @param {Integer} length The length to encode
* @returns {Uint8Array} String with openpgp length representation
*/
writeSimpleLength: function(length) {
export function writeSimpleLength(length) {
if (length < 192) {
return new Uint8Array([length]);
} else if (length > 191 && length < 8384) {
@ -71,19 +70,19 @@ export default {
return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]);
}
return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]);
},
}
writePartialLength: function(power) {
export function writePartialLength(power) {
if (power < 0 || power > 30) {
throw new Error('Partial Length power must be between 1 and 30');
}
return new Uint8Array([224 + power]);
},
}
writeTag: function(tag_type) {
export function writeTag(tag_type) {
/* we're only generating v4 packet headers here */
return new Uint8Array([0xC0 | tag_type]);
},
}
/**
* Writes a packet header version 4 with the given tag_type and length to a
@ -93,17 +92,17 @@ export default {
* @param {Integer} length Length of the payload
* @returns {String} String of the header
*/
writeHeader: function(tag_type, length) {
export function writeHeader(tag_type, length) {
/* we're only generating v4 packet headers here */
return util.concatUint8Array([this.writeTag(tag_type), this.writeSimpleLength(length)]);
},
return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]);
}
/**
* Whether the packet type supports partial lengths per RFC4880
* @param {Integer} tag_type Tag type
* @returns {Boolean} String of the header
*/
supportsStreaming: function(tag_type) {
export function supportsStreaming(tag_type) {
return [
enums.packet.literalData,
enums.packet.compressedData,
@ -111,7 +110,7 @@ export default {
enums.packet.symEncryptedIntegrityProtectedData,
enums.packet.AEADEncryptedData
].includes(tag_type);
},
}
/**
* Generic static Packet Parser function
@ -120,7 +119,7 @@ export default {
* @param {Function} callback Function to call with the parsed packet
* @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise.
*/
read: async function(input, streaming, callback) {
export async function readPackets(input, streaming, callback) {
const reader = stream.getReader(input);
let writer;
let callbackReturned;
@ -150,9 +149,9 @@ export default {
packet_length_type = headerByte & 0x03; // bit 1-0
}
const supportsStreaming = this.supportsStreaming(tag);
const packetSupportsStreaming = supportsStreaming(tag);
let packet = null;
if (streaming && supportsStreaming) {
if (streaming && packetSupportsStreaming) {
const transform = new stream.TransformStream();
writer = stream.getWriter(transform.writable);
packet = transform.readable;
@ -209,7 +208,7 @@ export default {
} else if (lengthByte > 223 && lengthByte < 255) {
packet_length = 1 << (lengthByte & 0x1F);
wasPartialLength = true;
if (!supportsStreaming) {
if (!packetSupportsStreaming) {
throw new TypeError('This packet type does not support partial lengths.');
}
// 4.2.2.3. Five-Octet Lengths
@ -270,7 +269,7 @@ export default {
// Note that this means that if there's an error in the very end of the
// stream, such as an MDC error, we throw in step 5 instead of in step 8
// (or never), which is the point of this exercise.
const nextPacket = await reader.peekBytes(supportsStreaming ? Infinity : 2);
const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2);
if (writer) {
await writer.ready;
await writer.close();
@ -293,4 +292,3 @@ export default {
reader.releaseLock();
}
}
};

View File

@ -10,7 +10,11 @@
import stream from 'web-stream-tools';
import * as packets from './all_packets';
import packetParser from './packet';
import {
readPackets, supportsStreaming,
writeTag, writeHeader,
writePartialLength, writeSimpleLength
} from './packet';
import config from '../config';
import enums from '../enums';
import util from '../util';
@ -33,7 +37,7 @@ class PacketList extends Array {
try {
while (true) {
await writer.ready;
const done = await packetParser.read(readable, streaming, async parsed => {
const done = await readPackets(readable, streaming, async parsed => {
try {
const tag = enums.read(enums.packet, parsed.tag);
const packet = packets.newPacketFromTag(tag, allowedPackets);
@ -42,7 +46,7 @@ class PacketList extends Array {
await packet.read(parsed.packet, streaming);
await writer.write(packet);
} catch (e) {
if (!config.tolerant || packetParser.supportsStreaming(parsed.tag)) {
if (!config.tolerant || supportsStreaming(parsed.tag)) {
// The packets that support streaming are the ones that contain
// message data. Those are also the ones we want to be more strict
// about and throw on parse errors for.
@ -71,7 +75,7 @@ class PacketList extends Array {
} else {
this.stream = null;
}
if (done || packetParser.supportsStreaming(value.tag)) {
if (done || supportsStreaming(value.tag)) {
break;
}
}
@ -88,31 +92,31 @@ class PacketList extends Array {
for (let i = 0; i < this.length; i++) {
const packetbytes = this[i].write();
if (util.isStream(packetbytes) && packetParser.supportsStreaming(this[i].tag)) {
if (util.isStream(packetbytes) && supportsStreaming(this[i].tag)) {
let buffer = [];
let bufferLength = 0;
const minLength = 512;
arr.push(packetParser.writeTag(this[i].tag));
arr.push(writeTag(this[i].tag));
arr.push(stream.transform(packetbytes, value => {
buffer.push(value);
bufferLength += value.length;
if (bufferLength >= minLength) {
const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30);
const chunkSize = 2 ** powerOf2;
const bufferConcat = util.concat([packetParser.writePartialLength(powerOf2)].concat(buffer));
const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer));
buffer = [bufferConcat.subarray(1 + chunkSize)];
bufferLength = buffer[0].length;
return bufferConcat.subarray(0, 1 + chunkSize);
}
}, () => util.concat([packetParser.writeSimpleLength(bufferLength)].concat(buffer))));
}, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer))));
} else {
if (util.isStream(packetbytes)) {
let length = 0;
arr.push(stream.transform(stream.clone(packetbytes), value => {
length += value.length;
}, () => packetParser.writeHeader(this[i].tag, length)));
}, () => writeHeader(this[i].tag, length)));
} else {
arr.push(packetParser.writeHeader(this[i].tag, packetbytes.length));
arr.push(writeHeader(this[i].tag, packetbytes.length));
}
arr.push(packetbytes);
}

View File

@ -26,7 +26,7 @@
*/
import stream from 'web-stream-tools';
import packet from './packet';
import { readSimpleLength, writeSimpleLength } from './packet';
import type_keyid from '../type/keyid.js';
import type_mpi from '../type/mpi.js';
import crypto from '../crypto';
@ -319,7 +319,7 @@ class SignaturePacket {
arr.push(write_sub_packet(sub.issuerFingerprint, bytes));
}
this.unhashedSubpackets.forEach(data => {
arr.push(packet.writeSimpleLength(data.length));
arr.push(writeSimpleLength(data.length));
arr.push(data);
});
@ -535,7 +535,7 @@ class SignaturePacket {
// subpacket data set (zero or more subpackets)
while (i < 2 + subpacket_length) {
const len = packet.readSimpleLength(bytes.subarray(i, bytes.length));
const len = readSimpleLength(bytes.subarray(i, bytes.length));
i += len.offset;
this.read_sub_packet(bytes.subarray(i, i + len.len), trusted);
@ -767,7 +767,7 @@ class SignaturePacket {
*/
function write_sub_packet(type, data) {
const arr = [];
arr.push(packet.writeSimpleLength(data.length + 1));
arr.push(writeSimpleLength(data.length + 1));
arr.push(new Uint8Array([type]));
arr.push(data);
return util.concat(arr);

View File

@ -21,7 +21,7 @@
* @requires util
*/
import packet from './packet';
import { readSimpleLength, writeSimpleLength } from './packet';
import enums from '../enums';
import util from '../util';
@ -56,7 +56,7 @@ class UserAttributePacket {
read(bytes) {
let i = 0;
while (i < bytes.length) {
const len = packet.readSimpleLength(bytes.subarray(i, bytes.length));
const len = readSimpleLength(bytes.subarray(i, bytes.length));
i += len.offset;
this.attributes.push(util.uint8ArrayToStr(bytes.subarray(i, i + len.len)));
@ -71,7 +71,7 @@ class UserAttributePacket {
write() {
const arr = [];
for (let i = 0; i < this.attributes.length; i++) {
arr.push(packet.writeSimpleLength(this.attributes[i].length));
arr.push(writeSimpleLength(this.attributes[i].length));
arr.push(util.strToUint8Array(this.attributes[i]));
}
return util.concatUint8Array(arr);

View File

@ -22,7 +22,7 @@
* @module signature
*/
import armor from './encoding/armor';
import { armor, unarmor } from './encoding/armor';
import { PacketList, SignaturePacket } from './packet';
import enums from './enums';
@ -50,7 +50,7 @@ export class Signature {
* @returns {ReadableStream<String>} ASCII armor
*/
armor() {
return armor.encode(enums.armor.signature, this.write());
return armor(enums.armor.signature, this.write());
}
}
@ -62,7 +62,7 @@ export class Signature {
* @static
*/
export async function readArmoredSignature(armoredText) {
const input = await armor.decode(armoredText);
const input = await unarmor(armoredText);
return readSignature(input.data);
}

View File

@ -30,7 +30,7 @@ import emailAddresses from 'email-addresses';
import stream from 'web-stream-tools';
import config from './config';
import util from './util'; // re-import module to access util functions
import b64 from './encoding/base64';
import * as b64 from './encoding/base64';
import { getBigInteger } from './biginteger';
export default {

View File

@ -186,17 +186,17 @@ module.exports = () => describe('Elliptic Curve Cryptography @lightweight', func
]);
}
});
it('Invalid point', function () {
it('Invalid point', async function () {
if (!openpgp.config.useIndutnyElliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
if (openpgp.util.getNodeCrypto()) {
expect(verify_signature(
await expect(verify_signature(
'secp256k1', 8, [], [], [], secp256k1_invalid_point
)).to.eventually.be.false;
}
if (openpgp.config.useIndutnyElliptic) {
expect(verify_signature_elliptic(
await expect(verify_signature_elliptic(
'secp256k1', 8, [], [], [], secp256k1_invalid_point
)).to.be.rejectedWith(Error, /Invalid elliptic public key/);
}

View File

@ -377,8 +377,8 @@ NJCB6+LWtabSoVIjNVgKwyKqyTLaESNwC2ogZwkdE8qPGiDFEHo4Gg9zuRof
-----END PGP PUBLIC KEY BLOCK-----
`;
const { type, data } = await openpgp.armor.decode(pubKey);
const armor = await openpgp.stream.readToEnd(openpgp.armor.encode(type, data));
const { type, data } = await openpgp.unarmor(pubKey);
const armor = await openpgp.stream.readToEnd(openpgp.armor(type, data));
expect(
armor
.replace(/^(Version|Comment): .*$\r\n/mg, '')

View File

@ -2584,35 +2584,9 @@ function versionSpecificTests() {
}
module.exports = () => describe('Key', function() {
async function deepCopyKeyParams(params) {
const paramsCopy = {};
Object.keys(params).forEach(name => {
const param = params[name];
const copy = new Uint8Array(param.length);
copy.set(param);
paramsCopy[name] = copy;
});
return paramsCopy;
}
let rsaGenStub;
let v5KeysVal;
let aeadProtectVal;
const rsaGenValue = {
512: openpgp.crypto.publicKey.rsa.generate(512, 65537),
1024: openpgp.crypto.publicKey.rsa.generate(1024, 65537),
2048: openpgp.crypto.publicKey.rsa.generate(2048, 65537)
};
beforeEach(function() {
// We fake the generation function to speed up the tests
rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate');
rsaGenStub.callsFake(async N => deepCopyKeyParams(await rsaGenValue[N]));
});
afterEach(function() {
rsaGenStub.restore();
});
tryTests('V4', versionSpecificTests, {
if: !openpgp.config.ci,
@ -2706,7 +2680,7 @@ module.exports = () => describe('Key', function() {
const packetlist = new openpgp.PacketList();
await packetlist.read((await openpgp.armor.decode(pub_sig_test)).data, openpgp);
await packetlist.read((await openpgp.unarmor(pub_sig_test)).data, openpgp);
const subkeys = pubKey.getSubkeys();
expect(subkeys).to.exist;
@ -3132,10 +3106,10 @@ module.exports = () => describe('Key', function() {
const revKey = await openpgp.readArmoredKey(revoked_key_arm4);
const revocationCertificate = await revKey.getRevocationCertificate();
const input = await openpgp.armor.decode(revocation_certificate_arm4);
const input = await openpgp.unarmor(revocation_certificate_arm4);
const packetlist = new openpgp.PacketList();
await packetlist.read(input.data, { SignaturePacket: openpgp.SignaturePacket });
const armored = openpgp.armor.encode(openpgp.enums.armor.publicKey, packetlist.write());
const armored = openpgp.armor(openpgp.enums.armor.publicKey, packetlist.write());
expect(revocationCertificate.replace(/^Comment: .*$\r\n/mg, '')).to.equal(armored.replace(/^Comment: .*$\r\n/mg, ''));
});

View File

@ -549,29 +549,6 @@ function withCompression(tests) {
}
module.exports = () => describe('OpenPGP.js public api tests', function() {
async function deepCopyKeyParams(params) {
const paramsCopy = {};
Object.keys(params).forEach(name => {
const param = params[name];
const copy = new Uint8Array(param.length);
copy.set(param);
paramsCopy[name] = copy;
});
return paramsCopy;
}
let rsaGenStub;
const rsaGenValue = openpgp.crypto.publicKey.rsa.generate(openpgp.util.getWebCryptoAll() ? 2048 : 512, 65537);
beforeEach(function() {
// We fake the generation function to speed up the tests
rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate');
rsaGenStub.returns(async () => deepCopyKeyParams(await rsaGenValue()));
});
afterEach(function() {
rsaGenStub.restore();
});
describe('generateKey - validate user ids', function() {
it('should fail for invalid user name', async function() {

View File

@ -243,6 +243,9 @@ module.exports = () => describe("Packet", function() {
it('Sym. encrypted AEAD protected packet test vector (AEAD)', async function() {
// From https://gitlab.com/openpgp-wg/rfc4880bis/commit/00b20923e6233fb6ff1666ecd5acfefceb32907d
const nodeCrypto = openpgp.util.getNodeCrypto();
if (!nodeCrypto) return;
let packetBytes = openpgp.util.hexToUint8Array(`
d4 4a 01 07 01 0e b7 32 37 9f 73 c4 92 8d e2 5f
ac fe 65 17 ec 10 5d c1 1a 81 dc 0c b8 a2 f6 f3
@ -271,8 +274,8 @@ module.exports = () => describe("Packet", function() {
const msg2 = new openpgp.PacketList();
let randomBytesStub = stub(openpgp.crypto.random, 'getRandomBytes');
randomBytesStub.returns(resolves(iv));
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
randomBytesStub.returns(iv);
try {
await enc.encrypt(algo, key);
@ -298,7 +301,7 @@ module.exports = () => describe("Packet", function() {
'=VZ0/\n' +
'-----END PGP MESSAGE-----';
const msgbytes = (await openpgp.armor.decode(msg)).data;
const msgbytes = (await openpgp.unarmor(msg)).data;
const parsed = new openpgp.PacketList();
await parsed.read(msgbytes, openpgp);
@ -365,7 +368,7 @@ module.exports = () => describe("Packet", function() {
'-----END PGP PRIVATE KEY BLOCK-----';
let key = new openpgp.PacketList();
await key.read((await openpgp.armor.decode(armored_key)).data, openpgp);
await key.read((await openpgp.unarmor(armored_key)).data, openpgp);
key = key[0];
const enc = new openpgp.PublicKeyEncryptedSessionKeyPacket();
@ -432,11 +435,11 @@ module.exports = () => describe("Packet", function() {
'-----END PGP MESSAGE-----';
let key = new openpgp.PacketList();
await key.read((await openpgp.armor.decode(armored_key)).data, openpgp);
await key.read((await openpgp.unarmor(armored_key)).data, openpgp);
key = key[3];
const msg = new openpgp.PacketList();
await msg.read((await openpgp.armor.decode(armored_msg)).data, openpgp);
await msg.read((await openpgp.unarmor(armored_msg)).data, openpgp);
return msg[0].decrypt(key).then(async () => {
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
@ -521,6 +524,9 @@ module.exports = () => describe("Packet", function() {
it('Sym. encrypted session key reading/writing test vector (EAX, AEAD)', async function() {
// From https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b20923/back.mkd#sample-aead-eax-encryption-and-decryption
const nodeCrypto = openpgp.util.getNodeCrypto();
if (!nodeCrypto) return;
let aeadProtectVal = openpgp.config.aeadProtect;
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
let s2kIterationCountByteVal = openpgp.config.s2kIterationCountByte;
@ -533,11 +539,11 @@ module.exports = () => describe("Packet", function() {
let sessionIV = openpgp.util.hexToUint8Array(`bc 66 9e 34 e5 00 dc ae dc 5b 32 aa 2d ab 02 35`.replace(/\s+/g, ''));
let dataIV = openpgp.util.hexToUint8Array(`b7 32 37 9f 73 c4 92 8d e2 5f ac fe 65 17 ec 10`.replace(/\s+/g, ''));
let randomBytesStub = stub(openpgp.crypto.random, 'getRandomBytes');
randomBytesStub.onCall(0).returns(resolves(salt));
randomBytesStub.onCall(1).returns(resolves(sessionKey));
randomBytesStub.onCall(2).returns(resolves(sessionIV));
randomBytesStub.onCall(3).returns(resolves(dataIV));
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
randomBytesStub.onCall(0).returns(salt);
randomBytesStub.onCall(1).returns(sessionKey);
randomBytesStub.onCall(2).returns(sessionIV);
randomBytesStub.onCall(3).returns(dataIV);
let packetBytes = openpgp.util.hexToUint8Array(`
c3 3e 05 07 01 03 08 cd 5a 9f 70 fb e0 bc 65 90
@ -596,6 +602,9 @@ module.exports = () => describe("Packet", function() {
it('Sym. encrypted session key reading/writing test vector (AEAD, OCB)', async function() {
// From https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b20923/back.mkd#sample-aead-ocb-encryption-and-decryption
const nodeCrypto = openpgp.util.getNodeCrypto();
if (!nodeCrypto) return;
let aeadProtectVal = openpgp.config.aeadProtect;
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
let s2kIterationCountByteVal = openpgp.config.s2kIterationCountByte;
@ -608,11 +617,11 @@ module.exports = () => describe("Packet", function() {
let sessionIV = openpgp.util.hexToUint8Array(`99 e3 26 e5 40 0a 90 93 6c ef b4 e8 eb a0 8c`.replace(/\s+/g, ''));
let dataIV = openpgp.util.hexToUint8Array(`5e d2 bc 1e 47 0a be 8f 1d 64 4c 7a 6c 8a 56`.replace(/\s+/g, ''));
let randomBytesStub = stub(openpgp.crypto.random, 'getRandomBytes');
randomBytesStub.onCall(0).returns(resolves(salt));
randomBytesStub.onCall(1).returns(resolves(sessionKey));
randomBytesStub.onCall(2).returns(resolves(sessionIV));
randomBytesStub.onCall(3).returns(resolves(dataIV));
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
randomBytesStub.onCall(0).returns(salt);
randomBytesStub.onCall(1).returns(sessionKey);
randomBytesStub.onCall(2).returns(sessionIV);
randomBytesStub.onCall(3).returns(dataIV);
let packetBytes = openpgp.util.hexToUint8Array(`
c3 3d 05 07 02 03 08 9f 0b 7d a3 e5 ea 64 77 90
@ -683,12 +692,12 @@ module.exports = () => describe("Packet", function() {
'-----END PGP MESSAGE-----';
let key = new openpgp.PacketList();
await key.read((await openpgp.armor.decode(armored_key)).data, openpgp);
await key.read((await openpgp.unarmor(armored_key)).data, openpgp);
key = key[3];
await key.decrypt('test');
const msg = new openpgp.PacketList();
await msg.read((await openpgp.armor.decode(armored_msg)).data, openpgp);
await msg.read((await openpgp.unarmor(armored_msg)).data, openpgp);
return msg[0].decrypt(key).then(async () => {
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
@ -701,7 +710,7 @@ module.exports = () => describe("Packet", function() {
it('Secret key reading with signature verification.', async function() {
const key = new openpgp.PacketList();
await key.read((await openpgp.armor.decode(armored_key)).data, openpgp);
await key.read((await openpgp.unarmor(armored_key)).data, openpgp);
return Promise.all([
expect(key[2].verify(key[0],
openpgp.enums.signature.certGeneric,
@ -736,11 +745,11 @@ module.exports = () => describe("Packet", function() {
'-----END PGP MESSAGE-----';
const key = new openpgp.PacketList();
await key.read((await openpgp.armor.decode(armored_key)).data, openpgp);
await key.read((await openpgp.unarmor(armored_key)).data, openpgp);
await key[3].decrypt('test');
const msg = new openpgp.PacketList();
await msg.read((await openpgp.armor.decode(armored_msg)).data, openpgp);
await msg.read((await openpgp.unarmor(armored_msg)).data, openpgp);
return msg[0].decrypt(key[3]).then(async () => {
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);