diff --git a/src/crypto/mode/cfb.js b/src/crypto/cipherMode/cfb.js similarity index 94% rename from src/crypto/mode/cfb.js rename to src/crypto/cipherMode/cfb.js index 829a0d29..3339f864 100644 --- a/src/crypto/mode/cfb.js +++ b/src/crypto/cipherMode/cfb.js @@ -27,6 +27,7 @@ import * as stream from '@openpgp/web-stream-tools'; import util from '../../util'; import enums from '../../enums'; import { getLegacyCipher, getCipherParams } from '../cipher'; +import { getRandomBytes } from '../random'; const webCrypto = util.getWebCrypto(); const nodeCrypto = util.getNodeCrypto(); @@ -43,6 +44,20 @@ const nodeAlgos = { /* twofish is not implemented in OpenSSL */ }; +/** + * 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. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ +export async function getPrefixRandom(algo) { + const { blockSize } = getCipherParams(algo); + const prefixrandom = await getRandomBytes(blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return util.concat([prefixrandom, repeat]); +} + /** * CFB encryption * @param {enums.symmetric} algo - block cipher algorithm diff --git a/src/crypto/mode/eax.js b/src/crypto/cipherMode/eax.js similarity index 100% rename from src/crypto/mode/eax.js rename to src/crypto/cipherMode/eax.js diff --git a/src/crypto/mode/gcm.js b/src/crypto/cipherMode/gcm.js similarity index 100% rename from src/crypto/mode/gcm.js rename to src/crypto/cipherMode/gcm.js diff --git a/src/crypto/cipherMode/index.js b/src/crypto/cipherMode/index.js new file mode 100644 index 00000000..6985b2a0 --- /dev/null +++ b/src/crypto/cipherMode/index.js @@ -0,0 +1,35 @@ +/** + * @fileoverview Cipher modes + * @module crypto/cipherMode + */ + +export * as cfb from './cfb'; +import eax from './eax'; +import ocb from './ocb'; +import gcm from './gcm'; +import enums from '../../enums'; + +/** +* Get implementation of the given AEAD mode +* @param {enums.aead} algo +* @param {Boolean} [acceptExperimentalGCM] - whether to allow the non-standard, legacy `experimentalGCM` algo +* @returns {Object} +* @throws {Error} on invalid algo +*/ +export function getAEADMode(algo, acceptExperimentalGCM = false) { + switch (algo) { + case enums.aead.eax: + return eax; + case enums.aead.ocb: + return ocb; + case enums.aead.gcm: + return gcm; + case enums.aead.experimentalGCM: + if (!acceptExperimentalGCM) { + throw new Error('Unexpected non-standard `experimentalGCM` AEAD algorithm provided in `config.preferredAEADAlgorithm`: use `gcm` instead'); + } + return gcm; + default: + throw new Error('Unsupported AEAD mode'); + } +} diff --git a/src/crypto/mode/ocb.js b/src/crypto/cipherMode/ocb.js similarity index 100% rename from src/crypto/mode/ocb.js rename to src/crypto/cipherMode/ocb.js diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index c4a586e7..0edf846a 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -23,8 +23,7 @@ * @module crypto/crypto */ -import publicKey from './public_key'; -import mode from './mode'; +import { rsa, elliptic, elgamal, dsa } from './public_key'; import { getRandomBytes } from './random'; import { getCipherParams } from './cipher'; import ECDHSymkey from '../type/ecdh_symkey'; @@ -51,16 +50,16 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, dat case enums.publicKey.rsaEncrypt: case enums.publicKey.rsaEncryptSign: { const { n, e } = publicParams; - const c = await publicKey.rsa.encrypt(data, n, e); + const c = await rsa.encrypt(data, n, e); return { c }; } case enums.publicKey.elgamal: { const { p, g, y } = publicParams; - return publicKey.elgamal.encrypt(data, p, g, y); + return elgamal.encrypt(data, p, g, y); } case enums.publicKey.ecdh: { const { oid, Q, kdfParams } = publicParams; - const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( + const { publicKey: V, wrappedKey: C } = await elliptic.ecdh.encrypt( oid, kdfParams, data, Q, fingerprint); return { V, C: new ECDHSymkey(C) }; } @@ -71,7 +70,7 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, dat throw new Error('X25519 and X448 keys can only encrypt AES session keys'); } const { A } = publicParams; - const { ephemeralPublicKey, wrappedKey } = await publicKey.elliptic.ecdhX.encrypt( + const { ephemeralPublicKey, wrappedKey } = await elliptic.ecdhX.encrypt( keyAlgo, data, A); const C = ECDHXSymmetricKey.fromObject({ algorithm: symmetricAlgo, wrappedKey }); return { ephemeralPublicKey, C }; @@ -102,19 +101,19 @@ export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, const { c } = sessionKeyParams; const { n, e } = publicKeyParams; const { d, p, q, u } = privateKeyParams; - return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); + return rsa.decrypt(c, n, e, d, p, q, u, randomPayload); } case enums.publicKey.elgamal: { const { c1, c2 } = sessionKeyParams; const p = publicKeyParams.p; const x = privateKeyParams.x; - return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); + return elgamal.decrypt(c1, c2, p, x, randomPayload); } case enums.publicKey.ecdh: { const { oid, Q, kdfParams } = publicKeyParams; const { d } = privateKeyParams; const { V, C } = sessionKeyParams; - return publicKey.elliptic.ecdh.decrypt( + return elliptic.ecdh.decrypt( oid, kdfParams, V, C.data, Q, d, fingerprint); } case enums.publicKey.x25519: @@ -125,7 +124,7 @@ export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, if (C.algorithm !== null && !util.isAES(C.algorithm)) { throw new Error('AES session key expected'); } - return publicKey.elliptic.ecdhX.decrypt( + return elliptic.ecdhX.decrypt( algo, ephemeralPublicKey, C.wrappedKey, A, k); } default: @@ -338,22 +337,22 @@ export function generateParams(algo, bits, oid) { case enums.publicKey.rsaEncrypt: case enums.publicKey.rsaEncryptSign: case enums.publicKey.rsaSign: - return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ + return rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ privateParams: { d, p, q, u }, publicParams: { n, e } })); case enums.publicKey.ecdsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + return elliptic.generate(oid).then(({ oid, Q, secret }) => ({ privateParams: { d: secret }, publicParams: { oid: new OID(oid), Q } })); case enums.publicKey.eddsaLegacy: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + return elliptic.generate(oid).then(({ oid, Q, secret }) => ({ privateParams: { seed: secret }, publicParams: { oid: new OID(oid), Q } })); case enums.publicKey.ecdh: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ + return elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ privateParams: { d: secret }, publicParams: { oid: new OID(oid), @@ -363,13 +362,13 @@ export function generateParams(algo, bits, oid) { })); case enums.publicKey.ed25519: case enums.publicKey.ed448: - return publicKey.elliptic.eddsa.generate(algo).then(({ A, seed }) => ({ + return elliptic.eddsa.generate(algo).then(({ A, seed }) => ({ privateParams: { seed }, publicParams: { A } })); case enums.publicKey.x25519: case enums.publicKey.x448: - return publicKey.elliptic.ecdhX.generate(algo).then(({ A, k }) => ({ + return elliptic.ecdhX.generate(algo).then(({ A, k }) => ({ privateParams: { k }, publicParams: { A } })); @@ -399,21 +398,21 @@ export async function validateParams(algo, publicParams, privateParams) { case enums.publicKey.rsaSign: { const { n, e } = publicParams; const { d, p, q, u } = privateParams; - return publicKey.rsa.validateParams(n, e, d, p, q, u); + return rsa.validateParams(n, e, d, p, q, u); } case enums.publicKey.dsa: { const { p, q, g, y } = publicParams; const { x } = privateParams; - return publicKey.dsa.validateParams(p, q, g, y, x); + return dsa.validateParams(p, q, g, y, x); } case enums.publicKey.elgamal: { const { p, g, y } = publicParams; const { x } = privateParams; - return publicKey.elgamal.validateParams(p, g, y, x); + return elgamal.validateParams(p, g, y, x); } case enums.publicKey.ecdsa: case enums.publicKey.ecdh: { - const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; + const algoModule = elliptic[enums.read(enums.publicKey, algo)]; const { oid, Q } = publicParams; const { d } = privateParams; return algoModule.validateParams(oid, Q, d); @@ -421,39 +420,25 @@ export async function validateParams(algo, publicParams, privateParams) { case enums.publicKey.eddsaLegacy: { const { Q, oid } = publicParams; const { seed } = privateParams; - return publicKey.elliptic.eddsaLegacy.validateParams(oid, Q, seed); + return elliptic.eddsaLegacy.validateParams(oid, Q, seed); } case enums.publicKey.ed25519: case enums.publicKey.ed448: { const { A } = publicParams; const { seed } = privateParams; - return publicKey.elliptic.eddsa.validateParams(algo, A, seed); + return elliptic.eddsa.validateParams(algo, A, seed); } case enums.publicKey.x25519: case enums.publicKey.x448: { const { A } = publicParams; const { k } = privateParams; - return publicKey.elliptic.ecdhX.validateParams(algo, A, k); + return elliptic.ecdhX.validateParams(algo, A, k); } default: throw new Error('Unknown public key 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. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ -export async function getPrefixRandom(algo) { - const { blockSize } = getCipherParams(algo); - const prefixrandom = await getRandomBytes(blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return util.concat([prefixrandom, repeat]); -} - /** * Generating a session key for the specified symmetric algorithm * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. @@ -465,31 +450,6 @@ export function generateSessionKey(algo) { return getRandomBytes(keySize); } -/** - * Get implementation of the given AEAD mode - * @param {enums.aead} algo - * @param {Boolean} [acceptExperimentalGCM] - whether to allow the non-standard, legacy `experimentalGCM` algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -export function getAEADMode(algo, acceptExperimentalGCM = false) { - switch (algo) { - case enums.aead.eax: - return mode.eax; - case enums.aead.ocb: - return mode.ocb; - case enums.aead.gcm: - return mode.gcm; - case enums.aead.experimentalGCM: - if (!acceptExperimentalGCM) { - throw new Error('Unexpected non-standard `experimentalGCM` AEAD algorithm provided in `config.preferredAEADAlgorithm`: use `gcm` instead'); - } - return mode.gcm; - default: - throw new Error('Unsupported AEAD mode'); - } -} - /** * Check whether the given curve OID is supported * @param {module:type/oid} oid - EC object identifier @@ -513,13 +473,13 @@ export function getCurvePayloadSize(algo, oid) { case enums.publicKey.ecdsa: case enums.publicKey.ecdh: case enums.publicKey.eddsaLegacy: - return new publicKey.elliptic.CurveWithOID(oid).payloadSize; + return new elliptic.CurveWithOID(oid).payloadSize; case enums.publicKey.ed25519: case enums.publicKey.ed448: - return publicKey.elliptic.eddsa.getPayloadSize(algo); + return elliptic.eddsa.getPayloadSize(algo); case enums.publicKey.x25519: case enums.publicKey.x448: - return publicKey.elliptic.ecdhX.getPayloadSize(algo); + return elliptic.ecdhX.getPayloadSize(algo); default: throw new Error('Unknown elliptic algo'); } @@ -534,14 +494,12 @@ export function getPreferredCurveHashAlgo(algo, oid) { switch (algo) { case enums.publicKey.ecdsa: case enums.publicKey.eddsaLegacy: - return publicKey.elliptic.getPreferredHashAlgo(oid); + return elliptic.getPreferredHashAlgo(oid); case enums.publicKey.ed25519: case enums.publicKey.ed448: - return publicKey.elliptic.eddsa.getPreferredHashAlgo(algo); + return elliptic.eddsa.getPreferredHashAlgo(algo); default: throw new Error('Unknown elliptic signing algo'); } } - -export { getCipherParams }; diff --git a/src/crypto/hash/index.js b/src/crypto/hash/index.js index 3332a1ce..968c9785 100644 --- a/src/crypto/hash/index.js +++ b/src/crypto/hash/index.js @@ -6,7 +6,7 @@ */ import * as stream from '@openpgp/web-stream-tools'; -import md5 from './md5'; +import computeMd5 from './md5'; import util from '../../util'; import enums from '../../enums'; @@ -55,76 +55,72 @@ function nobleHash(nobleHashName, webCryptoHashName) { }; } -export default { +const md5 = nodeHash('md5') || computeMd5; +const sha1 = nodeHash('sha1') || nobleHash('sha1', 'SHA-1'); +const sha224 = nodeHash('sha224') || nobleHash('sha224'); +const sha256 = nodeHash('sha256') || nobleHash('sha256', 'SHA-256'); +const sha384 = nodeHash('sha384') || nobleHash('sha384', 'SHA-384'); +const sha512 = nodeHash('sha512') || nobleHash('sha512', 'SHA-512'); +const ripemd = nodeHash('ripemd160') || nobleHash('ripemd160'); +const sha3_256 = nodeHash('sha3-256') || nobleHash('sha3_256'); +const sha3_512 = nodeHash('sha3-512') || nobleHash('sha3_512'); - /** @see module:md5 */ - md5: nodeHash('md5') || md5, - sha1: nodeHash('sha1') || nobleHash('sha1', 'SHA-1'), - sha224: nodeHash('sha224') || nobleHash('sha224'), - sha256: nodeHash('sha256') || nobleHash('sha256', 'SHA-256'), - sha384: nodeHash('sha384') || nobleHash('sha384', 'SHA-384'), - sha512: nodeHash('sha512') || nobleHash('sha512', 'SHA-512'), - ripemd: nodeHash('ripemd160') || nobleHash('ripemd160'), - sha3_256: nodeHash('sha3-256') || nobleHash('sha3_256'), - sha3_512: nodeHash('sha3-512') || nobleHash('sha3_512'), - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data - Data to be hashed - * @returns {Promise} Hash value. - */ - digest: function(algo, data) { - switch (algo) { - case enums.hash.md5: - return this.md5(data); - case enums.hash.sha1: - return this.sha1(data); - case enums.hash.ripemd: - return this.ripemd(data); - case enums.hash.sha256: - return this.sha256(data); - case enums.hash.sha384: - return this.sha384(data); - case enums.hash.sha512: - return this.sha512(data); - case enums.hash.sha224: - return this.sha224(data); - case enums.hash.sha3_256: - return this.sha3_256(data); - case enums.hash.sha3_512: - return this.sha3_512(data); - default: - throw new Error('Unsupported hash function'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash. - */ - getHashByteLength: function(algo) { - switch (algo) { - case enums.hash.md5: - return 16; - case enums.hash.sha1: - case enums.hash.ripemd: - return 20; - case enums.hash.sha256: - return 32; - case enums.hash.sha384: - return 48; - case enums.hash.sha512: - return 64; - case enums.hash.sha224: - return 28; - case enums.hash.sha3_256: - return 32; - case enums.hash.sha3_512: - return 64; - default: - throw new Error('Invalid hash algorithm.'); - } +/** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data - Data to be hashed + * @returns {Promise} Hash value. + */ +export function computeDigest(algo, data) { + switch (algo) { + case enums.hash.md5: + return md5(data); + case enums.hash.sha1: + return sha1(data); + case enums.hash.ripemd: + return ripemd(data); + case enums.hash.sha256: + return sha256(data); + case enums.hash.sha384: + return sha384(data); + case enums.hash.sha512: + return sha512(data); + case enums.hash.sha224: + return sha224(data); + case enums.hash.sha3_256: + return sha3_256(data); + case enums.hash.sha3_512: + return sha3_512(data); + default: + throw new Error('Unsupported hash function'); } -}; +} + +/** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash. + */ +export function getHashByteLength(algo) { + switch (algo) { + case enums.hash.md5: + return 16; + case enums.hash.sha1: + case enums.hash.ripemd: + return 20; + case enums.hash.sha256: + return 32; + case enums.hash.sha384: + return 48; + case enums.hash.sha512: + return 64; + case enums.hash.sha224: + return 28; + case enums.hash.sha3_256: + return 32; + case enums.hash.sha3_512: + return 64; + default: + throw new Error('Invalid hash algorithm.'); + } +} diff --git a/src/crypto/index.js b/src/crypto/index.js index 460140c1..596d2af2 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -9,39 +9,10 @@ * @module crypto */ -import * as cipher from './cipher'; -import hash from './hash'; -import mode from './mode'; -import publicKey from './public_key'; -import * as signature from './signature'; -import * as random from './random'; -import * as pkcs1 from './pkcs1'; -import * as pkcs5 from './pkcs5'; -import * as crypto from './crypto'; -import * as aesKW from './aes_kw'; - -// TODO move cfb and gcm to cipher -const mod = { - /** @see module:crypto/cipher */ - cipher: cipher, - /** @see module:crypto/hash */ - hash: hash, - /** @see module:crypto/mode */ - mode: mode, - /** @see module:crypto/public_key */ - publicKey: publicKey, - /** @see module:crypto/signature */ - signature: signature, - /** @see module:crypto/random */ - random: random, - /** @see module:crypto/pkcs1 */ - pkcs1: pkcs1, - /** @see module:crypto/pkcs5 */ - pkcs5: pkcs5, - /** @see module:crypto/aes_kw */ - aesKW: aesKW -}; - -Object.assign(mod, crypto); - -export default mod; +export * from './crypto'; +export { getCipherParams } from './cipher'; +export * from './hash'; +export * as cipherMode from './cipherMode'; +export * as publicKey from './public_key'; +export * as signature from './signature'; +export { getRandomBytes } from './random'; diff --git a/src/crypto/mode/index.js b/src/crypto/mode/index.js deleted file mode 100644 index beeeca55..00000000 --- a/src/crypto/mode/index.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @fileoverview Cipher modes - * @module crypto/mode - */ - -import * as cfb from './cfb'; -import eax from './eax'; -import ocb from './ocb'; -import gcm from './gcm'; - -export default { - /** @see module:crypto/mode/cfb */ - cfb: cfb, - /** @see module:crypto/mode/gcm */ - gcm: gcm, - experimentalGCM: gcm, - /** @see module:crypto/mode/eax */ - eax: eax, - /** @see module:crypto/mode/ocb */ - ocb: ocb -}; diff --git a/src/crypto/pkcs1.js b/src/crypto/pkcs1.js index d888017d..bb920c4e 100644 --- a/src/crypto/pkcs1.js +++ b/src/crypto/pkcs1.js @@ -24,7 +24,7 @@ */ import { getRandomBytes } from './random'; -import hash from './hash'; +import { getHashByteLength } from './hash'; import util from '../util'; /** @@ -134,7 +134,7 @@ export function emeDecode(encoded, randomPayload) { */ export function emsaEncode(algo, hashed, emLen) { let i; - if (hashed.length !== hash.getHashByteLength(algo)) { + if (hashed.length !== getHashByteLength(algo)) { throw new Error('Invalid hash length'); } // produce an ASN.1 DER value for the hash function used. diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index 18bdc664..66937b2c 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -22,7 +22,7 @@ import { CurveWithOID, jwkToRawPublic, rawPublicToJWK, privateToJWK, validateStandardParams, checkPublicPointEnconding } from './oid_curves'; import * as aesKW from '../../aes_kw'; -import hash from '../../hash'; +import { computeDigest } from '../../hash'; import enums from '../../../enums'; import util from '../../../util'; import { b64ToUint8Array } from '../../../encoding/base64'; @@ -72,7 +72,7 @@ async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTraili for (i = X.length - 1; i >= 0 && X[i] === 0; i--); X = X.subarray(0, i + 1); } - const digest = await hash.digest(hashAlgo, util.concatUint8Array([ + const digest = await computeDigest(hashAlgo, util.concatUint8Array([ new Uint8Array([0, 0, 0, 1]), X, param diff --git a/src/crypto/public_key/elliptic/ecdsa.js b/src/crypto/public_key/elliptic/ecdsa.js index b0797963..58f33398 100644 --- a/src/crypto/public_key/elliptic/ecdsa.js +++ b/src/crypto/public_key/elliptic/ecdsa.js @@ -23,7 +23,7 @@ import enums from '../../../enums'; import util from '../../../util'; import { getRandomBytes } from '../../random'; -import hash from '../../hash'; +import { computeDigest } from '../../hash'; import { CurveWithOID, webCurves, privateToJWK, rawPublicToJWK, validateStandardParams, nodeCurves, checkPublicPointEnconding } from './oid_curves'; import { bigIntToUint8Array } from '../../biginteger'; @@ -156,7 +156,7 @@ export async function validateParams(oid, Q, d) { case 'node': { const message = getRandomBytes(8); const hashAlgo = enums.hash.sha256; - const hashed = await hash.digest(hashAlgo, message); + const hashed = await computeDigest(hashAlgo, message); try { const signature = await sign(oid, hashAlgo, message, Q, d, hashed); // eslint-disable-next-line @typescript-eslint/return-await diff --git a/src/crypto/public_key/elliptic/eddsa.js b/src/crypto/public_key/elliptic/eddsa.js index 7b41eb23..79d68db4 100644 --- a/src/crypto/public_key/elliptic/eddsa.js +++ b/src/crypto/public_key/elliptic/eddsa.js @@ -23,7 +23,7 @@ import ed25519 from '@openpgp/tweetnacl'; import util from '../../../util'; import enums from '../../../enums'; -import hash from '../../hash'; +import { getHashByteLength } from '../../hash'; import { getRandomBytes } from '../../random'; import { b64ToUint8Array, uint8ArrayToB64 } from '../../../encoding/base64'; @@ -81,7 +81,7 @@ export async function generate(algo) { * @async */ export async function sign(algo, hashAlgo, message, publicKey, privateKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo(algo))) { + if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo(algo))) { // Enforce digest sizes: // - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4 // - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4 @@ -131,7 +131,7 @@ export async function sign(algo, hashAlgo, message, publicKey, privateKey, hashe * @async */ export async function verify(algo, hashAlgo, { RS }, m, publicKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo(algo))) { + if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo(algo))) { // Enforce digest sizes: // - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4 // - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4 diff --git a/src/crypto/public_key/elliptic/eddsa_legacy.js b/src/crypto/public_key/elliptic/eddsa_legacy.js index a88e67b4..682f53bb 100644 --- a/src/crypto/public_key/elliptic/eddsa_legacy.js +++ b/src/crypto/public_key/elliptic/eddsa_legacy.js @@ -24,7 +24,7 @@ import nacl from '@openpgp/tweetnacl'; import util from '../../../util'; import enums from '../../../enums'; -import hash from '../../hash'; +import { getHashByteLength } from '../../hash'; import { CurveWithOID, checkPublicPointEnconding } from './oid_curves'; import { sign as eddsaSign, verify as eddsaVerify } from './eddsa'; @@ -45,7 +45,7 @@ import { sign as eddsaSign, verify as eddsaVerify } from './eddsa'; export async function sign(oid, hashAlgo, message, publicKey, privateKey, hashed) { const curve = new CurveWithOID(oid); checkPublicPointEnconding(curve, publicKey); - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) { // Enforce digest sizes, since the constraint was already present in RFC4880bis: // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 // and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3 @@ -74,7 +74,7 @@ export async function sign(oid, hashAlgo, message, publicKey, privateKey, hashed export async function verify(oid, hashAlgo, { r, s }, m, publicKey, hashed) { const curve = new CurveWithOID(oid); checkPublicPointEnconding(curve, publicKey); - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) { // Enforce digest sizes, since the constraint was already present in RFC4880bis: // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 // and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3 diff --git a/src/crypto/public_key/index.js b/src/crypto/public_key/index.js index ffcf73cc..f49b4d24 100644 --- a/src/crypto/public_key/index.js +++ b/src/crypto/public_key/index.js @@ -3,18 +3,7 @@ * @module crypto/public_key */ -import * as rsa from './rsa'; -import * as elgamal from './elgamal'; -import * as elliptic from './elliptic'; -import * as dsa from './dsa'; - -export default { - /** @see module:crypto/public_key/rsa */ - rsa: rsa, - /** @see module:crypto/public_key/elgamal */ - elgamal: elgamal, - /** @see module:crypto/public_key/elliptic */ - elliptic: elliptic, - /** @see module:crypto/public_key/dsa */ - dsa: dsa -}; +export * as rsa from './rsa'; +export * as elgamal from './elgamal'; +export * as elliptic from './elliptic'; +export * as dsa from './dsa'; diff --git a/src/crypto/public_key/rsa.js b/src/crypto/public_key/rsa.js index 07ac8484..02c8e691 100644 --- a/src/crypto/public_key/rsa.js +++ b/src/crypto/public_key/rsa.js @@ -26,7 +26,7 @@ import { uint8ArrayToB64, b64ToUint8Array } from '../../encoding/base64'; import { emsaEncode, emeEncode, emeDecode } from '../pkcs1'; import enums from '../../enums'; import { bigIntToNumber, bigIntToUint8Array, bitLength, byteLength, mod, modExp, modInv, uint8ArrayToBigInt } from '../biginteger'; -import hash from '../hash'; +import { getHashByteLength } from '../hash'; const webCrypto = util.getWebCrypto(); const nodeCrypto = util.getNodeCrypto(); @@ -46,7 +46,7 @@ const _1n = BigInt(1); * @async */ export async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { - if (hash.getHashByteLength(hashAlgo) >= n.length) { + if (getHashByteLength(hashAlgo) >= n.length) { // Throw here instead of `emsaEncode` below, to provide a clearer and consistent error // e.g. if a 512-bit RSA key is used with a SHA-512 digest. // The size limit is actually slightly different but here we only care about throwing diff --git a/src/crypto/signature.js b/src/crypto/signature.js index 4f78a1ad..3156ebdd 100644 --- a/src/crypto/signature.js +++ b/src/crypto/signature.js @@ -3,7 +3,7 @@ * @module crypto/signature */ -import publicKey from './public_key'; +import { elliptic, rsa, dsa } from './public_key'; import enums from '../enums'; import util from '../util'; import { UnsupportedError } from '../packet/packet'; @@ -61,7 +61,7 @@ export function parseSignatureParams(algo, signature) { // - 114 octets of the native signature case enums.publicKey.ed25519: case enums.publicKey.ed448: { - const rsSize = 2 * publicKey.elliptic.eddsa.getPayloadSize(algo); + const rsSize = 2 * elliptic.eddsa.getPayloadSize(algo); const RS = util.readExactSubarray(signature, read, read + rsSize); read += RS.length; return { read, signatureParams: { RS } }; } @@ -92,34 +92,34 @@ export async function verify(algo, hashAlgo, signature, publicParams, data, hash case enums.publicKey.rsaSign: { const { n, e } = publicParams; const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto - return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); + return rsa.verify(hashAlgo, data, s, n, e, hashed); } case enums.publicKey.dsa: { const { g, p, q, y } = publicParams; const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers - return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); + return dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); } case enums.publicKey.ecdsa: { const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize; + const curveSize = new elliptic.CurveWithOID(oid).payloadSize; // padding needed for webcrypto const r = util.leftPad(signature.r, curveSize); const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + return elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); } case enums.publicKey.eddsaLegacy: { const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize; + const curveSize = new elliptic.CurveWithOID(oid).payloadSize; // When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values: // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 const r = util.leftPad(signature.r, curveSize); const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.eddsaLegacy.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + return elliptic.eddsaLegacy.verify(oid, hashAlgo, { r, s }, data, Q, hashed); } case enums.publicKey.ed25519: case enums.publicKey.ed448: { const { A } = publicParams; - return publicKey.elliptic.eddsa.verify(algo, hashAlgo, signature, data, A, hashed); + return elliptic.eddsa.verify(algo, hashAlgo, signature, data, A, hashed); } default: throw new Error('Unknown signature algorithm.'); @@ -150,31 +150,31 @@ export async function sign(algo, hashAlgo, publicKeyParams, privateKeyParams, da case enums.publicKey.rsaSign: { const { n, e } = publicKeyParams; const { d, p, q, u } = privateKeyParams; - const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); + const s = await rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); return { s }; } case enums.publicKey.dsa: { const { g, p, q } = publicKeyParams; const { x } = privateKeyParams; - return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); + return dsa.sign(hashAlgo, hashed, g, p, q, x); } case enums.publicKey.elgamal: throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); case enums.publicKey.ecdsa: { const { oid, Q } = publicKeyParams; const { d } = privateKeyParams; - return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); + return elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); } case enums.publicKey.eddsaLegacy: { const { oid, Q } = publicKeyParams; const { seed } = privateKeyParams; - return publicKey.elliptic.eddsaLegacy.sign(oid, hashAlgo, data, Q, seed, hashed); + return elliptic.eddsaLegacy.sign(oid, hashAlgo, data, Q, seed, hashed); } case enums.publicKey.ed25519: case enums.publicKey.ed448: { const { A } = publicKeyParams; const { seed } = privateKeyParams; - return publicKey.elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed); + return elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed); } default: throw new Error('Unknown signature algorithm.'); diff --git a/src/key/helper.js b/src/key/helper.js index cd1643d5..89338510 100644 --- a/src/key/helper.js +++ b/src/key/helper.js @@ -9,7 +9,7 @@ import { SignaturePacket } from '../packet'; import enums from '../enums'; -import crypto from '../crypto'; +import { getPreferredCurveHashAlgo, getHashByteLength } from '../crypto'; import util from '../util'; import defaultConfig from '../config'; @@ -149,10 +149,10 @@ export async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = } const sortedHashAlgos = Array.from(supportedAlgosMap.keys()) .filter(hashAlgo => isSupportedHashAlgo(hashAlgo)) - .sort((algoA, algoB) => crypto.hash.getHashByteLength(algoA) - crypto.hash.getHashByteLength(algoB)); + .sort((algoA, algoB) => getHashByteLength(algoA) - getHashByteLength(algoB)); const strongestHashAlgo = sortedHashAlgos[0]; // defaultAlgo is always implicilty supported, and might be stronger than the rest - return crypto.hash.getHashByteLength(strongestHashAlgo) >= crypto.hash.getHashByteLength(defaultAlgo) ? strongestHashAlgo : defaultAlgo; + return getHashByteLength(strongestHashAlgo) >= getHashByteLength(defaultAlgo) ? strongestHashAlgo : defaultAlgo; }; const eccAlgos = new Set([ @@ -171,16 +171,16 @@ export async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = // Hence, we return the `preferredHashAlgo` as long as it's supported and strong enough; // Otherwise, we look at the strongest supported algo, and ultimately fallback to the curve // preferred algo, even if not supported by all targets. - const preferredCurveAlgo = crypto.getPreferredCurveHashAlgo(signingKeyPacket.algorithm, signingKeyPacket.publicParams.oid); + const preferredCurveAlgo = getPreferredCurveHashAlgo(signingKeyPacket.algorithm, signingKeyPacket.publicParams.oid); const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo); - const preferredSenderAlgoStrongerThanCurveAlgo = crypto.hash.getHashByteLength(preferredSenderAlgo) >= crypto.hash.getHashByteLength(preferredCurveAlgo); + const preferredSenderAlgoStrongerThanCurveAlgo = getHashByteLength(preferredSenderAlgo) >= getHashByteLength(preferredCurveAlgo); if (preferredSenderAlgoIsSupported && preferredSenderAlgoStrongerThanCurveAlgo) { return preferredSenderAlgo; } else { const strongestSupportedAlgo = getStrongestSupportedHashAlgo(); - return crypto.hash.getHashByteLength(strongestSupportedAlgo) >= crypto.hash.getHashByteLength(preferredCurveAlgo) ? + return getHashByteLength(strongestSupportedAlgo) >= getHashByteLength(preferredCurveAlgo) ? strongestSupportedAlgo : preferredCurveAlgo; } diff --git a/src/message.js b/src/message.js index d90efb58..9045ed60 100644 --- a/src/message.js +++ b/src/message.js @@ -19,7 +19,7 @@ import * as stream from '@openpgp/web-stream-tools'; import { armor, unarmor } from './encoding/armor'; import { Argon2OutOfMemoryError } from './type/s2k'; import defaultConfig from './config'; -import crypto from './crypto'; +import { generateSessionKey } from './crypto'; import enums from './enums'; import util from './util'; import { Signature } from './signature'; @@ -255,7 +255,7 @@ export class Message { pkeskPacketCopy.read(serialisedPKESK); const randomSessionKey = { sessionKeyAlgorithm, - sessionKey: crypto.generateSessionKey(sessionKeyAlgorithm) + sessionKey: generateSessionKey(sessionKeyAlgorithm) }; try { await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); @@ -368,7 +368,7 @@ export class Message { }) )); - const sessionKeyData = crypto.generateSessionKey(symmetricAlgo); + const sessionKeyData = generateSessionKey(symmetricAlgo); return { data: sessionKeyData, algorithm: symmetricAlgoName, aeadAlgorithm: aeadAlgoName }; } diff --git a/src/packet/aead_encrypted_data.js b/src/packet/aead_encrypted_data.js index aa8d3429..0117b19f 100644 --- a/src/packet/aead_encrypted_data.js +++ b/src/packet/aead_encrypted_data.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import * as stream from '@openpgp/web-stream-tools'; -import crypto from '../crypto'; +import { cipherMode, getRandomBytes } from '../crypto'; import enums from '../enums'; import util from '../util'; import defaultConfig from '../config'; @@ -78,7 +78,7 @@ class AEADEncryptedDataPacket { this.aeadAlgorithm = await reader.readByte(); this.chunkSizeByte = await reader.readByte(); - const mode = crypto.getAEADMode(this.aeadAlgorithm, true); + const mode = cipherMode.getAEADMode(this.aeadAlgorithm, true); this.iv = await reader.readBytes(mode.ivLength); this.encrypted = reader.remainder(); }); @@ -119,8 +119,8 @@ class AEADEncryptedDataPacket { async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { this.cipherAlgorithm = sessionKeyAlgorithm; - const { ivLength } = crypto.getAEADMode(this.aeadAlgorithm, true); - this.iv = crypto.random.getRandomBytes(ivLength); // generate new random IV + const { ivLength } = cipherMode.getAEADMode(this.aeadAlgorithm, true); + this.iv = getRandomBytes(ivLength); // generate new random IV this.chunkSizeByte = config.aeadChunkSizeByte; const data = this.packets.write(); this.encrypted = await runAEAD(this, 'encrypt', key, data); diff --git a/src/packet/padding.js b/src/packet/padding.js index 8baec745..13b2c040 100644 --- a/src/packet/padding.js +++ b/src/packet/padding.js @@ -15,7 +15,7 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -import crypto from '../crypto'; +import { getRandomBytes } from '../crypto'; import enums from '../enums'; /** @@ -56,7 +56,7 @@ class PaddingPacket { * @async */ async createPadding(length) { - this.padding = await crypto.random.getRandomBytes(length); + this.padding = await getRandomBytes(length); } } diff --git a/src/packet/public_key.js b/src/packet/public_key.js index c3b13071..4d2235fc 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -17,7 +17,7 @@ import KeyID from '../type/keyid'; import defaultConfig from '../config'; -import crypto from '../crypto'; +import { computeDigest, parsePublicKeyParams, serializeParams } from '../crypto'; import enums from '../enums'; import util from '../util'; import { UnsupportedError } from './packet'; @@ -126,7 +126,7 @@ class PublicKeyPacket { } // - A series of values comprising the key material. - const { read, publicParams } = crypto.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); + const { read, publicParams } = parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); // The deprecated OIDs for Ed25519Legacy and Curve25519Legacy are used in legacy version 4 keys and signatures. // Implementations MUST NOT accept or generate v6 key material using the deprecated OIDs. if ( @@ -160,7 +160,7 @@ class PublicKeyPacket { // A one-octet number denoting the public-key algorithm of this key arr.push(new Uint8Array([this.algorithm])); - const params = crypto.serializeParams(this.algorithm, this.publicParams); + const params = serializeParams(this.algorithm, this.publicParams); if (this.version >= 5) { // A four-octet scalar octet count for the following key material arr.push(util.writeNumber(params.length, 4)); @@ -230,9 +230,9 @@ class PublicKeyPacket { const toHash = this.writeForHash(this.version); if (this.version >= 5) { - this.fingerprint = await crypto.hash.sha256(toHash); + this.fingerprint = await computeDigest(enums.hash.sha256, toHash); } else if (this.version === 4) { - this.fingerprint = await crypto.hash.sha1(toHash); + this.fingerprint = await computeDigest(enums.hash.sha1, toHash); } else { throw new Error('Unsupported key version'); } diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index eaa5dacd..5a751d05 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import KeyID from '../type/keyid'; -import crypto from '../crypto'; +import { parseEncSessionKeyParams, publicKeyEncrypt, publicKeyDecrypt, getCipherParams, serializeParams } from '../crypto'; import enums from '../enums'; import util from '../util'; import { UnsupportedError } from './packet'; @@ -127,7 +127,7 @@ class PublicKeyEncryptedSessionKeyPacket { offset += this.publicKeyID.read(bytes.subarray(offset, offset + 8)); } this.publicKeyAlgorithm = bytes[offset++]; - this.encrypted = crypto.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(offset)); + this.encrypted = parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(offset)); if (this.publicKeyAlgorithm === enums.publicKey.x25519 || this.publicKeyAlgorithm === enums.publicKey.x448) { if (this.version === 3) { this.sessionKeyAlgorithm = enums.write(enums.symmetric, this.encrypted.C.algorithm); @@ -163,7 +163,7 @@ class PublicKeyEncryptedSessionKeyPacket { arr.push( new Uint8Array([this.publicKeyAlgorithm]), - crypto.serializeParams(this.publicKeyAlgorithm, this.encrypted) + serializeParams(this.publicKeyAlgorithm, this.encrypted) ); return util.concatUint8Array(arr); @@ -182,7 +182,7 @@ class PublicKeyEncryptedSessionKeyPacket { const sessionKeyAlgorithm = this.version === 3 ? this.sessionKeyAlgorithm : null; const fingerprint = key.version === 5 ? key.getFingerprintBytes().subarray(0, 20) : key.getFingerprintBytes(); const encoded = encodeSessionKey(this.version, algo, sessionKeyAlgorithm, this.sessionKey); - this.encrypted = await crypto.publicKeyEncrypt( + this.encrypted = await publicKeyEncrypt( algo, sessionKeyAlgorithm, key.publicParams, encoded, fingerprint); } @@ -204,7 +204,7 @@ class PublicKeyEncryptedSessionKeyPacket { encodeSessionKey(this.version, this.publicKeyAlgorithm, randomSessionKey.sessionKeyAlgorithm, randomSessionKey.sessionKey) : null; const fingerprint = key.version === 5 ? key.getFingerprintBytes().subarray(0, 20) : key.getFingerprintBytes(); - const decryptedData = await crypto.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, fingerprint, randomPayload); + const decryptedData = await publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, fingerprint, randomPayload); const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey); @@ -213,7 +213,7 @@ class PublicKeyEncryptedSessionKeyPacket { const hasEncryptedAlgo = this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448; this.sessionKeyAlgorithm = hasEncryptedAlgo ? sessionKeyAlgorithm : this.sessionKeyAlgorithm; - if (sessionKey.length !== crypto.getCipherParams(this.sessionKeyAlgorithm).keySize) { + if (sessionKey.length !== getCipherParams(this.sessionKeyAlgorithm).keySize) { throw new Error('Unexpected session key size'); } } diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 48b31f56..287f888f 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -17,7 +17,7 @@ import PublicKeyPacket from './public_key'; import { newS2KFromConfig, newS2KFromType } from '../type/s2k'; -import crypto from '../crypto'; +import { computeDigest, getCipherParams, parsePrivateKeyParams, serializeParams, generateParams, validateParams, getRandomBytes, cipherMode } from '../crypto'; import enums from '../enums'; import util from '../util'; import defaultConfig from '../config'; @@ -174,7 +174,7 @@ class SecretKeyPacket extends PublicKeyPacket { if (this.s2kUsage !== 253 || this.isLegacyAEAD) { this.iv = bytes.subarray( i, - i + crypto.getCipherParams(this.symmetric).blockSize + i + getCipherParams(this.symmetric).blockSize ); this.usedModernAEAD = false; } else { @@ -183,7 +183,7 @@ class SecretKeyPacket extends PublicKeyPacket { // is used as the nonce for the AEAD algorithm. this.iv = bytes.subarray( i, - i + crypto.getAEADMode(this.aead).ivLength + i + cipherMode.getAEADMode(this.aead).ivLength ); // the non-legacy AEAD encryption mechanism also authenticates public key params; no need for manual validation. this.usedModernAEAD = true; @@ -221,7 +221,7 @@ class SecretKeyPacket extends PublicKeyPacket { } } try { - const { read, privateParams } = crypto.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + const { read, privateParams } = parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); if (read < cleartext.length) { throw new Error('Error reading MPIs'); } @@ -290,7 +290,7 @@ class SecretKeyPacket extends PublicKeyPacket { if (!this.isDummy()) { if (!this.s2kUsage) { - this.keyMaterial = crypto.serializeParams(this.algorithm, this.privateParams); + this.keyMaterial = serializeParams(this.algorithm, this.privateParams); } if (this.version === 5) { @@ -385,15 +385,15 @@ class SecretKeyPacket extends PublicKeyPacket { this.s2k = newS2KFromConfig(config); this.s2k.generateSalt(); - const cleartext = crypto.serializeParams(this.algorithm, this.privateParams); + const cleartext = serializeParams(this.algorithm, this.privateParams); this.symmetric = enums.symmetric.aes256; - const { blockSize } = crypto.getCipherParams(this.symmetric); + const { blockSize } = getCipherParams(this.symmetric); if (config.aeadProtect) { this.s2kUsage = 253; this.aead = config.preferredAEADAlgorithm; - const mode = crypto.getAEADMode(this.aead); + const mode = cipherMode.getAEADMode(this.aead); this.isLegacyAEAD = this.version === 5; // v4 is always re-encrypted with standard format instead. this.usedModernAEAD = !this.isLegacyAEAD; // legacy AEAD does not guarantee integrity of public key material @@ -401,7 +401,7 @@ class SecretKeyPacket extends PublicKeyPacket { const key = await produceEncryptionKey(this.version, this.s2k, passphrase, this.symmetric, this.aead, serializedPacketTag, this.isLegacyAEAD); const modeInstance = await mode(this.symmetric, key); - this.iv = this.isLegacyAEAD ? crypto.random.getRandomBytes(blockSize) : crypto.random.getRandomBytes(mode.ivLength); + this.iv = this.isLegacyAEAD ? getRandomBytes(blockSize) : getRandomBytes(mode.ivLength); const associateData = this.isLegacyAEAD ? new Uint8Array() : util.concatUint8Array([serializedPacketTag, this.writePublicKey()]); @@ -411,10 +411,10 @@ class SecretKeyPacket extends PublicKeyPacket { this.s2kUsage = 254; this.usedModernAEAD = false; const key = await produceEncryptionKey(this.version, this.s2k, passphrase, this.symmetric); - this.iv = crypto.random.getRandomBytes(blockSize); - this.keyMaterial = await crypto.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + this.iv = getRandomBytes(blockSize); + this.keyMaterial = await cipherMode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ cleartext, - await crypto.hash.sha1(cleartext, config) + await computeDigest(enums.hash.sha1, cleartext, config) ]), this.iv, config); } } @@ -454,7 +454,7 @@ class SecretKeyPacket extends PublicKeyPacket { let cleartext; if (this.s2kUsage === 253) { - const mode = crypto.getAEADMode(this.aead, true); + const mode = cipherMode.getAEADMode(this.aead, true); const modeInstance = await mode(this.symmetric, key); try { const associateData = this.isLegacyAEAD ? @@ -468,10 +468,10 @@ class SecretKeyPacket extends PublicKeyPacket { throw err; } } else { - const cleartextWithHash = await crypto.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + const cleartextWithHash = await cipherMode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); cleartext = cleartextWithHash.subarray(0, -20); - const hash = await crypto.hash.sha1(cleartext); + const hash = await computeDigest(enums.hash.sha1, cleartext); if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { throw new Error('Incorrect key passphrase'); @@ -479,7 +479,7 @@ class SecretKeyPacket extends PublicKeyPacket { } try { - const { privateParams } = crypto.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + const { privateParams } = parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); this.privateParams = privateParams; } catch (err) { throw new Error('Error reading MPIs'); @@ -514,7 +514,7 @@ class SecretKeyPacket extends PublicKeyPacket { let validParams; try { // this can throw if some parameters are undefined - validParams = await crypto.validateParams(this.algorithm, this.publicParams, this.privateParams); + validParams = await validateParams(this.algorithm, this.publicParams, this.privateParams); } catch (_) { validParams = false; } @@ -532,7 +532,7 @@ class SecretKeyPacket extends PublicKeyPacket { )) { throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`); } - const { privateParams, publicParams } = await crypto.generateParams(this.algorithm, bits, curve); + const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve); this.privateParams = privateParams; this.publicParams = publicParams; this.isEncrypted = false; @@ -574,7 +574,7 @@ async function produceEncryptionKey(keyVersion, s2k, passphrase, cipherAlgo, aea if (s2k.type === 'simple' && keyVersion === 6) { throw new Error('Using Simple S2K with version 6 keys is not allowed'); } - const { keySize } = crypto.getCipherParams(cipherAlgo); + const { keySize } = getCipherParams(cipherAlgo); const derivedKey = await s2k.produceKey(passphrase, keySize); if (!aeadMode || keyVersion === 5 || isLegacyAEAD) { return derivedKey; diff --git a/src/packet/signature.js b/src/packet/signature.js index 87e0d304..d248103d 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -18,7 +18,7 @@ import * as stream from '@openpgp/web-stream-tools'; import { readSimpleLength, UnsupportedError, writeSimpleLength } from './packet'; import KeyID from '../type/keyid'; -import crypto from '../crypto'; +import { signature, serializeParams, getRandomBytes, getHashByteLength, computeDigest } from '../crypto'; import enums from '../enums'; import util from '../util'; import defaultConfig from '../config'; @@ -166,7 +166,7 @@ class SignaturePacket { } const signatureMaterial = bytes.subarray(i, bytes.length); - const { read, signatureParams } = crypto.signature.parseSignatureParams(this.publicKeyAlgorithm, signatureMaterial); + const { read, signatureParams } = signature.parseSignatureParams(this.publicKeyAlgorithm, signatureMaterial); if (read < signatureMaterial.length) { throw new Error('Error reading MPIs'); } @@ -179,10 +179,10 @@ class SignaturePacket { writeParams() { if (this.params instanceof Promise) { return stream.fromAsync( - async () => crypto.serializeParams(this.publicKeyAlgorithm, await this.params) + async () => serializeParams(this.publicKeyAlgorithm, await this.params) ); } - return crypto.serializeParams(this.publicKeyAlgorithm, this.params); + return serializeParams(this.publicKeyAlgorithm, this.params); } write() { @@ -221,7 +221,7 @@ class SignaturePacket { if (this.version === 6) { const saltLength = saltLengthForHash(this.hashAlgorithm); if (this.salt === null) { - this.salt = crypto.random.getRandomBytes(saltLength); + this.salt = getRandomBytes(saltLength); } else if (saltLength !== this.salt.length) { throw new Error('Provided salt does not have the required length'); } @@ -230,7 +230,7 @@ class SignaturePacket { // since re-signing the same object is not supported, it's not expected to have multiple salt notations, // but we guard against it as a sanity check if (saltNotations.length === 0) { - const saltValue = crypto.random.getRandomBytes(saltLengthForHash(this.hashAlgorithm)); + const saltValue = getRandomBytes(saltLengthForHash(this.hashAlgorithm)); this.rawNotations.push({ name: SALT_NOTATION_NAME, value: saltValue, @@ -256,7 +256,7 @@ class SignaturePacket { const hash = await this.hash(this.signatureType, data, toHash, detached); this.signedHashValue = stream.slice(stream.clone(hash), 0, 2); - const signed = async () => crypto.signature.sign( + const signed = async () => signature.sign( this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await stream.readToEnd(hash) ); if (util.isStream(hash)) { @@ -570,7 +570,7 @@ class SignaturePacket { this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; this.signatureTargetHashAlgorithm = bytes[mypos++]; - const len = crypto.getHashByteLength(this.signatureTargetHashAlgorithm); + const len = getHashByteLength(this.signatureTargetHashAlgorithm); this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); break; @@ -738,7 +738,7 @@ class SignaturePacket { } if (!toHash) toHash = this.toHash(signatureType, data, detached); - return crypto.hash.digest(this.hashAlgorithm, toHash); + return computeDigest(this.hashAlgorithm, toHash); } /** @@ -782,7 +782,7 @@ class SignaturePacket { this.params = await this.params; - this[verified] = await crypto.signature.verify( + this[verified] = await signature.verify( this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, toHash, hash ); diff --git a/src/packet/sym_encrypted_integrity_protected_data.js b/src/packet/sym_encrypted_integrity_protected_data.js index 5e3417a4..94f96440 100644 --- a/src/packet/sym_encrypted_integrity_protected_data.js +++ b/src/packet/sym_encrypted_integrity_protected_data.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import * as stream from '@openpgp/web-stream-tools'; -import crypto from '../crypto'; +import { cipherMode, getRandomBytes, getCipherParams, computeDigest } from '../crypto'; import computeHKDF from '../crypto/hkdf'; import enums from '../enums'; import util from '../util'; @@ -133,7 +133,7 @@ class SymEncryptedIntegrityProtectedDataPacket { // but we want to ensure that the input key isn't e.g. too short. // The check is done here, instead of on encrypted session key (ESK) encryption, because v6 ESK packets do not store the session key algorithm, // which is instead included in the SEIPDv2 data. - const { blockSize, keySize } = crypto.getCipherParams(sessionKeyAlgorithm); + const { blockSize, keySize } = getCipherParams(sessionKeyAlgorithm); if (key.length !== keySize) { throw new Error('Unexpected session key size'); } @@ -144,18 +144,18 @@ class SymEncryptedIntegrityProtectedDataPacket { if (this.version === 2) { this.cipherAlgorithm = sessionKeyAlgorithm; - this.salt = crypto.random.getRandomBytes(32); + this.salt = getRandomBytes(32); this.chunkSizeByte = config.aeadChunkSizeByte; this.encrypted = await runAEAD(this, 'encrypt', key, bytes); } else { - const prefix = await crypto.getPrefixRandom(sessionKeyAlgorithm); + const prefix = await cipherMode.cfb.getPrefixRandom(sessionKeyAlgorithm); const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet const tohash = util.concat([prefix, bytes, mdc]); - const hash = await crypto.hash.sha1(stream.passiveClone(tohash)); + const hash = await computeDigest(enums.hash.sha1, stream.passiveClone(tohash)); const plaintext = util.concat([tohash, hash]); - this.encrypted = await crypto.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); + this.encrypted = await cipherMode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); } return true; } @@ -175,7 +175,7 @@ class SymEncryptedIntegrityProtectedDataPacket { // but we want to ensure that the input key isn't e.g. too short. // The check is done here, instead of on encrypted session key (ESK) decryption, because v6 ESK packets do not store the session key algorithm, // which is instead included in the SEIPDv2 data. - if (key.length !== crypto.getCipherParams(sessionKeyAlgorithm).keySize) { + if (key.length !== getCipherParams(sessionKeyAlgorithm).keySize) { throw new Error('Unexpected session key size'); } @@ -190,15 +190,15 @@ class SymEncryptedIntegrityProtectedDataPacket { } packetbytes = await runAEAD(this, 'decrypt', key, encrypted); } else { - const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); - const decrypted = await crypto.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); + const { blockSize } = getCipherParams(sessionKeyAlgorithm); + const decrypted = await cipherMode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); // there must be a modification detection code packet as the // last packet and everything gets hashed except the hash itself const realHash = stream.slice(stream.passiveClone(decrypted), -20); const tohash = stream.slice(decrypted, 0, -20); const verifyHash = Promise.all([ - stream.readToEnd(await crypto.hash.sha1(stream.passiveClone(tohash))), + stream.readToEnd(await computeDigest(enums.hash.sha1, stream.passiveClone(tohash))), stream.readToEnd(realHash) ]).then(([hash, mdc]) => { if (!util.equalsUint8Array(hash, mdc)) { @@ -237,7 +237,7 @@ export async function runAEAD(packet, fn, key, data) { // we allow `experimentalGCM` for AEADP for backwards compatibility, since v5 keys from OpenPGP.js v5 might be declaring // that preference, as the `gcm` ID had not been standardized at the time. // NB: AEADP are never automatically generate as part of message encryption by OpenPGP.js, the packet must be manually created. - const mode = crypto.getAEADMode(packet.aeadAlgorithm, isAEADP); + const mode = cipherMode.getAEADMode(packet.aeadAlgorithm, isAEADP); const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; const chunkSize = 2 ** (packet.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) @@ -255,7 +255,7 @@ export async function runAEAD(packet, fn, key, data) { let iv; let ivView; if (isSEIPDv2) { - const { keySize } = crypto.getCipherParams(packet.cipherAlgorithm); + const { keySize } = getCipherParams(packet.cipherAlgorithm); const { ivLength } = mode; const info = new Uint8Array(adataBuffer, 0, 5); const derived = await computeHKDF(enums.hash.sha256, key, packet.salt, info, keySize + ivLength); diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 475d6011..7e0f60a4 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -17,7 +17,7 @@ import { newS2KFromConfig, newS2KFromType } from '../type/s2k'; import defaultConfig from '../config'; -import crypto from '../crypto'; +import { cipherMode, generateSessionKey, getCipherParams, getRandomBytes } from '../crypto'; import computeHKDF from '../crypto/hkdf'; import enums from '../enums'; import util from '../util'; @@ -105,7 +105,7 @@ class SymEncryptedSessionKeyPacket { offset += this.s2k.read(bytes.subarray(offset, bytes.length)); if (this.version >= 5) { - const mode = crypto.getAEADMode(this.aeadAlgorithm, true); + const mode = cipherMode.getAEADMode(this.aeadAlgorithm, true); // A starting initialization vector of size specified by the AEAD // algorithm. @@ -163,21 +163,21 @@ class SymEncryptedSessionKeyPacket { this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; - const { blockSize, keySize } = crypto.getCipherParams(algo); + const { blockSize, keySize } = getCipherParams(algo); const key = await this.s2k.produceKey(passphrase, keySize); if (this.version >= 5) { - const mode = crypto.getAEADMode(this.aeadAlgorithm, true); + const mode = cipherMode.getAEADMode(this.aeadAlgorithm, true); const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); const encryptionKey = this.version === 6 ? await computeHKDF(enums.hash.sha256, key, new Uint8Array(), adata, keySize) : key; const modeInstance = await mode(algo, encryptionKey); this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); } else if (this.encrypted !== null) { - const decrypted = await crypto.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); + const decrypted = await cipherMode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); this.sessionKey = decrypted.subarray(1, decrypted.length); - if (this.sessionKey.length !== crypto.getCipherParams(this.sessionKeyAlgorithm).keySize) { + if (this.sessionKey.length !== getCipherParams(this.sessionKeyAlgorithm).keySize) { throw new Error('Unexpected session key size'); } } else { @@ -203,16 +203,16 @@ class SymEncryptedSessionKeyPacket { this.s2k = newS2KFromConfig(config); this.s2k.generateSalt(); - const { blockSize, keySize } = crypto.getCipherParams(algo); + const { blockSize, keySize } = getCipherParams(algo); const key = await this.s2k.produceKey(passphrase, keySize); if (this.sessionKey === null) { - this.sessionKey = crypto.generateSessionKey(this.sessionKeyAlgorithm); + this.sessionKey = generateSessionKey(this.sessionKeyAlgorithm); } if (this.version >= 5) { - const mode = crypto.getAEADMode(this.aeadAlgorithm); - this.iv = crypto.random.getRandomBytes(mode.ivLength); // generate new random IV + const mode = cipherMode.getAEADMode(this.aeadAlgorithm); + this.iv = getRandomBytes(mode.ivLength); // generate new random IV const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); const encryptionKey = this.version === 6 ? await computeHKDF(enums.hash.sha256, key, new Uint8Array(), adata, keySize) : key; const modeInstance = await mode(algo, encryptionKey); @@ -222,7 +222,7 @@ class SymEncryptedSessionKeyPacket { new Uint8Array([this.sessionKeyAlgorithm]), this.sessionKey ]); - this.encrypted = await crypto.mode.cfb.encrypt(algo, key, toEncrypt, new Uint8Array(blockSize), config); + this.encrypted = await cipherMode.cfb.encrypt(algo, key, toEncrypt, new Uint8Array(blockSize), config); } } } diff --git a/src/packet/symmetrically_encrypted_data.js b/src/packet/symmetrically_encrypted_data.js index 41e3cae7..5e3310f4 100644 --- a/src/packet/symmetrically_encrypted_data.js +++ b/src/packet/symmetrically_encrypted_data.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import * as stream from '@openpgp/web-stream-tools'; -import crypto from '../crypto'; +import { cipherMode, getCipherParams } from '../crypto'; import enums from '../enums'; import util from '../util'; import defaultConfig from '../config'; @@ -86,9 +86,9 @@ class SymmetricallyEncryptedDataPacket { throw new Error('Message is not authenticated.'); } - const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); + const { blockSize } = getCipherParams(sessionKeyAlgorithm); const encrypted = await stream.readToEnd(stream.clone(this.encrypted)); - const decrypted = await crypto.mode.cfb.decrypt(sessionKeyAlgorithm, key, + const decrypted = await cipherMode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted.subarray(blockSize + 2), encrypted.subarray(2, blockSize + 2) ); @@ -107,11 +107,11 @@ class SymmetricallyEncryptedDataPacket { */ async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { const data = this.packets.write(); - const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); + const { blockSize } = getCipherParams(sessionKeyAlgorithm); - const prefix = await crypto.getPrefixRandom(sessionKeyAlgorithm); - const FRE = await crypto.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); - const ciphertext = await crypto.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); + const prefix = await cipherMode.cfb.getPrefixRandom(sessionKeyAlgorithm); + const FRE = await cipherMode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); + const ciphertext = await cipherMode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); this.encrypted = util.concat([FRE, ciphertext]); } } diff --git a/src/type/s2k/argon2.js b/src/type/s2k/argon2.js index 84200a6b..be357b50 100644 --- a/src/type/s2k/argon2.js +++ b/src/type/s2k/argon2.js @@ -1,7 +1,7 @@ import defaultConfig from '../../config'; import enums from '../../enums'; import util from '../../util'; -import crypto from '../../crypto'; +import { getRandomBytes } from '../../crypto'; const ARGON2_TYPE = 0x02; // id const ARGON2_VERSION = 0x13; @@ -56,7 +56,7 @@ class Argon2S2K { } generateSalt() { - this.salt = crypto.random.getRandomBytes(ARGON2_SALT_SIZE); + this.salt = getRandomBytes(ARGON2_SALT_SIZE); } /** diff --git a/src/type/s2k/generic.js b/src/type/s2k/generic.js index 76b81f5b..de8b37ce 100644 --- a/src/type/s2k/generic.js +++ b/src/type/s2k/generic.js @@ -28,7 +28,7 @@ */ import defaultConfig from '../../config'; -import crypto from '../../crypto'; +import { getRandomBytes, computeDigest } from '../../crypto'; import enums from '../../enums'; import { UnsupportedError } from '../../packet/packet'; import util from '../../util'; @@ -60,7 +60,7 @@ class GenericS2K { switch (this.type) { case 'salted': case 'iterated': - this.salt = crypto.random.getRandomBytes(8); + this.salt = getRandomBytes(8); } } @@ -188,7 +188,7 @@ class GenericS2K { default: throw new Error('Unknown s2k type.'); } - const result = await crypto.hash.digest(this.algorithm, toHash); + const result = await computeDigest(this.algorithm, toHash); arr.push(result); rlength += result.length; prefixlen++; diff --git a/test/crypto/crypto.js b/test/crypto/crypto.js index c6bd5828..0fd63fbb 100644 --- a/test/crypto/crypto.js +++ b/test/crypto/crypto.js @@ -3,7 +3,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import crypto from '../../src/crypto'; +import * as crypto from '../../src/crypto'; import util from '../../src/util.js'; export default () => describe('API functional testing', function() { @@ -211,20 +211,20 @@ export default () => describe('API functional testing', function() { describe('Sign and verify', function () { it('RSA', async function () { const RSAsignedData = await crypto.signature.sign( - openpgp.enums.publicKey.rsaEncryptSign, openpgp.enums.hash.sha1, RSAPublicParams, RSAPrivateParams, data, await crypto.hash.digest(2, data) + openpgp.enums.publicKey.rsaEncryptSign, openpgp.enums.hash.sha1, RSAPublicParams, RSAPrivateParams, data, await crypto.computeDigest(2, data) ); const success = await crypto.signature.verify( - openpgp.enums.publicKey.rsaEncryptSign, openpgp.enums.hash.sha1, RSAsignedData, RSAPublicParams, data, await crypto.hash.digest(2, data) + openpgp.enums.publicKey.rsaEncryptSign, openpgp.enums.hash.sha1, RSAsignedData, RSAPublicParams, data, await crypto.computeDigest(2, data) ); return expect(success).to.be.true; }); it('DSA', async function () { const DSAsignedData = await crypto.signature.sign( - openpgp.enums.publicKey.dsa, openpgp.enums.hash.sha1, DSAPublicParams, DSAPrivateParams, data, await crypto.hash.digest(2, data) + openpgp.enums.publicKey.dsa, openpgp.enums.hash.sha1, DSAPublicParams, DSAPrivateParams, data, await crypto.computeDigest(2, data) ); const success = await crypto.signature.verify( - openpgp.enums.publicKey.dsa, openpgp.enums.hash.sha1, DSAsignedData, DSAPublicParams, data, await crypto.hash.digest(2, data) + openpgp.enums.publicKey.dsa, openpgp.enums.hash.sha1, DSAsignedData, DSAPublicParams, data, await crypto.computeDigest(2, data) ); return expect(success).to.be.true; @@ -234,7 +234,7 @@ export default () => describe('API functional testing', function() { // key data from https://www.rfc-editor.org/rfc/rfc8032#section-7.4 const seed = util.hexToUint8Array('d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01'); const A = util.hexToUint8Array('df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00'); - const toSign = await crypto.hash.digest(openpgp.enums.hash.sha512, data); + const toSign = await crypto.computeDigest(openpgp.enums.hash.sha512, data); const signedData = await crypto.signature.sign( openpgp.enums.publicKey.ed448, openpgp.enums.hash.sha512, { A }, { seed }, data, toSign ); @@ -257,8 +257,8 @@ export default () => describe('API functional testing', function() { const { blockSize } = crypto.getCipherParams(algo); const symmKey = crypto.generateSessionKey(algo); const IV = new Uint8Array(blockSize); - const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config); - const text = util.uint8ArrayToString(await crypto.mode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize))); + const symmencData = await crypto.cipherMode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config); + const text = util.uint8ArrayToString(await crypto.cipherMode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize))); expect(text).to.equal(plaintext); })); } diff --git a/test/crypto/eax.js b/test/crypto/eax.js index a18688a2..78109ec5 100644 --- a/test/crypto/eax.js +++ b/test/crypto/eax.js @@ -7,7 +7,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import EAX from '../../src/crypto/mode/eax.js'; +import { cipherMode } from '../../src/crypto'; import util from '../../src/util.js'; function testAESEAX() { @@ -95,7 +95,8 @@ function testAESEAX() { const headerBytes = util.hexToUint8Array(vec.header); const ctBytes = util.hexToUint8Array(vec.ct); - const eax = await EAX(cipher, keyBytes); + const eaxMode = cipherMode.getAEADMode(openpgp.enums.aead.eax); + const eax = await eaxMode(cipher, keyBytes); // encryption test let ct = await eax.encrypt(msgBytes, nonceBytes, headerBytes); diff --git a/test/crypto/elliptic.js b/test/crypto/elliptic.js index 80059cea..7f98cd3e 100644 --- a/test/crypto/elliptic.js +++ b/test/crypto/elliptic.js @@ -5,7 +5,7 @@ chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; import * as elliptic_curves from '../../src/crypto/public_key/elliptic'; -import hashMod from '../../src/crypto/hash'; +import { computeDigest } from '../../src/crypto/hash'; import config from '../../src/config'; import util from '../../src/util.js'; @@ -151,7 +151,7 @@ export default () => describe('Elliptic Curve Cryptography @lightweight', functi const curve = new elliptic_curves.CurveWithOID(curveName); const oid = new OID(curve.oid); return ecdsa.verify( - oid, hash, { r: new Uint8Array(r), s: new Uint8Array(s) }, message, new Uint8Array(pub), await hashMod.digest(hash, message) + oid, hash, { r: new Uint8Array(r), s: new Uint8Array(s) }, message, new Uint8Array(pub), await computeDigest(hash, message) ); }; const secp256k1_point = new Uint8Array([ @@ -249,7 +249,7 @@ export default () => describe('Elliptic Curve Cryptography @lightweight', functi 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF ]); - const messageDigest = await hashMod.digest(openpgp.enums.hash.sha512, message); + const messageDigest = await computeDigest(openpgp.enums.hash.sha512, message); await testNativeAndFallback(async () => { const signature = await elliptic_curves.ecdsa.sign(oid, openpgp.enums.hash.sha512, message, keyPublic, keyPrivate, messageDigest); await expect(elliptic_curves.ecdsa.verify(oid, openpgp.enums.hash.sha512, signature, message, keyPublic, messageDigest)).to.eventually.be.true; diff --git a/test/crypto/gcm.js b/test/crypto/gcm.js index cf4e6600..1e0f4530 100644 --- a/test/crypto/gcm.js +++ b/test/crypto/gcm.js @@ -4,10 +4,9 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import crypto from '../../src/crypto'; +import * as crypto from '../../src/crypto'; import util from '../../src/util.js'; - export default () => describe('Symmetric AES-GCM (experimental)', function() { let sinonSandbox; let getWebCryptoStub; @@ -46,18 +45,19 @@ export default () => describe('Symmetric AES-GCM (experimental)', function() { } const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName); const key = crypto.generateSessionKey(algo); - const iv = crypto.random.getRandomBytes(crypto.mode.gcm.ivLength); + const gcmMode = crypto.cipherMode.getAEADMode(openpgp.enums.aead.gcm); + const iv = crypto.getRandomBytes(gcmMode.ivLength); const nativeEncryptSpy = nodeCrypto ? sinonSandbox.spy(nodeCrypto, 'createCipheriv') : sinonSandbox.spy(webCrypto, 'encrypt'); const nativeDecryptSpy = nodeCrypto ? sinonSandbox.spy(nodeCrypto, 'createDecipheriv') : sinonSandbox.spy(webCrypto, 'decrypt'); nativeEncrypt || disableNative(); - let modeInstance = await crypto.mode.gcm(algo, key); + let modeInstance = await gcmMode(algo, key); const ciphertext = await modeInstance.encrypt(util.stringToUint8Array(plaintext), iv); enableNative(); nativeDecrypt || disableNative(); - modeInstance = await crypto.mode.gcm(algo, key); + modeInstance = await gcmMode(algo, key); const decrypted = await modeInstance.decrypt(util.stringToUint8Array(util.uint8ArrayToString(ciphertext)), iv); enableNative(); diff --git a/test/crypto/hash/md5.js b/test/crypto/hash/md5.js index 0825e421..8dff9a76 100644 --- a/test/crypto/hash/md5.js +++ b/test/crypto/hash/md5.js @@ -1,13 +1,14 @@ import { expect } from 'chai'; -import md5 from '../../../src/crypto/hash/md5.js'; import util from '../../../src/util.js'; +import { computeDigest } from '../../../src/crypto/hash'; +import enums from '../../../src/enums.js'; export default () => it('MD5 with test vectors from RFC 1321', async function() { - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('')), 'MD5("") = d41d8cd98f00b204e9800998ecf8427e')).to.equal('d41d8cd98f00b204e9800998ecf8427e'); - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('abc')), 'MD5("a") = 0cc175b9c0f1b6a831c399e269772661')).to.equal('900150983cd24fb0d6963f7d28e17f72'); - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('message digest')), 'MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0')).to.equal('f96b697d7cb7938d525a2f31aaf161d0'); - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('abcdefghijklmnopqrstuvwxyz')), 'MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b')).to.equal('c3fcd3d76192e4007dfb496cca67e13b'); - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')), 'MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f')).to.equal('d174ab98d277d9f5a5611c2c9f419d9f'); - expect(util.uint8ArrayToHex(await md5(util.stringToUint8Array('12345678901234567890123456789012345678901234567890123456789012345678901234567890')), 'MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a')).to.equal('57edf4a22be3c955ac49da2e2107b67a'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('')), 'MD5("") = d41d8cd98f00b204e9800998ecf8427e')).to.equal('d41d8cd98f00b204e9800998ecf8427e'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('abc')), 'MD5("a") = 0cc175b9c0f1b6a831c399e269772661')).to.equal('900150983cd24fb0d6963f7d28e17f72'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('message digest')), 'MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0')).to.equal('f96b697d7cb7938d525a2f31aaf161d0'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('abcdefghijklmnopqrstuvwxyz')), 'MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b')).to.equal('c3fcd3d76192e4007dfb496cca67e13b'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')), 'MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f')).to.equal('d174ab98d277d9f5a5611c2c9f419d9f'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.md5, util.stringToUint8Array('12345678901234567890123456789012345678901234567890123456789012345678901234567890')), 'MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a')).to.equal('57edf4a22be3c955ac49da2e2107b67a'); }); diff --git a/test/crypto/hash/ripemd.js b/test/crypto/hash/ripemd.js index a1116c31..99d47137 100644 --- a/test/crypto/hash/ripemd.js +++ b/test/crypto/hash/ripemd.js @@ -1,11 +1,12 @@ import { expect } from 'chai'; -import hash from '../../../src/crypto/hash'; +import { computeDigest } from '../../../src/crypto/hash'; import util from '../../../src/util.js'; +import enums from '../../../src/enums.js'; export default () => it('RIPE-MD 160 bits with test vectors from https://homes.esat.kuleuven.be/~bosselae/ripemd160.html', async function() { - expect(util.uint8ArrayToHex(await hash.ripemd(util.stringToUint8Array('')), 'RMDstring("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31')).to.equal('9c1185a5c5e9fc54612808977ee8f548b2258d31'); - expect(util.uint8ArrayToHex(await hash.ripemd(util.stringToUint8Array('a')), 'RMDstring("a") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe')).to.equal('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe'); - expect(util.uint8ArrayToHex(await hash.ripemd(util.stringToUint8Array('abc')), 'RMDstring("abc") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc')).to.equal('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc'); - expect(util.uint8ArrayToHex(await hash.ripemd(util.stringToUint8Array('message digest')), 'RMDstring("message digest") = 5d0689ef49d2fae572b881b123a85ffa21595f36')).to.equal('5d0689ef49d2fae572b881b123a85ffa21595f36'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.ripemd, util.stringToUint8Array('')), 'RMDstring("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31')).to.equal('9c1185a5c5e9fc54612808977ee8f548b2258d31'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.ripemd, util.stringToUint8Array('a')), 'RMDstring("a") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe')).to.equal('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.ripemd, util.stringToUint8Array('abc')), 'RMDstring("abc") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc')).to.equal('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.ripemd, util.stringToUint8Array('message digest')), 'RMDstring("message digest") = 5d0689ef49d2fae572b881b123a85ffa21595f36')).to.equal('5d0689ef49d2fae572b881b123a85ffa21595f36'); }); diff --git a/test/crypto/hash/sha.js b/test/crypto/hash/sha.js index 5297aca5..194b767a 100644 --- a/test/crypto/hash/sha.js +++ b/test/crypto/hash/sha.js @@ -1,21 +1,22 @@ import { expect } from 'chai'; -import hash from '../../../src/crypto/hash'; +import { computeDigest } from '../../../src/crypto/hash'; import util from '../../../src/util.js'; +import enums from '../../../src/enums.js'; export default () => it('SHA* with test vectors from NIST FIPS 180-2', async function() { - expect(util.uint8ArrayToHex(await hash.sha1(util.stringToUint8Array('abc')), 'hash.sha1("abc") = a9993e364706816aba3e25717850c26c9cd0d89d')).to.equal('a9993e364706816aba3e25717850c26c9cd0d89d'); - expect(util.uint8ArrayToHex(await hash.sha1(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e441c3bd26ebaae4aa1f95129e5e54670f1')).to.equal('84983e441c3bd26ebaae4aa1f95129e5e54670f1'); - expect(util.uint8ArrayToHex(await hash.sha224(util.stringToUint8Array('abc')), 'hash.sha224("abc") = 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7')).to.equal('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'); - expect(util.uint8ArrayToHex(await hash.sha224(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha224("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525')).to.equal('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525'); - expect(util.uint8ArrayToHex(await hash.sha256(util.stringToUint8Array('abc')), 'hash.sha256("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad')).to.equal('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'); - expect(util.uint8ArrayToHex(await hash.sha256(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1')).to.equal('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1'); - expect(util.uint8ArrayToHex(await hash.sha384(util.stringToUint8Array('abc')), 'hash.sha384("abc") = cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7')).to.equal('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'); - expect(util.uint8ArrayToHex(await hash.sha384(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha384("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b')).to.equal('3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b'); - expect(util.uint8ArrayToHex(await hash.sha512(util.stringToUint8Array('abc')), 'hash.sha512("abc") = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f')).to.equal('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'); - expect(util.uint8ArrayToHex(await hash.sha512(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445')).to.equal('204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445'); - expect(util.uint8ArrayToHex(await hash.sha3_256(util.stringToUint8Array('abc')), 'hash.sha3_256("abc") = 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532')).to.equal('3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532'); - expect(util.uint8ArrayToHex(await hash.sha3_256(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha3_256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376')).to.equal('41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376'); - expect(util.uint8ArrayToHex(await hash.sha3_512(util.stringToUint8Array('abc')), 'hash.sha3_512("abc") = b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0')).to.equal('b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0'); - expect(util.uint8ArrayToHex(await hash.sha3_512(util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha3_512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e')).to.equal('04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha1, util.stringToUint8Array('abc')), 'hash.sha1("abc") = a9993e364706816aba3e25717850c26c9cd0d89d')).to.equal('a9993e364706816aba3e25717850c26c9cd0d89d'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha1, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e441c3bd26ebaae4aa1f95129e5e54670f1')).to.equal('84983e441c3bd26ebaae4aa1f95129e5e54670f1'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha224, util.stringToUint8Array('abc')), 'hash.sha224("abc") = 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7')).to.equal('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha224, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha224("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525')).to.equal('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha256, util.stringToUint8Array('abc')), 'hash.sha256("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad')).to.equal('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha256, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1')).to.equal('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha384, util.stringToUint8Array('abc')), 'hash.sha384("abc") = cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7')).to.equal('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha384, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha384("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b')).to.equal('3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha512, util.stringToUint8Array('abc')), 'hash.sha512("abc") = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f')).to.equal('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha512, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445')).to.equal('204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha3_256, util.stringToUint8Array('abc')), 'hash.sha3_256("abc") = 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532')).to.equal('3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha3_256, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha3_256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376')).to.equal('41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha3_512, util.stringToUint8Array('abc')), 'hash.sha3_512("abc") = b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0')).to.equal('b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0'); + expect(util.uint8ArrayToHex(await computeDigest(enums.hash.sha3_512, util.stringToUint8Array('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')), 'hash.sha3_512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e')).to.equal('04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e'); }); diff --git a/test/crypto/ocb.js b/test/crypto/ocb.js index ef80a96b..5c793c00 100644 --- a/test/crypto/ocb.js +++ b/test/crypto/ocb.js @@ -6,7 +6,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import OCB from '../../src/crypto/mode/ocb.js'; +import { cipherMode } from '../../src/crypto'; import util from '../../src/util.js'; export default () => describe('Symmetric AES-OCB', function() { @@ -122,7 +122,8 @@ export default () => describe('Symmetric AES-OCB', function() { const headerBytes = util.hexToUint8Array(vec.A); const ctBytes = util.hexToUint8Array(vec.C); - const ocb = await OCB(cipher, keyBytes); + const ocbMode = cipherMode.getAEADMode(openpgp.enums.aead.ocb); + const ocb = await ocbMode(cipher, keyBytes); // encryption test let ct = await ocb.encrypt(msgBytes, nonceBytes, headerBytes); @@ -163,7 +164,8 @@ export default () => describe('Symmetric AES-OCB', function() { k[k.length - 1] = taglen; const algo = openpgp.enums.write(openpgp.enums.symmetric, 'aes' + keylen); - const ocb = await OCB(algo, k); + const ocbMode = cipherMode.getAEADMode(openpgp.enums.aead.ocb); + const ocb = await ocbMode(algo, k); const c = []; let n; diff --git a/test/crypto/rsa.js b/test/crypto/rsa.js index 61d00cf7..54a0d90c 100644 --- a/test/crypto/rsa.js +++ b/test/crypto/rsa.js @@ -4,7 +4,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import crypto from '../../src/crypto'; +import * as crypto from '../../src/crypto'; import * as random from '../../src/crypto/random.js'; import util from '../../src/util.js'; @@ -67,7 +67,7 @@ export default () => describe('basic RSA cryptography', function () { const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits); const message = random.getRandomBytes(64); const hashAlgo = openpgp.enums.write(openpgp.enums.hash, 'sha256'); - const hashed = await crypto.hash.digest(hashAlgo, message); + const hashed = await crypto.computeDigest(hashAlgo, message); const { n, e, d, p, q, u } = { ...publicParams, ...privateParams }; const signature = await crypto.publicKey.rsa.sign(hashAlgo, message, n, e, d, p, q, u, hashed); expect(signature).to.exist; @@ -113,7 +113,7 @@ export default () => describe('basic RSA cryptography', function () { const message = random.getRandomBytes(64); const hashName = 'sha256'; const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName); - const hashed = await crypto.hash.digest(hashAlgo, message); + const hashed = await crypto.computeDigest(hashAlgo, message); enableNative(); const signatureNative = await crypto.publicKey.rsa.sign(hashAlgo, message, n, e, d, p, q, u, hashed); disableNative(); @@ -130,7 +130,7 @@ export default () => describe('basic RSA cryptography', function () { const { n, e, d, p, q, u } = { ...publicParams, ...privateParams }; const message = random.getRandomBytes(64); const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName); - const hashed = await crypto.hash.digest(hashAlgo, message); + const hashed = await crypto.computeDigest(hashAlgo, message); enableNative(); await expect(crypto.publicKey.rsa.sign(hashAlgo, message, n, e, d, p, q, u, hashed)).to.be.rejectedWith(/Digest size cannot exceed key modulus size/); disableNative(); @@ -146,7 +146,7 @@ export default () => describe('basic RSA cryptography', function () { const message = random.getRandomBytes(64); const hashName = 'sha256'; const hashAlgo = openpgp.enums.write(openpgp.enums.hash, hashName); - const hashed = await crypto.hash.digest(hashAlgo, message); + const hashed = await crypto.computeDigest(hashAlgo, message); enableNative(); const signatureNative = await crypto.publicKey.rsa.sign(hashAlgo, message, n, e, d, p, q, u, hashed); const verifyNative = await crypto.publicKey.rsa.verify(hashAlgo, message, signatureNative, n, e); diff --git a/test/general/openpgp.js b/test/general/openpgp.js index f5754a6a..3eb42d70 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -7,8 +7,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import crypto from '../../src/crypto'; -import * as random from '../../src/crypto/random.js'; +import * as crypto from '../../src/crypto'; import util from '../../src/util.js'; import keyIDType from '../../src/type/keyid.js'; import { getPreferredCipherSuite } from '../../src/key'; @@ -3706,7 +3705,7 @@ XfA3pqV4mTzF const data = new globalThis.ReadableStream({ pull(controller) { if (i++ < 4) { - const randomBytes = random.getRandomBytes(10); + const randomBytes = crypto.getRandomBytes(10); controller.enqueue(randomBytes); plaintext.push(randomBytes.slice()); } else { diff --git a/test/general/packet.js b/test/general/packet.js index e977ebab..acda172c 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -6,7 +6,7 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new chaiUse(chaiAsPromised); import openpgp from '../initOpenpgp.js'; -import crypto from '../../src/crypto'; +import * as crypto from '../../src/crypto'; import util from '../../src/util.js'; import * as packet from '../../src/packet'; import * as random from '../../src/crypto/random';