Don't export default objects / namespaces
Import individual functions, instead.
This commit is contained in:
parent
f276e1ef51
commit
b3e08fdc26
|
@ -24,7 +24,7 @@
|
||||||
* @module cleartext
|
* @module cleartext
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import armor from './encoding/armor';
|
import { armor, unarmor } from './encoding/armor';
|
||||||
import enums from './enums';
|
import enums from './enums';
|
||||||
import util from './util';
|
import util from './util';
|
||||||
import { PacketList, LiteralDataPacket, SignaturePacket } from './packet';
|
import { PacketList, LiteralDataPacket, SignaturePacket } from './packet';
|
||||||
|
@ -140,7 +140,7 @@ export class CleartextMessage {
|
||||||
text: this.text,
|
text: this.text,
|
||||||
data: this.signature.packets.write()
|
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
|
* @static
|
||||||
*/
|
*/
|
||||||
export async function readArmoredCleartextMessage(armoredText) {
|
export async function readArmoredCleartextMessage(armoredText) {
|
||||||
const input = await armor.decode(armoredText);
|
const input = await unarmor(armoredText);
|
||||||
if (input.type !== enums.armor.signed) {
|
if (input.type !== enums.armor.signed) {
|
||||||
throw new Error('No cleartext signed message.');
|
throw new Error('No cleartext signed message.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,17 @@
|
||||||
* @module crypto/aes_kw
|
* @module crypto/aes_kw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import cipher from './cipher';
|
import * as cipher from './cipher';
|
||||||
import util from '../util';
|
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 aes = new cipher["aes" + (key.length * 8)](key);
|
||||||
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
|
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
|
||||||
const P = unpack(data);
|
const P = unpack(data);
|
||||||
|
@ -58,7 +65,15 @@ function wrap(key, data) {
|
||||||
return pack(A, R);
|
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 aes = new cipher["aes" + (key.length * 8)](key);
|
||||||
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
|
const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]);
|
||||||
const C = unpack(data);
|
const C = unpack(data);
|
||||||
|
@ -131,23 +146,3 @@ function pack() {
|
||||||
}
|
}
|
||||||
return new Uint8Array(buffer);
|
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
|
|
||||||
};
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
import { AES_CFB } from 'asmcrypto.js/dist_es8/aes/cfb';
|
import { AES_CFB } from 'asmcrypto.js/dist_es8/aes/cfb';
|
||||||
|
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import cipher from './cipher';
|
import * as cipher from './cipher';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ const Buffer = util.getNodeBuffer();
|
||||||
const knownAlgos = nodeCrypto ? nodeCrypto.getCiphers() : [];
|
const knownAlgos = nodeCrypto ? nodeCrypto.getCiphers() : [];
|
||||||
const nodeAlgos = {
|
const nodeAlgos = {
|
||||||
idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */
|
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,
|
tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined,
|
||||||
cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined,
|
cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined,
|
||||||
blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined,
|
blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined,
|
||||||
|
@ -48,8 +47,7 @@ const nodeAlgos = {
|
||||||
/* twofish is not implemented in OpenSSL */
|
/* twofish is not implemented in OpenSSL */
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export async function encrypt(algo, key, plaintext, iv) {
|
||||||
encrypt: function(algo, key, plaintext, iv) {
|
|
||||||
if (util.getNodeCrypto() && nodeAlgos[algo]) { // Node crypto library.
|
if (util.getNodeCrypto() && nodeAlgos[algo]) { // Node crypto library.
|
||||||
return nodeEncrypt(algo, key, plaintext, iv);
|
return nodeEncrypt(algo, key, plaintext, iv);
|
||||||
}
|
}
|
||||||
|
@ -80,9 +78,9 @@ export default {
|
||||||
return ciphertext.subarray(0, j);
|
return ciphertext.subarray(0, j);
|
||||||
};
|
};
|
||||||
return stream.transform(plaintext, process, process);
|
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.
|
if (util.getNodeCrypto() && nodeAlgos[algo]) { // Node crypto library.
|
||||||
return nodeDecrypt(algo, key, ciphertext, iv);
|
return nodeDecrypt(algo, key, ciphertext, iv);
|
||||||
}
|
}
|
||||||
|
@ -113,8 +111,7 @@ export default {
|
||||||
return plaintext.subarray(0, j);
|
return plaintext.subarray(0, j);
|
||||||
};
|
};
|
||||||
return stream.transform(ciphertext, process, process);
|
return stream.transform(ciphertext, process, process);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function aesEncrypt(algo, key, pt, iv) {
|
function aesEncrypt(algo, key, pt, iv) {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -432,7 +432,7 @@ function des_removePadding(message, padding) {
|
||||||
|
|
||||||
// added by Recurity Labs
|
// added by Recurity Labs
|
||||||
|
|
||||||
function TripleDES(key) {
|
export function TripleDES(key) {
|
||||||
this.key = [];
|
this.key = [];
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
|
@ -459,7 +459,7 @@ TripleDES.blockSize = TripleDES.prototype.blockSize = 8;
|
||||||
|
|
||||||
// This is "original" DES
|
// This is "original" DES
|
||||||
|
|
||||||
function DES(key) {
|
export function DES(key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
||||||
this.encrypt = function(block, padding) {
|
this.encrypt = function(block, padding) {
|
||||||
|
@ -472,5 +472,3 @@ function DES(key) {
|
||||||
return des(keys, block, false, 0, null, padding);
|
return des(keys, block, false, 0, null, padding);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { DES, TripleDES };
|
|
||||||
|
|
|
@ -9,13 +9,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import aes from './aes';
|
import aes from './aes';
|
||||||
import des from './des.js';
|
import { DES, TripleDES } from './des.js';
|
||||||
import cast5 from './cast5';
|
import Cast5 from './cast5';
|
||||||
import twofish from './twofish';
|
import TF from './twofish';
|
||||||
import blowfish from './blowfish';
|
import BF from './blowfish';
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* AES-128 encryption and decryption (ID 7)
|
* AES-128 encryption and decryption (ID 7)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 128-bit key
|
* @param {String} key 128-bit key
|
||||||
|
@ -24,8 +23,8 @@ export default {
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
* @requires asmcrypto.js
|
* @requires asmcrypto.js
|
||||||
*/
|
*/
|
||||||
aes128: aes(128),
|
export const aes128 = aes(128);
|
||||||
/**
|
/**
|
||||||
* AES-128 Block Cipher (ID 8)
|
* AES-128 Block Cipher (ID 8)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 192-bit key
|
* @param {String} key 192-bit key
|
||||||
|
@ -34,8 +33,8 @@ export default {
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
* @requires asmcrypto.js
|
* @requires asmcrypto.js
|
||||||
*/
|
*/
|
||||||
aes192: aes(192),
|
export const aes192 = aes(192);
|
||||||
/**
|
/**
|
||||||
* AES-128 Block Cipher (ID 9)
|
* AES-128 Block Cipher (ID 9)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 256-bit key
|
* @param {String} key 256-bit key
|
||||||
|
@ -44,48 +43,46 @@ export default {
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
* @requires asmcrypto.js
|
* @requires asmcrypto.js
|
||||||
*/
|
*/
|
||||||
aes256: aes(256),
|
export const aes256 = aes(256);
|
||||||
// Not in OpenPGP specifications
|
// Not in OpenPGP specifications
|
||||||
des: des.DES,
|
export const des = DES;
|
||||||
/**
|
/**
|
||||||
* Triple DES Block Cipher (ID 2)
|
* Triple DES Block Cipher (ID 2)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 192-bit key
|
* @param {String} key 192-bit key
|
||||||
* @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67}
|
* @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67}
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
tripledes: des.TripleDES,
|
export const tripledes = TripleDES;
|
||||||
'3des': des.TripleDES,
|
/**
|
||||||
/**
|
|
||||||
* CAST-128 Block Cipher (ID 3)
|
* CAST-128 Block Cipher (ID 3)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 128-bit key
|
* @param {String} key 128-bit key
|
||||||
* @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm}
|
* @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm}
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
cast5: cast5,
|
export const cast5 = Cast5;
|
||||||
/**
|
/**
|
||||||
* Twofish Block Cipher (ID 10)
|
* Twofish Block Cipher (ID 10)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 256-bit key
|
* @param {String} key 256-bit key
|
||||||
* @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH}
|
* @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH}
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
twofish: twofish,
|
export const twofish = TF;
|
||||||
/**
|
/**
|
||||||
* Blowfish Block Cipher (ID 4)
|
* Blowfish Block Cipher (ID 4)
|
||||||
* @function
|
* @function
|
||||||
* @param {String} key 128-bit key
|
* @param {String} key 128-bit key
|
||||||
* @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH}
|
* @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH}
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
blowfish: blowfish,
|
export const blowfish = BF;
|
||||||
/**
|
/**
|
||||||
* Not implemented
|
* Not implemented
|
||||||
* @function
|
* @function
|
||||||
* @throws {Error}
|
* @throws {Error}
|
||||||
*/
|
*/
|
||||||
idea: function() {
|
export const idea = function() {
|
||||||
throw new Error('IDEA symmetric-key algorithm not implemented');
|
throw new Error('IDEA symmetric-key algorithm not implemented');
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,17 +33,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import publicKey from './public_key';
|
import publicKey from './public_key';
|
||||||
import cipher from './cipher';
|
import * as cipher from './cipher';
|
||||||
import random from './random';
|
import { getRandomBytes } from './random';
|
||||||
import type_ecdh_symkey from '../type/ecdh_symkey';
|
import type_ecdh_symkey from '../type/ecdh_symkey';
|
||||||
import KDFParams from '../type/kdf_params';
|
import KDFParams from '../type/kdf_params';
|
||||||
import type_mpi from '../type/mpi';
|
import type_mpi from '../type/mpi';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
import OID from '../type/oid';
|
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) {
|
return types.map(function(type, i) {
|
||||||
if (data && data[i]) {
|
if (data && data[i]) {
|
||||||
return new type(data[i]);
|
return new type(data[i]);
|
||||||
|
@ -52,8 +52,7 @@ function constructParams(types, data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* Encrypts data using specified algorithm and public key parameters.
|
* 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.
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
|
||||||
* @param {module:enums.publicKey} algo Public key algorithm
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
|
@ -64,8 +63,8 @@ export default {
|
||||||
* module:type/ecdh_symkey>} encrypted session key parameters
|
* module:type/ecdh_symkey>} encrypted session key parameters
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
publicKeyEncrypt: async function(algo, publicParams, data, fingerprint) {
|
export async function publicKeyEncrypt(algo, publicParams, data, fingerprint) {
|
||||||
const types = this.getEncSessionKeyParamTypes(algo);
|
const types = getEncSessionKeyParamTypes(algo);
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncrypt:
|
case enums.publicKey.rsaEncrypt:
|
||||||
case enums.publicKey.rsaEncryptSign: {
|
case enums.publicKey.rsaEncryptSign: {
|
||||||
|
@ -87,9 +86,9 @@ export default {
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts data using specified algorithm and private key parameters.
|
* Decrypts data using specified algorithm and private key parameters.
|
||||||
* See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3}
|
* See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3}
|
||||||
* @param {module:enums.publicKey} algo Public key algorithm
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
|
@ -102,7 +101,7 @@ export default {
|
||||||
* @returns {Uint8Array} decrypted data
|
* @returns {Uint8Array} decrypted data
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
publicKeyDecrypt: async function(algo, publicKeyParams, privateKeyParams, data_params, fingerprint) {
|
export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, data_params, fingerprint) {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncryptSign:
|
case enums.publicKey.rsaEncryptSign:
|
||||||
case enums.publicKey.rsaEncrypt: {
|
case enums.publicKey.rsaEncrypt: {
|
||||||
|
@ -129,16 +128,16 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key encryption algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse public key material in binary form to get the key parameters
|
* Parse public key material in binary form to get the key parameters
|
||||||
* @param {module:enums.publicKey} algo The key algorithm
|
* @param {module:enums.publicKey} algo The key algorithm
|
||||||
* @param {Uint8Array} bytes The key material to parse
|
* @param {Uint8Array} bytes The key material to parse
|
||||||
* @returns {Object} key parameters referenced by name
|
* @returns {Object} key parameters referenced by name
|
||||||
* @returns { read: Number, publicParams: Object } number of read bytes plus 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;
|
let read = 0;
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncrypt:
|
case enums.publicKey.rsaEncrypt:
|
||||||
|
@ -182,16 +181,16 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key encryption algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse private key material in binary form to get the key parameters
|
* Parse private key material in binary form to get the key parameters
|
||||||
* @param {module:enums.publicKey} algo The key algorithm
|
* @param {module:enums.publicKey} algo The key algorithm
|
||||||
* @param {Uint8Array} bytes The key material to parse
|
* @param {Uint8Array} bytes The key material to parse
|
||||||
* @param {Object} publicParams (ECC only) public params, needed to format some private params
|
* @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
|
* @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;
|
let read = 0;
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncrypt:
|
case enums.publicKey.rsaEncrypt:
|
||||||
|
@ -223,13 +222,13 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key encryption algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/** Returns the types comprising the encrypted session key of an algorithm
|
/** Returns the types comprising the encrypted session key of an algorithm
|
||||||
* @param {module:enums.publicKey} algo The public key algorithm
|
* @param {module:enums.publicKey} algo The public key algorithm
|
||||||
* @returns {Array<Object>} The array of types
|
* @returns {Array<Object>} The array of types
|
||||||
*/
|
*/
|
||||||
getEncSessionKeyParamTypes: function(algo) {
|
export function getEncSessionKeyParamTypes(algo) {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
// Algorithm-Specific Fields for RSA encrypted session keys:
|
// Algorithm-Specific Fields for RSA encrypted session keys:
|
||||||
// - MPI of RSA encrypted value m**e mod n.
|
// - MPI of RSA encrypted value m**e mod n.
|
||||||
|
@ -250,23 +249,23 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key encryption algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert params to MPI and serializes them in the proper order
|
* Convert params to MPI and serializes them in the proper order
|
||||||
* @param {module:enums.publicKey} algo The public key algorithm
|
* @param {module:enums.publicKey} algo The public key algorithm
|
||||||
* @param {Object} params The key parameters indexed by name
|
* @param {Object} params The key parameters indexed by name
|
||||||
* @returns {Uint8Array} The array containing the MPIs
|
* @returns {Uint8Array} The array containing the MPIs
|
||||||
*/
|
*/
|
||||||
serializeKeyParams: function(algo, params) {
|
export function serializeKeyParams(algo, params) {
|
||||||
const orderedParams = Object.keys(params).map(name => {
|
const orderedParams = Object.keys(params).map(name => {
|
||||||
const param = params[name];
|
const param = params[name];
|
||||||
return util.isUint8Array(param) ? util.uint8ArrayToMpi(param) : param.write();
|
return util.isUint8Array(param) ? util.uint8ArrayToMpi(param) : param.write();
|
||||||
});
|
});
|
||||||
return util.concatUint8Array(orderedParams);
|
return util.concatUint8Array(orderedParams);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate algorithm-specific key parameters
|
* Generate algorithm-specific key parameters
|
||||||
* @param {module:enums.publicKey} algo The public key algorithm
|
* @param {module:enums.publicKey} algo The public key algorithm
|
||||||
* @param {Integer} bits Bit length for RSA keys
|
* @param {Integer} bits Bit length for RSA keys
|
||||||
|
@ -274,7 +273,7 @@ export default {
|
||||||
* @returns { publicParams, privateParams: {Object} } The parameters referenced by name
|
* @returns { publicParams, privateParams: {Object} } The parameters referenced by name
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
generateParams: function(algo, bits, oid) {
|
export function generateParams(algo, bits, oid) {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncrypt:
|
case enums.publicKey.rsaEncrypt:
|
||||||
case enums.publicKey.rsaEncryptSign:
|
case enums.publicKey.rsaEncryptSign:
|
||||||
|
@ -309,9 +308,9 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key algorithm.');
|
throw new Error('Invalid public key algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate algorithm-specific key parameters
|
* Validate algorithm-specific key parameters
|
||||||
* @param {module:enums.publicKey} algo The public key algorithm
|
* @param {module:enums.publicKey} algo The public key algorithm
|
||||||
* @param {Object} publicParams Algorithm-specific public key parameters
|
* @param {Object} publicParams Algorithm-specific public key parameters
|
||||||
|
@ -319,7 +318,7 @@ export default {
|
||||||
* @returns {Promise<Boolean>} whether the parameters are valid
|
* @returns {Promise<Boolean>} whether the parameters are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
validateParams: async function(algo, publicParams, privateParams) {
|
export async function validateParams(algo, publicParams, privateParams) {
|
||||||
if (!publicParams || !privateParams) {
|
if (!publicParams || !privateParams) {
|
||||||
throw new Error('Missing key parameters');
|
throw new Error('Missing key parameters');
|
||||||
}
|
}
|
||||||
|
@ -356,31 +355,28 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key algorithm.');
|
throw new Error('Invalid public key algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a random byte prefix for the specified algorithm
|
* Generates a random byte prefix for the specified 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 {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated.
|
* @returns {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated.
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
getPrefixRandom: async function(algo) {
|
export async function getPrefixRandom(algo) {
|
||||||
const prefixrandom = await random.getRandomBytes(cipher[algo].blockSize);
|
const prefixrandom = await getRandomBytes(cipher[algo].blockSize);
|
||||||
const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
|
const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
|
||||||
return util.concat([prefixrandom, repeat]);
|
return util.concat([prefixrandom, repeat]);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {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
|
* @async
|
||||||
*/
|
*/
|
||||||
generateSessionKey: function(algo) {
|
export function generateSessionKey(algo) {
|
||||||
return random.getRandomBytes(cipher[algo].keySize);
|
return getRandomBytes(cipher[algo].keySize);
|
||||||
},
|
}
|
||||||
|
|
||||||
constructParams: constructParams
|
|
||||||
};
|
|
||||||
|
|
|
@ -9,19 +9,19 @@
|
||||||
* @module crypto
|
* @module crypto
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import cipher from './cipher';
|
import * as cipher from './cipher';
|
||||||
import hash from './hash';
|
import hash from './hash';
|
||||||
import cfb from './cfb';
|
import * as cfb from './cfb';
|
||||||
import gcm from './gcm';
|
import gcm from './gcm';
|
||||||
import eax from './eax';
|
import eax from './eax';
|
||||||
import ocb from './ocb';
|
import ocb from './ocb';
|
||||||
import publicKey from './public_key';
|
import publicKey from './public_key';
|
||||||
import signature from './signature';
|
import * as signature from './signature';
|
||||||
import random from './random';
|
import * as random from './random';
|
||||||
import pkcs1 from './pkcs1';
|
import * as pkcs1 from './pkcs1';
|
||||||
import pkcs5 from './pkcs5';
|
import * as pkcs5 from './pkcs5';
|
||||||
import crypto from './crypto';
|
import * as crypto from './crypto';
|
||||||
import aes_kw from './aes_kw';
|
import * as aes_kw from './aes_kw';
|
||||||
|
|
||||||
// TODO move cfb and gcm to cipher
|
// TODO move cfb and gcm to cipher
|
||||||
const mod = {
|
const mod = {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* @module crypto/ocb
|
* @module crypto/ocb
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ciphers from './cipher';
|
import * as ciphers from './cipher';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,9 @@
|
||||||
* @module crypto/pkcs1
|
* @module crypto/pkcs1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import random from './random';
|
import { getRandomBytes } from './random';
|
||||||
import hash from './hash';
|
import hash from './hash';
|
||||||
|
|
||||||
/** @namespace */
|
|
||||||
const eme = {};
|
|
||||||
/** @namespace */
|
|
||||||
const emsa = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN1 object identifiers for hashes
|
* ASN1 object identifiers for hashes
|
||||||
* @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2}
|
* @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);
|
const result = new Uint8Array(length);
|
||||||
let count = 0;
|
let count = 0;
|
||||||
while (count < length) {
|
while (count < length) {
|
||||||
const randomBytes = await random.getRandomBytes(length - count);
|
const randomBytes = await 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];
|
||||||
|
@ -80,7 +75,7 @@ async function getPkcs1Padding(length) {
|
||||||
* @returns {Promise<Uint8Array>} EME-PKCS1 padded message
|
* @returns {Promise<Uint8Array>} EME-PKCS1 padded message
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
eme.encode = async function(message, keyLength) {
|
export async function emeEncode(message, keyLength) {
|
||||||
const mLength = message.length;
|
const mLength = message.length;
|
||||||
// length checking
|
// length checking
|
||||||
if (mLength > keyLength - 11) {
|
if (mLength > keyLength - 11) {
|
||||||
|
@ -98,7 +93,7 @@ eme.encode = async function(message, keyLength) {
|
||||||
// 0x00 bytes
|
// 0x00 bytes
|
||||||
encoded.set(message, keyLength - mLength);
|
encoded.set(message, keyLength - mLength);
|
||||||
return encoded;
|
return encoded;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a EME-PKCS1-v1_5 padded message
|
* Decode a EME-PKCS1-v1_5 padded message
|
||||||
|
@ -106,7 +101,7 @@ eme.encode = async function(message, keyLength) {
|
||||||
* @param {Uint8Array} encoded encoded message bytes
|
* @param {Uint8Array} encoded encoded message bytes
|
||||||
* @returns {Uint8Array} message
|
* @returns {Uint8Array} message
|
||||||
*/
|
*/
|
||||||
eme.decode = function(encoded) {
|
export function emeDecode(encoded) {
|
||||||
let i = 2;
|
let i = 2;
|
||||||
while (encoded[i] !== 0 && i < encoded.length) {
|
while (encoded[i] !== 0 && i < encoded.length) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -117,7 +112,7 @@ eme.decode = function(encoded) {
|
||||||
return encoded.subarray(i);
|
return encoded.subarray(i);
|
||||||
}
|
}
|
||||||
throw new Error('Decryption error');
|
throw new Error('Decryption error');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a EMSA-PKCS1-v1_5 padded message
|
* 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
|
* @param {Integer} emLen intended length in octets of the encoded message
|
||||||
* @returns {Uint8Array} encoded message
|
* @returns {Uint8Array} encoded message
|
||||||
*/
|
*/
|
||||||
emsa.encode = async function(algo, hashed, emLen) {
|
export async function emsaEncode(algo, hashed, emLen) {
|
||||||
let i;
|
let i;
|
||||||
if (hashed.length !== hash.getHashByteLength(algo)) {
|
if (hashed.length !== hash.getHashByteLength(algo)) {
|
||||||
throw new Error('Invalid hash length');
|
throw new Error('Invalid hash length');
|
||||||
|
@ -155,6 +150,4 @@ emsa.encode = async function(algo, hashed, emLen) {
|
||||||
EM.set(hashPrefix, emLen - tLen);
|
EM.set(hashPrefix, emLen - tLen);
|
||||||
EM.set(hashed, emLen - hashed.length);
|
EM.set(hashed, emLen - hashed.length);
|
||||||
return EM;
|
return EM;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default { eme, emsa };
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import util from '../util';
|
||||||
* @param {Uint8Array} message message to pad
|
* @param {Uint8Array} message message to pad
|
||||||
* @returns {Uint8Array} padded message
|
* @returns {Uint8Array} padded message
|
||||||
*/
|
*/
|
||||||
function encode(message) {
|
export function encode(message) {
|
||||||
const c = 8 - (message.length % 8);
|
const c = 8 - (message.length % 8);
|
||||||
const padded = new Uint8Array(message.length + c).fill(c);
|
const padded = new Uint8Array(message.length + c).fill(c);
|
||||||
padded.set(message);
|
padded.set(message);
|
||||||
|
@ -40,7 +40,7 @@ function encode(message) {
|
||||||
* @param {Uint8Array} message message to remove padding from
|
* @param {Uint8Array} message message to remove padding from
|
||||||
* @returns {Uint8Array} message without padding
|
* @returns {Uint8Array} message without padding
|
||||||
*/
|
*/
|
||||||
function decode(message) {
|
export function decode(message) {
|
||||||
const len = message.length;
|
const len = message.length;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
const c = message[len - 1];
|
const c = message[len - 1];
|
||||||
|
@ -54,5 +54,3 @@ function decode(message) {
|
||||||
}
|
}
|
||||||
throw new Error('Invalid padding');
|
throw new Error('Invalid padding');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { encode, decode };
|
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
* @requires util
|
* @requires util
|
||||||
* @module crypto/public_key/dsa
|
* @module crypto/public_key/dsa
|
||||||
*/
|
*/
|
||||||
import random from '../random';
|
import { getRandomBigInteger } from '../random';
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import prime from './prime';
|
import { isProbablePrime } from './prime';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO regarding the hash function, read:
|
TODO regarding the hash function, read:
|
||||||
|
@ -31,8 +31,7 @@ import prime from './prime';
|
||||||
https://tools.ietf.org/html/rfc4880#section-14
|
https://tools.ietf.org/html/rfc4880#section-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* DSA Sign function
|
* DSA Sign function
|
||||||
* @param {Integer} hash_algo
|
* @param {Integer} hash_algo
|
||||||
* @param {Uint8Array} hashed
|
* @param {Uint8Array} hashed
|
||||||
|
@ -43,7 +42,7 @@ export default {
|
||||||
* @returns {{ r: Uint8Array, s: Uint8Array }}
|
* @returns {{ r: Uint8Array, s: Uint8Array }}
|
||||||
* @async
|
* @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 BigInteger = await util.getBigInteger();
|
||||||
const one = new BigInteger(1);
|
const one = new BigInteger(1);
|
||||||
p = new BigInteger(p);
|
p = new BigInteger(p);
|
||||||
|
@ -70,7 +69,7 @@ export default {
|
||||||
// or s = 0 if signatures are generated properly.
|
// or s = 0 if signatures are generated properly.
|
||||||
while (true) {
|
while (true) {
|
||||||
// See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
// 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
|
r = g.modExp(k, p).imod(q); // (g**k mod p) mod q
|
||||||
if (r.isZero()) {
|
if (r.isZero()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -87,9 +86,9 @@ export default {
|
||||||
r: r.toUint8Array('be', q.byteLength()),
|
r: r.toUint8Array('be', q.byteLength()),
|
||||||
s: s.toUint8Array('be', q.byteLength())
|
s: s.toUint8Array('be', q.byteLength())
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSA Verify function
|
* DSA Verify function
|
||||||
* @param {Integer} hash_algo
|
* @param {Integer} hash_algo
|
||||||
* @param {Uint8Array} r
|
* @param {Uint8Array} r
|
||||||
|
@ -102,7 +101,7 @@ export default {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
* @async
|
* @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 BigInteger = await util.getBigInteger();
|
||||||
const zero = new BigInteger(0);
|
const zero = new BigInteger(0);
|
||||||
r = new BigInteger(r);
|
r = new BigInteger(r);
|
||||||
|
@ -133,9 +132,9 @@ export default {
|
||||||
const t2 = y.modExp(u2, p); // y**u2 mod p
|
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
|
const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q
|
||||||
return v.equal(r);
|
return v.equal(r);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate DSA parameters
|
* Validate DSA parameters
|
||||||
* @param {Uint8Array} p DSA prime
|
* @param {Uint8Array} p DSA prime
|
||||||
* @param {Uint8Array} q DSA group order
|
* @param {Uint8Array} q DSA group order
|
||||||
|
@ -145,7 +144,7 @@ export default {
|
||||||
* @returns {Promise<Boolean>} whether params are valid
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
validateParams: async function (p, q, g, y, x) {
|
export async function validateParams(p, q, g, y, x) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
p = new BigInteger(p);
|
p = new BigInteger(p);
|
||||||
q = new BigInteger(q);
|
q = new BigInteger(q);
|
||||||
|
@ -177,7 +176,7 @@ export default {
|
||||||
*/
|
*/
|
||||||
const qSize = new BigInteger(q.bitLength());
|
const qSize = new BigInteger(q.bitLength());
|
||||||
const n150 = new BigInteger(150);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +188,11 @@ export default {
|
||||||
*/
|
*/
|
||||||
x = new BigInteger(x);
|
x = new BigInteger(x);
|
||||||
const two = new BigInteger(2);
|
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);
|
const rqx = q.mul(r).add(x);
|
||||||
if (!y.equal(g.modExp(rqx, p))) {
|
if (!y.equal(g.modExp(rqx, p))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -23,11 +23,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import random from '../random';
|
import { getRandomBigInteger } from '../random';
|
||||||
import pkcs1 from '../pkcs1';
|
import { emeEncode, emeDecode } from '../pkcs1';
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* ElGamal Encryption function
|
* ElGamal Encryption function
|
||||||
* Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA)
|
* Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA)
|
||||||
* @param {Uint8Array} data to be padded and encrypted
|
* @param {Uint8Array} data to be padded and encrypted
|
||||||
|
@ -37,25 +36,25 @@ export default {
|
||||||
* @returns {{ c1: Uint8Array, c2: Uint8Array }}
|
* @returns {{ c1: Uint8Array, c2: Uint8Array }}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
encrypt: async function(data, p, g, y) {
|
export async function encrypt(data, p, g, y) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
p = new BigInteger(p);
|
p = new BigInteger(p);
|
||||||
g = new BigInteger(g);
|
g = new BigInteger(g);
|
||||||
y = new BigInteger(y);
|
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);
|
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*
|
||||||
// hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2]
|
// 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 {
|
return {
|
||||||
c1: g.modExp(k, p).toUint8Array(),
|
c1: g.modExp(k, p).toUint8Array(),
|
||||||
c2: y.modExp(k, p).imul(m).imod(p).toUint8Array()
|
c2: y.modExp(k, p).imul(m).imod(p).toUint8Array()
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElGamal Encryption function
|
* ElGamal Encryption function
|
||||||
* @param {Uint8Array} c1
|
* @param {Uint8Array} c1
|
||||||
* @param {Uint8Array} c2
|
* @param {Uint8Array} c2
|
||||||
|
@ -64,7 +63,7 @@ export default {
|
||||||
* @returns {Uint8Array} unpadded message
|
* @returns {Uint8Array} unpadded message
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
decrypt: async function(c1, c2, p, x) {
|
export async function decrypt(c1, c2, p, x) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
c1 = new BigInteger(c1);
|
c1 = new BigInteger(c1);
|
||||||
c2 = new BigInteger(c2);
|
c2 = new BigInteger(c2);
|
||||||
|
@ -72,10 +71,10 @@ export default {
|
||||||
x = new BigInteger(x);
|
x = new BigInteger(x);
|
||||||
|
|
||||||
const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p);
|
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
|
* Validate ElGamal parameters
|
||||||
* @param {Uint8Array} p ElGamal prime
|
* @param {Uint8Array} p ElGamal prime
|
||||||
* @param {Uint8Array} g ElGamal group generator
|
* @param {Uint8Array} g ElGamal group generator
|
||||||
|
@ -84,7 +83,7 @@ export default {
|
||||||
* @returns {Promise<Boolean>} whether params are valid
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
validateParams: async function (p, g, y, x) {
|
export async function validateParams(p, g, y, x) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
p = new BigInteger(p);
|
p = new BigInteger(p);
|
||||||
g = new BigInteger(g);
|
g = new BigInteger(g);
|
||||||
|
@ -136,12 +135,11 @@ export default {
|
||||||
*/
|
*/
|
||||||
x = new BigInteger(x);
|
x = new BigInteger(x);
|
||||||
const two = new BigInteger(2);
|
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);
|
const rqx = p.dec().imul(r).iadd(x);
|
||||||
if (!y.equal(g.modExp(rqx, p))) {
|
if (!y.equal(g.modExp(rqx, p))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nacl from 'tweetnacl/nacl-fast-light.js';
|
import nacl from 'tweetnacl/nacl-fast-light.js';
|
||||||
import random from '../../random';
|
import { getRandomBytes } from '../../random';
|
||||||
import enums from '../../../enums';
|
import enums from '../../../enums';
|
||||||
import util from '../../../util';
|
import util from '../../../util';
|
||||||
import OID from '../../../type/oid';
|
import OID from '../../../type/oid';
|
||||||
|
@ -186,7 +186,7 @@ class Curve {
|
||||||
case 'node':
|
case 'node':
|
||||||
return nodeGenKeyPair(this.name);
|
return nodeGenKeyPair(this.name);
|
||||||
case 'curve25519': {
|
case 'curve25519': {
|
||||||
const privateKey = await random.getRandomBytes(32);
|
const privateKey = await 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();
|
||||||
|
@ -195,7 +195,7 @@ class Curve {
|
||||||
return { publicKey, privateKey };
|
return { publicKey, privateKey };
|
||||||
}
|
}
|
||||||
case 'ed25519': {
|
case 'ed25519': {
|
||||||
const privateKey = await random.getRandomBytes(32);
|
const privateKey = await 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 };
|
||||||
|
@ -203,7 +203,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.uint8ArrayToStr(await random.getRandomBytes(32))
|
entropy: util.uint8ArrayToStr(await 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) };
|
||||||
}
|
}
|
||||||
|
@ -291,10 +291,8 @@ async function validateStandardParams(algo, oid, Q, d) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Curve;
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
curves, webCurves, nodeCurves, generate, getPreferredHashAlgo, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams
|
Curve, curves, webCurves, nodeCurves, generate, getPreferredHashAlgo, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
|
@ -30,14 +30,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nacl from 'tweetnacl/nacl-fast-light.js';
|
import nacl from 'tweetnacl/nacl-fast-light.js';
|
||||||
import Curve, { jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams } from './curves';
|
import { Curve, jwkToRawPublic, rawPublicToJwk, privateToJwk, validateStandardParams } from './curves';
|
||||||
import aes_kw from '../../aes_kw';
|
import * as aes_kw from '../../aes_kw';
|
||||||
import cipher from '../../cipher';
|
import * as cipher from '../../cipher';
|
||||||
import random from '../../random';
|
import { getRandomBytes } from '../../random';
|
||||||
import hash from '../../hash';
|
import hash from '../../hash';
|
||||||
import enums from '../../../enums';
|
import enums from '../../../enums';
|
||||||
import util from '../../../util';
|
import util from '../../../util';
|
||||||
import pkcs5 from '../../pkcs5';
|
import * as pkcs5 from '../../pkcs5';
|
||||||
import MPI from '../../../type/mpi';
|
import MPI from '../../../type/mpi';
|
||||||
import { keyFromPublic, keyFromPrivate, getIndutnyCurve } from './indutnyKey';
|
import { keyFromPublic, keyFromPrivate, getIndutnyCurve } from './indutnyKey';
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ const nodeCrypto = util.getNodeCrypto();
|
||||||
* @returns {Promise<Boolean>} whether params are valid
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function validateParams(oid, Q, d) {
|
export async function validateParams(oid, Q, d) {
|
||||||
return validateStandardParams(enums.publicKey.ecdh, 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) {
|
async function genPublicEphemeralKey(curve, Q) {
|
||||||
switch (curve.type) {
|
switch (curve.type) {
|
||||||
case 'curve25519': {
|
case 'curve25519': {
|
||||||
const d = await random.getRandomBytes(32);
|
const d = await 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]);
|
||||||
|
@ -134,7 +134,7 @@ async function genPublicEphemeralKey(curve, Q) {
|
||||||
* @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>}
|
* @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>}
|
||||||
* @async
|
* @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 m = new MPI(pkcs5.encode(data));
|
||||||
|
|
||||||
const curve = new Curve(oid);
|
const curve = new Curve(oid);
|
||||||
|
@ -196,7 +196,7 @@ async function genPrivateEphemeralKey(curve, V, Q, d) {
|
||||||
* @returns {Promise<Uint8Array>} Value derived from session key
|
* @returns {Promise<Uint8Array>} Value derived from session key
|
||||||
* @async
|
* @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 curve = new Curve(oid);
|
||||||
const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
|
const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
|
||||||
const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
|
const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
|
||||||
|
@ -387,5 +387,3 @@ async function nodePublicEphemeralKey(curve, Q) {
|
||||||
const publicKey = new Uint8Array(sender.getPublicKey());
|
const publicKey = new Uint8Array(sender.getPublicKey());
|
||||||
return { publicKey, sharedKey };
|
return { publicKey, sharedKey };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { encrypt, decrypt, genPublicEphemeralKey, genPrivateEphemeralKey, buildEcdhParam, kdf, webPublicEphemeralKey, webPrivateEphemeralKey, ellipticPublicEphemeralKey, ellipticPrivateEphemeralKey, nodePublicEphemeralKey, nodePrivateEphemeralKey, validateParams };
|
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
|
|
||||||
import enums from '../../../enums';
|
import enums from '../../../enums';
|
||||||
import util from '../../../util';
|
import util from '../../../util';
|
||||||
import random from '../../random';
|
import { getRandomBytes } from '../../random';
|
||||||
import hash from '../../hash';
|
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';
|
import { getIndutnyCurve, keyFromPrivate, keyFromPublic } from './indutnyKey';
|
||||||
|
|
||||||
const webCrypto = util.getWebCrypto();
|
const webCrypto = util.getWebCrypto();
|
||||||
|
@ -46,7 +46,7 @@ const nodeCrypto = util.getNodeCrypto();
|
||||||
* s: Uint8Array}} Signature of the message
|
* s: Uint8Array}} Signature of the message
|
||||||
* @async
|
* @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);
|
const curve = new Curve(oid);
|
||||||
if (message && !util.isStream(message)) {
|
if (message && !util.isStream(message)) {
|
||||||
const keyPair = { publicKey, privateKey };
|
const keyPair = { publicKey, privateKey };
|
||||||
|
@ -91,7 +91,7 @@ async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) {
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
* @async
|
* @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);
|
const curve = new Curve(oid);
|
||||||
if (message && !util.isStream(message)) {
|
if (message && !util.isStream(message)) {
|
||||||
switch (curve.type) {
|
switch (curve.type) {
|
||||||
|
@ -125,7 +125,7 @@ async function verify(oid, hash_algo, signature, message, publicKey, hashed) {
|
||||||
* @returns {Promise<Boolean>} whether params are valid
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function validateParams(oid, Q, d) {
|
export async function validateParams(oid, Q, d) {
|
||||||
const curve = new Curve(oid);
|
const curve = new Curve(oid);
|
||||||
// Reject curves x25519 and ed25519
|
// Reject curves x25519 and ed25519
|
||||||
if (curve.keyType !== enums.publicKey.ecdsa) {
|
if (curve.keyType !== enums.publicKey.ecdsa) {
|
||||||
|
@ -137,7 +137,7 @@ async function validateParams(oid, Q, d) {
|
||||||
switch (curve.type) {
|
switch (curve.type) {
|
||||||
case 'web':
|
case 'web':
|
||||||
case 'node': {
|
case 'node': {
|
||||||
const message = await random.getRandomBytes(8);
|
const message = await 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 {
|
||||||
|
@ -152,8 +152,6 @@ async function validateParams(oid, Q, d) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { sign, verify, ellipticVerify, ellipticSign, validateParams };
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// //
|
// //
|
||||||
|
|
|
@ -42,7 +42,7 @@ nacl.hash = bytes => new Uint8Array(sha512().update(bytes).digest());
|
||||||
* S: Uint8Array}} Signature of the message
|
* S: Uint8Array}} Signature of the message
|
||||||
* @async
|
* @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 secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]);
|
||||||
const signature = nacl.sign.detached(hashed, secretKey);
|
const signature = nacl.sign.detached(hashed, secretKey);
|
||||||
// EdDSA signature params are returned in little-endian format
|
// 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}
|
* @returns {Boolean}
|
||||||
* @async
|
* @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]);
|
const signature = util.concatUint8Array([R, S]);
|
||||||
return nacl.sign.detached.verify(hashed, signature, publicKey.subarray(1));
|
return nacl.sign.detached.verify(hashed, signature, publicKey.subarray(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate EdDSA parameters
|
* Validate EdDSA parameters
|
||||||
* @param {module:type/oid} oid Elliptic curve object identifier
|
* @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
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function validateParams(oid, Q, k) {
|
export async function validateParams(oid, Q, k) {
|
||||||
// Check whether the given curve is supported
|
// Check whether the given curve is supported
|
||||||
if (oid.getName() !== 'ed25519') {
|
if (oid.getName() !== 'ed25519') {
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,5 +90,3 @@ async function validateParams(oid, Q, k) {
|
||||||
const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix
|
const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix
|
||||||
return util.equalsUint8Array(Q, dG);
|
return util.equalsUint8Array(Q, dG);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { sign, verify, validateParams };
|
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
* @module crypto/public_key/elliptic
|
* @module crypto/public_key/elliptic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Curve, { generate, getPreferredHashAlgo } from './curves';
|
import { Curve, generate, getPreferredHashAlgo } from './curves';
|
||||||
import ecdsa from './ecdsa';
|
import * as ecdsa from './ecdsa';
|
||||||
import eddsa from './eddsa';
|
import * as eddsa from './eddsa';
|
||||||
import ecdh from './ecdh';
|
import * as ecdh from './ecdh';
|
||||||
|
|
||||||
export default {
|
export {
|
||||||
Curve, ecdh, ecdsa, eddsa, generate, getPreferredHashAlgo
|
Curve, ecdh, ecdsa, eddsa, generate, getPreferredHashAlgo
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nacl from 'tweetnacl/nacl-fast-light.js';
|
import nacl from 'tweetnacl/nacl-fast-light.js';
|
||||||
import rsa from './rsa';
|
import * as rsa from './rsa';
|
||||||
import elgamal from './elgamal';
|
import * as elgamal from './elgamal';
|
||||||
import elliptic from './elliptic';
|
import * as elliptic from './elliptic';
|
||||||
import dsa from './dsa';
|
import * as dsa from './dsa';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/** @see module:crypto/public_key/rsa */
|
/** @see module:crypto/public_key/rsa */
|
||||||
|
|
|
@ -22,11 +22,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import random from '../random';
|
import { getRandomBigInteger } from '../random';
|
||||||
|
|
||||||
export default {
|
|
||||||
randomProbablePrime, isProbablePrime, fermat, millerRabin, divisionTest
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probabilistic random number generator
|
* Probabilistic random number generator
|
||||||
|
@ -36,7 +32,7 @@ export default {
|
||||||
* @returns BigInteger
|
* @returns BigInteger
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function randomProbablePrime(bits, e, k) {
|
export async function randomProbablePrime(bits, e, k) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
const one = new BigInteger(1);
|
const one = new BigInteger(1);
|
||||||
const min = one.leftShift(new BigInteger(bits - 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 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();
|
let i = n.mod(thirty).toNumber();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -72,7 +68,7 @@ async function randomProbablePrime(bits, e, k) {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function isProbablePrime(n, e, k) {
|
export async function isProbablePrime(n, e, k) {
|
||||||
if (e && !n.dec().gcd(e).isOne()) {
|
if (e && !n.dec().gcd(e).isOne()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -97,13 +93,13 @@ async function isProbablePrime(n, e, k) {
|
||||||
* @param {BigInteger} b Optional Fermat test base
|
* @param {BigInteger} b Optional Fermat test base
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
async function fermat(n, b) {
|
export async function fermat(n, b) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
b = b || new BigInteger(2);
|
b = b || new BigInteger(2);
|
||||||
return b.modExp(n.dec(), n).isOne();
|
return b.modExp(n.dec(), n).isOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function divisionTest(n) {
|
export async function divisionTest(n) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
return smallPrimes.every(m => {
|
return smallPrimes.every(m => {
|
||||||
return n.mod(new BigInteger(m)) !== 0;
|
return n.mod(new BigInteger(m)) !== 0;
|
||||||
|
@ -232,7 +228,7 @@ const smallPrimes = [
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function millerRabin(n, k, rand) {
|
export async function millerRabin(n, k, rand) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
const len = n.bitLength();
|
const len = n.bitLength();
|
||||||
|
|
||||||
|
@ -248,7 +244,7 @@ async function millerRabin(n, k, rand) {
|
||||||
const d = n.rightShift(new BigInteger(s));
|
const d = n.rightShift(new BigInteger(s));
|
||||||
|
|
||||||
for (; k > 0; k--) {
|
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);
|
let x = a.modExp(d, n);
|
||||||
if (x.isOne() || x.equal(n1)) {
|
if (x.isOne() || x.equal(n1)) {
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
* @module crypto/public_key/rsa
|
* @module crypto/public_key/rsa
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import prime from './prime';
|
import { randomProbablePrime } from './prime';
|
||||||
import random from '../random';
|
import { getRandomBigInteger } from '../random';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import pkcs1 from '../pkcs1';
|
import { emsaEncode, emeEncode, emeDecode } from '../pkcs1';
|
||||||
import enums from '../../enums';
|
import enums from '../../enums';
|
||||||
|
|
||||||
const webCrypto = util.getWebCrypto();
|
const webCrypto = util.getWebCrypto();
|
||||||
|
@ -73,8 +73,7 @@ const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function (
|
||||||
}) : undefined;
|
}) : undefined;
|
||||||
/* eslint-enable no-invalid-this */
|
/* eslint-enable no-invalid-this */
|
||||||
|
|
||||||
export default {
|
/** Create signature
|
||||||
/** Create signature
|
|
||||||
* @param {module:enums.hash} hash_algo Hash algorithm
|
* @param {module:enums.hash} hash_algo Hash algorithm
|
||||||
* @param {Uint8Array} data message
|
* @param {Uint8Array} data message
|
||||||
* @param {Uint8Array} n RSA public modulus
|
* @param {Uint8Array} n RSA public modulus
|
||||||
|
@ -87,22 +86,22 @@ export default {
|
||||||
* @returns {Uint8Array} RSA Signature
|
* @returns {Uint8Array} RSA Signature
|
||||||
* @async
|
* @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 (data && !util.isStream(data)) {
|
||||||
if (util.getWebCrypto()) {
|
if (util.getWebCrypto()) {
|
||||||
try {
|
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) {
|
} catch (err) {
|
||||||
util.printDebugError(err);
|
util.printDebugError(err);
|
||||||
}
|
}
|
||||||
} else if (util.getNodeCrypto()) {
|
} 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
|
* Verify signature
|
||||||
* @param {module:enums.hash} hash_algo Hash algorithm
|
* @param {module:enums.hash} hash_algo Hash algorithm
|
||||||
* @param {Uint8Array} data message
|
* @param {Uint8Array} data message
|
||||||
|
@ -113,22 +112,22 @@ export default {
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
* @async
|
* @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 (data && !util.isStream(data)) {
|
||||||
if (util.getWebCrypto()) {
|
if (util.getWebCrypto()) {
|
||||||
try {
|
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) {
|
} catch (err) {
|
||||||
util.printDebugError(err);
|
util.printDebugError(err);
|
||||||
}
|
}
|
||||||
} else if (util.getNodeCrypto()) {
|
} 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
|
* Encrypt message
|
||||||
* @param {Uint8Array} data message
|
* @param {Uint8Array} data message
|
||||||
* @param {Uint8Array} n RSA public modulus
|
* @param {Uint8Array} n RSA public modulus
|
||||||
|
@ -136,14 +135,14 @@ export default {
|
||||||
* @returns {Uint8Array} RSA Ciphertext
|
* @returns {Uint8Array} RSA Ciphertext
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
encrypt: async function(data, n, e) {
|
export async function encrypt(data, n, e) {
|
||||||
if (util.getNodeCrypto()) {
|
if (util.getNodeCrypto()) {
|
||||||
return this.nodeEncrypt(data, n, e);
|
return nodeEncrypt(data, n, e);
|
||||||
}
|
}
|
||||||
return this.bnEncrypt(data, n, e);
|
return bnEncrypt(data, n, e);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt RSA message
|
* Decrypt RSA message
|
||||||
* @param {Uint8Array} m message
|
* @param {Uint8Array} m message
|
||||||
* @param {Uint8Array} n RSA public modulus
|
* @param {Uint8Array} n RSA public modulus
|
||||||
|
@ -155,14 +154,14 @@ export default {
|
||||||
* @returns {String} RSA Plaintext
|
* @returns {String} RSA Plaintext
|
||||||
* @async
|
* @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()) {
|
if (util.getNodeCrypto()) {
|
||||||
return this.nodeDecrypt(data, n, e, d, p, q, u);
|
return nodeDecrypt(data, n, e, d, p, q, u);
|
||||||
}
|
}
|
||||||
return this.bnDecrypt(data, n, e, d, p, q, u);
|
return bnDecrypt(data, n, e, d, p, q, u);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new random private key B bits long with public exponent E.
|
* Generate a new random private key B bits long with public exponent E.
|
||||||
*
|
*
|
||||||
* When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using
|
* When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using
|
||||||
|
@ -175,7 +174,7 @@ export default {
|
||||||
* RSA private prime p, RSA private prime q, u = p ** -1 mod q
|
* RSA private prime p, RSA private prime q, u = p ** -1 mod q
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
generate: async function(bits, e) {
|
export async function generate(bits, e) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
|
|
||||||
e = new BigInteger(e);
|
e = new BigInteger(e);
|
||||||
|
@ -265,8 +264,8 @@ export default {
|
||||||
// RSA keygen fallback using 40 iterations of the Miller-Rabin test
|
// RSA keygen fallback using 40 iterations of the Miller-Rabin test
|
||||||
// See https://stackoverflow.com/a/6330138 for justification
|
// See https://stackoverflow.com/a/6330138 for justification
|
||||||
// Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST
|
// Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST
|
||||||
let q = await prime.randomProbablePrime(bits - (bits >> 1), e, 40);
|
let q = await randomProbablePrime(bits - (bits >> 1), e, 40);
|
||||||
let p = await prime.randomProbablePrime(bits >> 1, e, 40);
|
let p = await randomProbablePrime(bits >> 1, e, 40);
|
||||||
|
|
||||||
if (q.lt(p)) {
|
if (q.lt(p)) {
|
||||||
[p, q] = [q, p];
|
[p, q] = [q, p];
|
||||||
|
@ -282,9 +281,9 @@ export default {
|
||||||
// dq: d.mod(q.subn(1)),
|
// dq: d.mod(q.subn(1)),
|
||||||
u: p.modInv(q).toUint8Array()
|
u: p.modInv(q).toUint8Array()
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate RSA parameters
|
* Validate RSA parameters
|
||||||
* @param {Uint8Array} n RSA public modulus
|
* @param {Uint8Array} n RSA public modulus
|
||||||
* @param {Uint8Array} e RSA public exponent
|
* @param {Uint8Array} e RSA public exponent
|
||||||
|
@ -295,7 +294,7 @@ export default {
|
||||||
* @returns {Promise<Boolean>} whether params are valid
|
* @returns {Promise<Boolean>} whether params are valid
|
||||||
* @async
|
* @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();
|
const BigInteger = await util.getBigInteger();
|
||||||
n = new BigInteger(n);
|
n = new BigInteger(n);
|
||||||
p = new BigInteger(p);
|
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)
|
* 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 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 rde = r.mul(d).mul(e);
|
||||||
|
|
||||||
const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r);
|
const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r);
|
||||||
|
@ -332,20 +331,20 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
}
|
||||||
|
|
||||||
bnSign: async function (hash_algo, n, d, hashed) {
|
async function bnSign(hash_algo, n, d, hashed) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
n = new BigInteger(n);
|
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);
|
d = new BigInteger(d);
|
||||||
if (m.gte(n)) {
|
if (m.gte(n)) {
|
||||||
throw new Error('Message size cannot exceed modulus size');
|
throw new Error('Message size cannot exceed modulus size');
|
||||||
}
|
}
|
||||||
return m.modExp(d, n).toUint8Array('be', n.byteLength());
|
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.
|
/** 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,
|
* We swap them in privateToJwk, so it usually works out, but nevertheless,
|
||||||
* not all OpenPGP keys are compatible with this requirement.
|
* 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"]);
|
const key = await webCrypto.importKey("jwk", jwk, algo, false, ["sign"]);
|
||||||
// add hash field for ms edge support
|
// add hash field for ms edge support
|
||||||
return new Uint8Array(await webCrypto.sign({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, data));
|
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 { default: BN } = await import('bn.js');
|
||||||
const pBNum = new BN(p);
|
const pBNum = new BN(p);
|
||||||
const qBNum = new BN(q);
|
const qBNum = new BN(q);
|
||||||
|
@ -393,9 +392,9 @@ export default {
|
||||||
label: 'RSA PRIVATE KEY'
|
label: 'RSA PRIVATE KEY'
|
||||||
});
|
});
|
||||||
return new Uint8Array(sign.sign(pem));
|
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();
|
const BigInteger = await util.getBigInteger();
|
||||||
n = new BigInteger(n);
|
n = new BigInteger(n);
|
||||||
s = new BigInteger(s);
|
s = new BigInteger(s);
|
||||||
|
@ -404,11 +403,11 @@ export default {
|
||||||
throw new Error('Signature size cannot exceed modulus size');
|
throw new Error('Signature size cannot exceed modulus size');
|
||||||
}
|
}
|
||||||
const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength());
|
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);
|
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 jwk = publicToJwk(n, e);
|
||||||
const key = await webCrypto.importKey("jwk", jwk, {
|
const key = await webCrypto.importKey("jwk", jwk, {
|
||||||
name: "RSASSA-PKCS1-v1_5",
|
name: "RSASSA-PKCS1-v1_5",
|
||||||
|
@ -416,9 +415,9 @@ export default {
|
||||||
}, false, ["verify"]);
|
}, false, ["verify"]);
|
||||||
// add hash field for ms edge support
|
// add hash field for ms edge support
|
||||||
return webCrypto.verify({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, s, data);
|
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 { default: BN } = await import('bn.js');
|
||||||
|
|
||||||
const verify = nodeCrypto.createVerify(enums.read(enums.hash, hash_algo));
|
const verify = nodeCrypto.createVerify(enums.read(enums.hash, hash_algo));
|
||||||
|
@ -442,9 +441,9 @@ export default {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
nodeEncrypt: async function (data, n, e) {
|
async function nodeEncrypt(data, n, e) {
|
||||||
const { default: BN } = await import('bn.js');
|
const { default: BN } = await import('bn.js');
|
||||||
|
|
||||||
const keyObject = {
|
const keyObject = {
|
||||||
|
@ -462,20 +461,20 @@ export default {
|
||||||
key = { key: pem, padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
key = { key: pem, padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
||||||
}
|
}
|
||||||
return new Uint8Array(nodeCrypto.publicEncrypt(key, data));
|
return new Uint8Array(nodeCrypto.publicEncrypt(key, data));
|
||||||
},
|
}
|
||||||
|
|
||||||
bnEncrypt: async function (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 pkcs1.eme.encode(data, n.byteLength()));
|
data = new BigInteger(await 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');
|
||||||
}
|
}
|
||||||
return data.modExp(e, n).toUint8Array('be', n.byteLength());
|
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 { default: BN } = await import('bn.js');
|
||||||
|
|
||||||
const pBNum = new BN(p);
|
const pBNum = new BN(p);
|
||||||
|
@ -511,9 +510,9 @@ export default {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error('Decryption error');
|
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();
|
const BigInteger = await util.getBigInteger();
|
||||||
data = new BigInteger(data);
|
data = new BigInteger(data);
|
||||||
n = new BigInteger(n);
|
n = new BigInteger(n);
|
||||||
|
@ -531,7 +530,7 @@ export default {
|
||||||
let blinder;
|
let blinder;
|
||||||
let unblinder;
|
let unblinder;
|
||||||
if (config.rsaBlinding) {
|
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);
|
blinder = unblinder.modInv(n).modExp(e, n);
|
||||||
data = data.mul(blinder).mod(n);
|
data = data.mul(blinder).mod(n);
|
||||||
}
|
}
|
||||||
|
@ -546,11 +545,8 @@ export default {
|
||||||
result = result.mul(unblinder).mod(n);
|
result = result.mul(unblinder).mod(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkcs1.eme.decode(result.toUint8Array('be', n.byteLength()));
|
return emeDecode(result.toUint8Array('be', n.byteLength()));
|
||||||
},
|
}
|
||||||
|
|
||||||
prime: prime
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Convert Openpgp private key params to jwk key according to
|
/** Convert Openpgp private key params to jwk key according to
|
||||||
* @link https://tools.ietf.org/html/rfc7517
|
* @link https://tools.ietf.org/html/rfc7517
|
||||||
|
|
|
@ -94,14 +94,13 @@ class RandomBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* 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 {Uint8Array} Random byte array
|
* @returns {Uint8Array} Random byte array
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
getRandomBytes: async function(length) {
|
export async 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);
|
||||||
|
@ -110,22 +109,22 @@ export default {
|
||||||
} 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 (this.randomBuffer.buffer) {
|
} else if (randomBuffer.buffer) {
|
||||||
await this.randomBuffer.get(buf);
|
await randomBuffer.get(buf);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No secure random number generator available.');
|
throw new Error('No secure random number generator available.');
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a secure random BigInteger that is greater than or equal to min and less than max.
|
* Create a secure random BigInteger that is greater than or equal to min and less than max.
|
||||||
* @param {module:BigInteger} min Lower bound, included
|
* @param {module:BigInteger} min Lower bound, included
|
||||||
* @param {module:BigInteger} max Upper bound, excluded
|
* @param {module:BigInteger} max Upper bound, excluded
|
||||||
* @returns {module:BigInteger} Random BigInteger
|
* @returns {module:BigInteger} Random BigInteger
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
getRandomBigInteger: async function(min, max) {
|
export async function getRandomBigInteger(min, max) {
|
||||||
const BigInteger = await util.getBigInteger();
|
const BigInteger = await util.getBigInteger();
|
||||||
|
|
||||||
if (max.lt(min)) {
|
if (max.lt(min)) {
|
||||||
|
@ -138,9 +137,8 @@ export default {
|
||||||
// Using a while loop is necessary to avoid bias introduced by the mod operation.
|
// 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.
|
// 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
|
// 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);
|
return r.mod(modulus).add(min);
|
||||||
},
|
}
|
||||||
|
|
||||||
randomBuffer: new RandomBuffer()
|
export const randomBuffer = new RandomBuffer();
|
||||||
};
|
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
/**
|
/**
|
||||||
* @fileoverview Provides functions for asymmetric signing and signature verification
|
* @fileoverview Provides functions for asymmetric signing and signature verification
|
||||||
* @requires crypto/crypto
|
|
||||||
* @requires crypto/public_key
|
* @requires crypto/public_key
|
||||||
* @requires enums
|
* @requires enums
|
||||||
* @requires util
|
* @requires util
|
||||||
* @module crypto/signature
|
* @module crypto/signature
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import crypto from './crypto';
|
|
||||||
import publicKey from './public_key';
|
import publicKey from './public_key';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
/**
|
|
||||||
* Verifies the signature provided for data using specified algorithms and public key parameters.
|
* 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}
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
|
||||||
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
||||||
|
@ -27,7 +24,7 @@ export default {
|
||||||
* @returns {Boolean} True if signature is valid
|
* @returns {Boolean} True if signature is valid
|
||||||
* @async
|
* @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) {
|
switch (algo) {
|
||||||
case enums.publicKey.rsaEncryptSign:
|
case enums.publicKey.rsaEncryptSign:
|
||||||
case enums.publicKey.rsaEncrypt:
|
case enums.publicKey.rsaEncrypt:
|
||||||
|
@ -59,9 +56,9 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid signature algorithm.');
|
throw new Error('Invalid signature algorithm.');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a signature on data using specified algorithms and private key parameters.
|
* Creates a signature on data using specified algorithms and private key parameters.
|
||||||
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
|
||||||
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
||||||
|
@ -75,7 +72,7 @@ export default {
|
||||||
* @returns {Uint8Array} Signature
|
* @returns {Uint8Array} Signature
|
||||||
* @async
|
* @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) {
|
if (!publicKeyParams || !privateKeyParams) {
|
||||||
throw new Error('Missing key parameters');
|
throw new Error('Missing key parameters');
|
||||||
}
|
}
|
||||||
|
@ -121,5 +118,4 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid signature algorithm.');
|
throw new Error('Invalid signature algorithm.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import base64 from './base64.js';
|
import * as base64 from './base64.js';
|
||||||
import enums from '../enums.js';
|
import enums from '../enums.js';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
@ -233,7 +233,7 @@ function splitChecksum(text) {
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function dearmor(input) {
|
export function unarmor(input) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const reSplit = /^-----[^-]+-----$/m;
|
const reSplit = /^-----[^-]+-----$/m;
|
||||||
|
@ -359,7 +359,7 @@ function dearmor(input) {
|
||||||
* @returns {String | ReadableStream<String>} Armored text
|
* @returns {String | ReadableStream<String>} Armored text
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function armor(messagetype, body, partindex, parttotal, customComment) {
|
export function armor(messagetype, body, partindex, parttotal, customComment) {
|
||||||
let text;
|
let text;
|
||||||
let hash;
|
let hash;
|
||||||
if (messagetype === enums.armor.signed) {
|
if (messagetype === enums.armor.signed) {
|
||||||
|
@ -426,8 +426,3 @@ function armor(messagetype, body, partindex, parttotal, customComment) {
|
||||||
|
|
||||||
return util.concat(result);
|
return util.concat(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
|
||||||
encode: armor,
|
|
||||||
decode: dearmor
|
|
||||||
};
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ if (Buffer) {
|
||||||
* @returns {String | ReadableStream<String>} radix-64 version of input string
|
* @returns {String | ReadableStream<String>} radix-64 version of input string
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function encode(data) {
|
export function encode(data) {
|
||||||
let buf = new Uint8Array();
|
let buf = new Uint8Array();
|
||||||
return stream.transform(data, value => {
|
return stream.transform(data, value => {
|
||||||
buf = util.concatUint8Array([buf, value]);
|
buf = util.concatUint8Array([buf, value]);
|
||||||
|
@ -65,7 +65,7 @@ function encode(data) {
|
||||||
* @returns {Uint8Array | ReadableStream<Uint8Array>} binary array version of input string
|
* @returns {Uint8Array | ReadableStream<Uint8Array>} binary array version of input string
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function decode(data) {
|
export function decode(data) {
|
||||||
let buf = '';
|
let buf = '';
|
||||||
return stream.transform(data, value => {
|
return stream.transform(data, value => {
|
||||||
buf += value;
|
buf += value;
|
||||||
|
@ -92,5 +92,3 @@ function decode(data) {
|
||||||
return decoded;
|
return decoded;
|
||||||
}, () => decodeChunk(buf));
|
}, () => decodeChunk(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { encode, decode };
|
|
||||||
|
|
|
@ -126,7 +126,6 @@ export default {
|
||||||
plaintext: 0,
|
plaintext: 0,
|
||||||
/** Not implemented! */
|
/** Not implemented! */
|
||||||
idea: 1,
|
idea: 1,
|
||||||
'3des': 2,
|
|
||||||
tripledes: 2,
|
tripledes: 2,
|
||||||
cast5: 3,
|
cast5: 3,
|
||||||
blowfish: 4,
|
blowfish: 4,
|
||||||
|
|
|
@ -98,7 +98,7 @@ export { default as stream } from 'web-stream-tools';
|
||||||
* @see module:encoding/armor
|
* @see module:encoding/armor
|
||||||
* @name module:openpgp.armor
|
* @name module:openpgp.armor
|
||||||
*/
|
*/
|
||||||
export { default as armor } from './encoding/armor';
|
export * from './encoding/armor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see module:enums
|
* @see module:enums
|
||||||
|
|
|
@ -33,7 +33,7 @@ import * as helper from './helper';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import armor from '../encoding/armor';
|
import { unarmor } from '../encoding/armor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key. Supports RSA and ECC keys.
|
* Generates a new OpenPGP key. Supports RSA and ECC keys.
|
||||||
|
@ -283,7 +283,7 @@ export async function readKey(data) {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export async function readArmoredKey(armoredKey) {
|
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)) {
|
if (!(input.type === enums.armor.publicKey || input.type === enums.armor.privateKey)) {
|
||||||
throw new Error('Armored text not of type key');
|
throw new Error('Armored text not of type key');
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ export async function readKeys(data) {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export async function readArmoredKeys(armoredKey) {
|
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)) {
|
if (!(input.type === enums.armor.publicKey || input.type === enums.armor.privateKey)) {
|
||||||
throw new Error('Armored text not of type key');
|
throw new Error('Armored text not of type key');
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* @module key/Key
|
* @module key/Key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import armor from '../encoding/armor';
|
import { armor, unarmor } from '../encoding/armor';
|
||||||
import {
|
import {
|
||||||
PacketList,
|
PacketList,
|
||||||
PublicKeyPacket,
|
PublicKeyPacket,
|
||||||
|
@ -280,7 +280,7 @@ class Key {
|
||||||
*/
|
*/
|
||||||
armor() {
|
armor() {
|
||||||
const type = this.isPublic() ? enums.armor.publicKey : enums.armor.privateKey;
|
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 revocationSignature = await helper.getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date);
|
||||||
const packetlist = new PacketList();
|
const packetlist = new PacketList();
|
||||||
packetlist.push(revocationSignature);
|
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
|
||||||
*/
|
*/
|
||||||
async applyRevocationCertificate(revocationCertificate) {
|
async applyRevocationCertificate(revocationCertificate) {
|
||||||
const input = await armor.decode(revocationCertificate);
|
const input = await unarmor(revocationCertificate);
|
||||||
const packetlist = new PacketList();
|
const packetlist = new PacketList();
|
||||||
await packetlist.read(input.data, { SignaturePacket });
|
await packetlist.read(input.data, { SignaturePacket });
|
||||||
const revocationSignature = packetlist.findPacket(enums.packet.signature);
|
const revocationSignature = packetlist.findPacket(enums.packet.signature);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import armor from './encoding/armor';
|
import { armor, unarmor } from './encoding/armor';
|
||||||
import type_keyid from './type/keyid';
|
import type_keyid from './type/keyid';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import crypto from './crypto';
|
import crypto from './crypto';
|
||||||
|
@ -607,7 +607,7 @@ export class Message {
|
||||||
* @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature
|
* @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature
|
||||||
*/
|
*/
|
||||||
async appendSignature(detachedSignature) {
|
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
|
* @returns {ReadableStream<String>} ASCII armor
|
||||||
*/
|
*/
|
||||||
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') {
|
if (streamType === 'node') {
|
||||||
armoredText = stream.nodeToWeb(armoredText);
|
armoredText = stream.nodeToWeb(armoredText);
|
||||||
}
|
}
|
||||||
const input = await armor.decode(armoredText);
|
const input = await unarmor(armoredText);
|
||||||
return readMessage(input.data, streamType);
|
return readMessage(input.data, streamType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,7 @@ import stream from 'web-stream-tools';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
export default {
|
export function readSimpleLength(bytes) {
|
||||||
readSimpleLength: function(bytes) {
|
|
||||||
let len = 0;
|
let len = 0;
|
||||||
let offset;
|
let offset;
|
||||||
const type = bytes[0];
|
const type = bytes[0];
|
||||||
|
@ -51,16 +50,16 @@ export default {
|
||||||
len: len,
|
len: len,
|
||||||
offset: offset
|
offset: offset
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a given integer of length to the openpgp length specifier to a
|
* Encodes a given integer of length to the openpgp length specifier to a
|
||||||
* string
|
* string
|
||||||
*
|
*
|
||||||
* @param {Integer} length The length to encode
|
* @param {Integer} length The length to encode
|
||||||
* @returns {Uint8Array} String with openpgp length representation
|
* @returns {Uint8Array} String with openpgp length representation
|
||||||
*/
|
*/
|
||||||
writeSimpleLength: function(length) {
|
export function writeSimpleLength(length) {
|
||||||
if (length < 192) {
|
if (length < 192) {
|
||||||
return new Uint8Array([length]);
|
return new Uint8Array([length]);
|
||||||
} else if (length > 191 && length < 8384) {
|
} else if (length > 191 && length < 8384) {
|
||||||
|
@ -71,21 +70,21 @@ export default {
|
||||||
return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]);
|
return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]);
|
||||||
}
|
}
|
||||||
return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]);
|
return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]);
|
||||||
},
|
}
|
||||||
|
|
||||||
writePartialLength: function(power) {
|
export function writePartialLength(power) {
|
||||||
if (power < 0 || power > 30) {
|
if (power < 0 || power > 30) {
|
||||||
throw new Error('Partial Length power must be between 1 and 30');
|
throw new Error('Partial Length power must be between 1 and 30');
|
||||||
}
|
}
|
||||||
return new Uint8Array([224 + power]);
|
return new Uint8Array([224 + power]);
|
||||||
},
|
}
|
||||||
|
|
||||||
writeTag: function(tag_type) {
|
export function writeTag(tag_type) {
|
||||||
/* we're only generating v4 packet headers here */
|
/* we're only generating v4 packet headers here */
|
||||||
return new Uint8Array([0xC0 | tag_type]);
|
return new Uint8Array([0xC0 | tag_type]);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a packet header version 4 with the given tag_type and length to a
|
* Writes a packet header version 4 with the given tag_type and length to a
|
||||||
* string
|
* string
|
||||||
*
|
*
|
||||||
|
@ -93,17 +92,17 @@ export default {
|
||||||
* @param {Integer} length Length of the payload
|
* @param {Integer} length Length of the payload
|
||||||
* @returns {String} String of the header
|
* @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 */
|
/* 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
|
* Whether the packet type supports partial lengths per RFC4880
|
||||||
* @param {Integer} tag_type Tag type
|
* @param {Integer} tag_type Tag type
|
||||||
* @returns {Boolean} String of the header
|
* @returns {Boolean} String of the header
|
||||||
*/
|
*/
|
||||||
supportsStreaming: function(tag_type) {
|
export function supportsStreaming(tag_type) {
|
||||||
return [
|
return [
|
||||||
enums.packet.literalData,
|
enums.packet.literalData,
|
||||||
enums.packet.compressedData,
|
enums.packet.compressedData,
|
||||||
|
@ -111,16 +110,16 @@ export default {
|
||||||
enums.packet.symEncryptedIntegrityProtectedData,
|
enums.packet.symEncryptedIntegrityProtectedData,
|
||||||
enums.packet.AEADEncryptedData
|
enums.packet.AEADEncryptedData
|
||||||
].includes(tag_type);
|
].includes(tag_type);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic static Packet Parser function
|
* Generic static Packet Parser function
|
||||||
*
|
*
|
||||||
* @param {Uint8Array | ReadableStream<Uint8Array>} input Input stream as string
|
* @param {Uint8Array | ReadableStream<Uint8Array>} input Input stream as string
|
||||||
* @param {Function} callback Function to call with the parsed packet
|
* @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.
|
* @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);
|
const reader = stream.getReader(input);
|
||||||
let writer;
|
let writer;
|
||||||
let callbackReturned;
|
let callbackReturned;
|
||||||
|
@ -150,9 +149,9 @@ export default {
|
||||||
packet_length_type = headerByte & 0x03; // bit 1-0
|
packet_length_type = headerByte & 0x03; // bit 1-0
|
||||||
}
|
}
|
||||||
|
|
||||||
const supportsStreaming = this.supportsStreaming(tag);
|
const packetSupportsStreaming = supportsStreaming(tag);
|
||||||
let packet = null;
|
let packet = null;
|
||||||
if (streaming && supportsStreaming) {
|
if (streaming && packetSupportsStreaming) {
|
||||||
const transform = new stream.TransformStream();
|
const transform = new stream.TransformStream();
|
||||||
writer = stream.getWriter(transform.writable);
|
writer = stream.getWriter(transform.writable);
|
||||||
packet = transform.readable;
|
packet = transform.readable;
|
||||||
|
@ -209,7 +208,7 @@ export default {
|
||||||
} else if (lengthByte > 223 && lengthByte < 255) {
|
} else if (lengthByte > 223 && lengthByte < 255) {
|
||||||
packet_length = 1 << (lengthByte & 0x1F);
|
packet_length = 1 << (lengthByte & 0x1F);
|
||||||
wasPartialLength = true;
|
wasPartialLength = true;
|
||||||
if (!supportsStreaming) {
|
if (!packetSupportsStreaming) {
|
||||||
throw new TypeError('This packet type does not support partial lengths.');
|
throw new TypeError('This packet type does not support partial lengths.');
|
||||||
}
|
}
|
||||||
// 4.2.2.3. Five-Octet 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
|
// 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
|
// 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.
|
// (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) {
|
if (writer) {
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
await writer.close();
|
await writer.close();
|
||||||
|
@ -292,5 +291,4 @@ export default {
|
||||||
}
|
}
|
||||||
reader.releaseLock();
|
reader.releaseLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -10,7 +10,11 @@
|
||||||
|
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import * as packets from './all_packets';
|
import * as packets from './all_packets';
|
||||||
import packetParser from './packet';
|
import {
|
||||||
|
readPackets, supportsStreaming,
|
||||||
|
writeTag, writeHeader,
|
||||||
|
writePartialLength, writeSimpleLength
|
||||||
|
} from './packet';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
@ -33,7 +37,7 @@ class PacketList extends Array {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
const done = await packetParser.read(readable, streaming, async parsed => {
|
const done = await readPackets(readable, streaming, async parsed => {
|
||||||
try {
|
try {
|
||||||
const tag = enums.read(enums.packet, parsed.tag);
|
const tag = enums.read(enums.packet, parsed.tag);
|
||||||
const packet = packets.newPacketFromTag(tag, allowedPackets);
|
const packet = packets.newPacketFromTag(tag, allowedPackets);
|
||||||
|
@ -42,7 +46,7 @@ class PacketList extends Array {
|
||||||
await packet.read(parsed.packet, streaming);
|
await packet.read(parsed.packet, streaming);
|
||||||
await writer.write(packet);
|
await writer.write(packet);
|
||||||
} catch (e) {
|
} 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
|
// The packets that support streaming are the ones that contain
|
||||||
// message data. Those are also the ones we want to be more strict
|
// message data. Those are also the ones we want to be more strict
|
||||||
// about and throw on parse errors for.
|
// about and throw on parse errors for.
|
||||||
|
@ -71,7 +75,7 @@ class PacketList extends Array {
|
||||||
} else {
|
} else {
|
||||||
this.stream = null;
|
this.stream = null;
|
||||||
}
|
}
|
||||||
if (done || packetParser.supportsStreaming(value.tag)) {
|
if (done || supportsStreaming(value.tag)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,31 +92,31 @@ class PacketList extends Array {
|
||||||
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
for (let i = 0; i < this.length; i++) {
|
||||||
const packetbytes = this[i].write();
|
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 buffer = [];
|
||||||
let bufferLength = 0;
|
let bufferLength = 0;
|
||||||
const minLength = 512;
|
const minLength = 512;
|
||||||
arr.push(packetParser.writeTag(this[i].tag));
|
arr.push(writeTag(this[i].tag));
|
||||||
arr.push(stream.transform(packetbytes, value => {
|
arr.push(stream.transform(packetbytes, value => {
|
||||||
buffer.push(value);
|
buffer.push(value);
|
||||||
bufferLength += value.length;
|
bufferLength += value.length;
|
||||||
if (bufferLength >= minLength) {
|
if (bufferLength >= minLength) {
|
||||||
const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30);
|
const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30);
|
||||||
const chunkSize = 2 ** powerOf2;
|
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)];
|
buffer = [bufferConcat.subarray(1 + chunkSize)];
|
||||||
bufferLength = buffer[0].length;
|
bufferLength = buffer[0].length;
|
||||||
return bufferConcat.subarray(0, 1 + chunkSize);
|
return bufferConcat.subarray(0, 1 + chunkSize);
|
||||||
}
|
}
|
||||||
}, () => util.concat([packetParser.writeSimpleLength(bufferLength)].concat(buffer))));
|
}, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer))));
|
||||||
} else {
|
} else {
|
||||||
if (util.isStream(packetbytes)) {
|
if (util.isStream(packetbytes)) {
|
||||||
let length = 0;
|
let length = 0;
|
||||||
arr.push(stream.transform(stream.clone(packetbytes), value => {
|
arr.push(stream.transform(stream.clone(packetbytes), value => {
|
||||||
length += value.length;
|
length += value.length;
|
||||||
}, () => packetParser.writeHeader(this[i].tag, length)));
|
}, () => writeHeader(this[i].tag, length)));
|
||||||
} else {
|
} else {
|
||||||
arr.push(packetParser.writeHeader(this[i].tag, packetbytes.length));
|
arr.push(writeHeader(this[i].tag, packetbytes.length));
|
||||||
}
|
}
|
||||||
arr.push(packetbytes);
|
arr.push(packetbytes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import packet from './packet';
|
import { readSimpleLength, writeSimpleLength } from './packet';
|
||||||
import type_keyid from '../type/keyid.js';
|
import type_keyid from '../type/keyid.js';
|
||||||
import type_mpi from '../type/mpi.js';
|
import type_mpi from '../type/mpi.js';
|
||||||
import crypto from '../crypto';
|
import crypto from '../crypto';
|
||||||
|
@ -319,7 +319,7 @@ class SignaturePacket {
|
||||||
arr.push(write_sub_packet(sub.issuerFingerprint, bytes));
|
arr.push(write_sub_packet(sub.issuerFingerprint, bytes));
|
||||||
}
|
}
|
||||||
this.unhashedSubpackets.forEach(data => {
|
this.unhashedSubpackets.forEach(data => {
|
||||||
arr.push(packet.writeSimpleLength(data.length));
|
arr.push(writeSimpleLength(data.length));
|
||||||
arr.push(data);
|
arr.push(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -535,7 +535,7 @@ class SignaturePacket {
|
||||||
|
|
||||||
// subpacket data set (zero or more subpackets)
|
// subpacket data set (zero or more subpackets)
|
||||||
while (i < 2 + subpacket_length) {
|
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;
|
i += len.offset;
|
||||||
|
|
||||||
this.read_sub_packet(bytes.subarray(i, i + len.len), trusted);
|
this.read_sub_packet(bytes.subarray(i, i + len.len), trusted);
|
||||||
|
@ -767,7 +767,7 @@ class SignaturePacket {
|
||||||
*/
|
*/
|
||||||
function write_sub_packet(type, data) {
|
function write_sub_packet(type, data) {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
arr.push(packet.writeSimpleLength(data.length + 1));
|
arr.push(writeSimpleLength(data.length + 1));
|
||||||
arr.push(new Uint8Array([type]));
|
arr.push(new Uint8Array([type]));
|
||||||
arr.push(data);
|
arr.push(data);
|
||||||
return util.concat(arr);
|
return util.concat(arr);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* @requires util
|
* @requires util
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import packet from './packet';
|
import { readSimpleLength, writeSimpleLength } from './packet';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class UserAttributePacket {
|
||||||
read(bytes) {
|
read(bytes) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (i < bytes.length) {
|
while (i < bytes.length) {
|
||||||
const len = packet.readSimpleLength(bytes.subarray(i, bytes.length));
|
const len = readSimpleLength(bytes.subarray(i, bytes.length));
|
||||||
i += len.offset;
|
i += len.offset;
|
||||||
|
|
||||||
this.attributes.push(util.uint8ArrayToStr(bytes.subarray(i, i + len.len)));
|
this.attributes.push(util.uint8ArrayToStr(bytes.subarray(i, i + len.len)));
|
||||||
|
@ -71,7 +71,7 @@ class UserAttributePacket {
|
||||||
write() {
|
write() {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
for (let i = 0; i < this.attributes.length; i++) {
|
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]));
|
arr.push(util.strToUint8Array(this.attributes[i]));
|
||||||
}
|
}
|
||||||
return util.concatUint8Array(arr);
|
return util.concatUint8Array(arr);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* @module signature
|
* @module signature
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import armor from './encoding/armor';
|
import { armor, unarmor } from './encoding/armor';
|
||||||
import { PacketList, SignaturePacket } from './packet';
|
import { PacketList, SignaturePacket } from './packet';
|
||||||
import enums from './enums';
|
import enums from './enums';
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ export class Signature {
|
||||||
* @returns {ReadableStream<String>} ASCII armor
|
* @returns {ReadableStream<String>} ASCII armor
|
||||||
*/
|
*/
|
||||||
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
|
* @static
|
||||||
*/
|
*/
|
||||||
export async function readArmoredSignature(armoredText) {
|
export async function readArmoredSignature(armoredText) {
|
||||||
const input = await armor.decode(armoredText);
|
const input = await unarmor(armoredText);
|
||||||
return readSignature(input.data);
|
return readSignature(input.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import emailAddresses from 'email-addresses';
|
||||||
import stream from 'web-stream-tools';
|
import stream from 'web-stream-tools';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import util from './util'; // re-import module to access util functions
|
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';
|
import { getBigInteger } from './biginteger';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -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()) {
|
if (!openpgp.config.useIndutnyElliptic && !openpgp.util.getNodeCrypto()) {
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
if (openpgp.util.getNodeCrypto()) {
|
if (openpgp.util.getNodeCrypto()) {
|
||||||
expect(verify_signature(
|
await expect(verify_signature(
|
||||||
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
||||||
)).to.eventually.be.false;
|
)).to.eventually.be.false;
|
||||||
}
|
}
|
||||||
if (openpgp.config.useIndutnyElliptic) {
|
if (openpgp.config.useIndutnyElliptic) {
|
||||||
expect(verify_signature_elliptic(
|
await expect(verify_signature_elliptic(
|
||||||
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
||||||
)).to.be.rejectedWith(Error, /Invalid elliptic public key/);
|
)).to.be.rejectedWith(Error, /Invalid elliptic public key/);
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,8 +377,8 @@ NJCB6+LWtabSoVIjNVgKwyKqyTLaESNwC2ogZwkdE8qPGiDFEHo4Gg9zuRof
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const { type, data } = await openpgp.armor.decode(pubKey);
|
const { type, data } = await openpgp.unarmor(pubKey);
|
||||||
const armor = await openpgp.stream.readToEnd(openpgp.armor.encode(type, data));
|
const armor = await openpgp.stream.readToEnd(openpgp.armor(type, data));
|
||||||
expect(
|
expect(
|
||||||
armor
|
armor
|
||||||
.replace(/^(Version|Comment): .*$\r\n/mg, '')
|
.replace(/^(Version|Comment): .*$\r\n/mg, '')
|
||||||
|
|
|
@ -2584,35 +2584,9 @@ function versionSpecificTests() {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = () => describe('Key', function() {
|
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 rsaGenStub;
|
||||||
let v5KeysVal;
|
let v5KeysVal;
|
||||||
let aeadProtectVal;
|
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, {
|
tryTests('V4', versionSpecificTests, {
|
||||||
if: !openpgp.config.ci,
|
if: !openpgp.config.ci,
|
||||||
|
@ -2706,7 +2680,7 @@ module.exports = () => describe('Key', function() {
|
||||||
|
|
||||||
const packetlist = new openpgp.PacketList();
|
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();
|
const subkeys = pubKey.getSubkeys();
|
||||||
expect(subkeys).to.exist;
|
expect(subkeys).to.exist;
|
||||||
|
@ -3132,10 +3106,10 @@ module.exports = () => describe('Key', function() {
|
||||||
const revKey = await openpgp.readArmoredKey(revoked_key_arm4);
|
const revKey = await openpgp.readArmoredKey(revoked_key_arm4);
|
||||||
const revocationCertificate = await revKey.getRevocationCertificate();
|
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();
|
const packetlist = new openpgp.PacketList();
|
||||||
await packetlist.read(input.data, { SignaturePacket: openpgp.SignaturePacket });
|
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, ''));
|
expect(revocationCertificate.replace(/^Comment: .*$\r\n/mg, '')).to.equal(armored.replace(/^Comment: .*$\r\n/mg, ''));
|
||||||
});
|
});
|
||||||
|
|
|
@ -549,29 +549,6 @@ function withCompression(tests) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = () => describe('OpenPGP.js public api tests', function() {
|
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() {
|
describe('generateKey - validate user ids', function() {
|
||||||
it('should fail for invalid user name', async function() {
|
it('should fail for invalid user name', async function() {
|
||||||
|
|
|
@ -243,6 +243,9 @@ module.exports = () => describe("Packet", function() {
|
||||||
it('Sym. encrypted AEAD protected packet test vector (AEAD)', async function() {
|
it('Sym. encrypted AEAD protected packet test vector (AEAD)', async function() {
|
||||||
// From https://gitlab.com/openpgp-wg/rfc4880bis/commit/00b20923e6233fb6ff1666ecd5acfefceb32907d
|
// From https://gitlab.com/openpgp-wg/rfc4880bis/commit/00b20923e6233fb6ff1666ecd5acfefceb32907d
|
||||||
|
|
||||||
|
const nodeCrypto = openpgp.util.getNodeCrypto();
|
||||||
|
if (!nodeCrypto) return;
|
||||||
|
|
||||||
let packetBytes = openpgp.util.hexToUint8Array(`
|
let packetBytes = openpgp.util.hexToUint8Array(`
|
||||||
d4 4a 01 07 01 0e b7 32 37 9f 73 c4 92 8d e2 5f
|
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
|
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();
|
const msg2 = new openpgp.PacketList();
|
||||||
|
|
||||||
let randomBytesStub = stub(openpgp.crypto.random, 'getRandomBytes');
|
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
|
||||||
randomBytesStub.returns(resolves(iv));
|
randomBytesStub.returns(iv);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await enc.encrypt(algo, key);
|
await enc.encrypt(algo, key);
|
||||||
|
@ -298,7 +301,7 @@ module.exports = () => describe("Packet", function() {
|
||||||
'=VZ0/\n' +
|
'=VZ0/\n' +
|
||||||
'-----END PGP MESSAGE-----';
|
'-----END PGP MESSAGE-----';
|
||||||
|
|
||||||
const msgbytes = (await openpgp.armor.decode(msg)).data;
|
const msgbytes = (await openpgp.unarmor(msg)).data;
|
||||||
|
|
||||||
const parsed = new openpgp.PacketList();
|
const parsed = new openpgp.PacketList();
|
||||||
await parsed.read(msgbytes, openpgp);
|
await parsed.read(msgbytes, openpgp);
|
||||||
|
@ -365,7 +368,7 @@ module.exports = () => describe("Packet", function() {
|
||||||
'-----END PGP PRIVATE KEY BLOCK-----';
|
'-----END PGP PRIVATE KEY BLOCK-----';
|
||||||
|
|
||||||
let key = new openpgp.PacketList();
|
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];
|
key = key[0];
|
||||||
|
|
||||||
const enc = new openpgp.PublicKeyEncryptedSessionKeyPacket();
|
const enc = new openpgp.PublicKeyEncryptedSessionKeyPacket();
|
||||||
|
@ -432,11 +435,11 @@ module.exports = () => describe("Packet", function() {
|
||||||
'-----END PGP MESSAGE-----';
|
'-----END PGP MESSAGE-----';
|
||||||
|
|
||||||
let key = new openpgp.PacketList();
|
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];
|
key = key[3];
|
||||||
|
|
||||||
const msg = new openpgp.PacketList();
|
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 () => {
|
return msg[0].decrypt(key).then(async () => {
|
||||||
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
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() {
|
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
|
// 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 aeadProtectVal = openpgp.config.aeadProtect;
|
||||||
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
|
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
|
||||||
let s2kIterationCountByteVal = openpgp.config.s2kIterationCountByte;
|
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 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 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');
|
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
|
||||||
randomBytesStub.onCall(0).returns(resolves(salt));
|
randomBytesStub.onCall(0).returns(salt);
|
||||||
randomBytesStub.onCall(1).returns(resolves(sessionKey));
|
randomBytesStub.onCall(1).returns(sessionKey);
|
||||||
randomBytesStub.onCall(2).returns(resolves(sessionIV));
|
randomBytesStub.onCall(2).returns(sessionIV);
|
||||||
randomBytesStub.onCall(3).returns(resolves(dataIV));
|
randomBytesStub.onCall(3).returns(dataIV);
|
||||||
|
|
||||||
let packetBytes = openpgp.util.hexToUint8Array(`
|
let packetBytes = openpgp.util.hexToUint8Array(`
|
||||||
c3 3e 05 07 01 03 08 cd 5a 9f 70 fb e0 bc 65 90
|
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() {
|
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
|
// 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 aeadProtectVal = openpgp.config.aeadProtect;
|
||||||
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
|
let aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte;
|
||||||
let s2kIterationCountByteVal = openpgp.config.s2kIterationCountByte;
|
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 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 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');
|
let randomBytesStub = stub(nodeCrypto, 'randomBytes');
|
||||||
randomBytesStub.onCall(0).returns(resolves(salt));
|
randomBytesStub.onCall(0).returns(salt);
|
||||||
randomBytesStub.onCall(1).returns(resolves(sessionKey));
|
randomBytesStub.onCall(1).returns(sessionKey);
|
||||||
randomBytesStub.onCall(2).returns(resolves(sessionIV));
|
randomBytesStub.onCall(2).returns(sessionIV);
|
||||||
randomBytesStub.onCall(3).returns(resolves(dataIV));
|
randomBytesStub.onCall(3).returns(dataIV);
|
||||||
|
|
||||||
let packetBytes = openpgp.util.hexToUint8Array(`
|
let packetBytes = openpgp.util.hexToUint8Array(`
|
||||||
c3 3d 05 07 02 03 08 9f 0b 7d a3 e5 ea 64 77 90
|
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-----';
|
'-----END PGP MESSAGE-----';
|
||||||
|
|
||||||
let key = new openpgp.PacketList();
|
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];
|
key = key[3];
|
||||||
await key.decrypt('test');
|
await key.decrypt('test');
|
||||||
|
|
||||||
const msg = new openpgp.PacketList();
|
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 () => {
|
return msg[0].decrypt(key).then(async () => {
|
||||||
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
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() {
|
it('Secret key reading with signature verification.', async function() {
|
||||||
const key = new openpgp.PacketList();
|
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([
|
return Promise.all([
|
||||||
expect(key[2].verify(key[0],
|
expect(key[2].verify(key[0],
|
||||||
openpgp.enums.signature.certGeneric,
|
openpgp.enums.signature.certGeneric,
|
||||||
|
@ -736,11 +745,11 @@ module.exports = () => describe("Packet", function() {
|
||||||
'-----END PGP MESSAGE-----';
|
'-----END PGP MESSAGE-----';
|
||||||
|
|
||||||
const key = new openpgp.PacketList();
|
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');
|
await key[3].decrypt('test');
|
||||||
|
|
||||||
const msg = new openpgp.PacketList();
|
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 () => {
|
return msg[0].decrypt(key[3]).then(async () => {
|
||||||
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
await msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user