mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-11-24 14:35:51 +00:00
Lightweight build: lazy load tweetnacl dependency module (curve25519 JS fallback)
Since all major browsers have shipped support for the curve in WebCrypto, we only load the JS fallback if needed. Also, add native/non-native ECDH test for Curve25519Legacy. (The more modern X25519/X448 algo implementations cannot be tested that way since they include an HKDF step for which we assume native support and do not implement a fallback.)
This commit is contained in:
parent
721b918296
commit
ed5554e114
@ -6,9 +6,8 @@
|
||||
import enums from '../enums';
|
||||
import util from '../util';
|
||||
|
||||
const webCrypto = util.getWebCrypto();
|
||||
|
||||
export default async function computeHKDF(hashAlgo, inputKey, salt, info, outLen) {
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const hash = enums.read(enums.webHash, hashAlgo);
|
||||
if (!hash) throw new Error('Hash algo not supported with HKDF');
|
||||
|
||||
|
||||
@ -30,9 +30,6 @@ import * as pkcs5 from '../../pkcs5';
|
||||
import { getCipherParams } from '../../cipher';
|
||||
import { generateEphemeralEncryptionMaterial as ecdhXGenerateEphemeralEncryptionMaterial, recomputeSharedSecret as ecdhXRecomputeSharedSecret } from './ecdh_x';
|
||||
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
|
||||
/**
|
||||
* Validate ECDH parameters
|
||||
* @param {module:type/oid} oid - Elliptic curve object identifier
|
||||
@ -238,6 +235,7 @@ async function jsPublicEphemeralKey(curve, Q) {
|
||||
* @async
|
||||
*/
|
||||
async function webPrivateEphemeralKey(curve, V, Q, d) {
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const recipient = privateToJWK(curve.payloadSize, curve.web, Q, d);
|
||||
let privateKey = webCrypto.importKey(
|
||||
'jwk',
|
||||
@ -289,6 +287,7 @@ async function webPrivateEphemeralKey(curve, V, Q, d) {
|
||||
* @async
|
||||
*/
|
||||
async function webPublicEphemeralKey(curve, Q) {
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const jwk = rawPublicToJWK(curve.payloadSize, curve.web, Q);
|
||||
let keyPair = webCrypto.generateKey(
|
||||
{
|
||||
@ -338,6 +337,7 @@ async function webPublicEphemeralKey(curve, Q) {
|
||||
* @async
|
||||
*/
|
||||
async function nodePrivateEphemeralKey(curve, V, d) {
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
const recipient = nodeCrypto.createECDH(curve.node);
|
||||
recipient.setPrivateKey(d);
|
||||
const sharedKey = new Uint8Array(recipient.computeSecret(V));
|
||||
@ -354,6 +354,7 @@ async function nodePrivateEphemeralKey(curve, V, d) {
|
||||
* @async
|
||||
*/
|
||||
async function nodePublicEphemeralKey(curve, Q) {
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
const sender = nodeCrypto.createECDH(curve.node);
|
||||
sender.generateKeys();
|
||||
const sharedKey = new Uint8Array(sender.computeSecret(Q));
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
* @module crypto/public_key/elliptic/ecdh
|
||||
*/
|
||||
|
||||
import x25519 from '@openpgp/tweetnacl';
|
||||
import * as aesKW from '../../aes_kw';
|
||||
import { getRandomBytes } from '../../random';
|
||||
|
||||
import enums from '../../../enums';
|
||||
import util from '../../../util';
|
||||
@ -55,9 +53,9 @@ export async function generate(algo) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const { default: x25519 } = await import('@openpgp/tweetnacl');
|
||||
// k stays in little-endian, unlike legacy ECDH over curve25519
|
||||
const k = getRandomBytes(32);
|
||||
const { publicKey: A } = x25519.box.keyPair.fromSecretKey(k);
|
||||
const { secretKey: k, publicKey: A } = x25519.box.keyPair();
|
||||
return { A, k };
|
||||
}
|
||||
|
||||
@ -240,10 +238,10 @@ export async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
||||
const { default: x25519 } = await import('@openpgp/tweetnacl');
|
||||
const { secretKey: ephemeralSecretKey, publicKey: ephemeralPublicKey } = x25519.box.keyPair();
|
||||
const sharedSecret = x25519.scalarMult(ephemeralSecretKey, recipientA);
|
||||
assertNonZeroArray(sharedSecret);
|
||||
const { publicKey: ephemeralPublicKey } = x25519.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
||||
return { ephemeralPublicKey, sharedSecret };
|
||||
}
|
||||
case enums.publicKey.x448: {
|
||||
@ -278,6 +276,7 @@ export async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const { default: x25519 } = await import('@openpgp/tweetnacl');
|
||||
const sharedSecret = x25519.scalarMult(k, ephemeralPublicKey);
|
||||
assertNonZeroArray(sharedSecret);
|
||||
return sharedSecret;
|
||||
|
||||
@ -20,10 +20,9 @@
|
||||
* @module crypto/public_key/elliptic/eddsa
|
||||
*/
|
||||
|
||||
import ed25519 from '@openpgp/tweetnacl';
|
||||
import util from '../../../util';
|
||||
import enums from '../../../enums';
|
||||
import { computeDigest, getHashByteLength } from '../../hash';
|
||||
import { getHashByteLength } from '../../hash';
|
||||
import { getRandomBytes } from '../../random';
|
||||
import { b64ToUint8Array, uint8ArrayToB64 } from '../../../encoding/base64';
|
||||
|
||||
@ -59,7 +58,9 @@ export async function generate(algo) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const { default: ed25519 } = await import('@openpgp/tweetnacl');
|
||||
const seed = getRandomBytes(getPayloadSize(algo));
|
||||
// not using `ed25519.sign.keyPair` since it returns the expanded secret, so using `fromSeed` instead is more straightforward
|
||||
const { publicKey: A } = ed25519.sign.keyPair.fromSeed(seed);
|
||||
return { A, seed };
|
||||
}
|
||||
@ -111,6 +112,7 @@ export async function sign(algo, hashAlgo, message, publicKey, privateKey, hashe
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const { default: ed25519 } = await import('@openpgp/tweetnacl');
|
||||
const secretKey = util.concatUint8Array([privateKey, publicKey]);
|
||||
const signature = ed25519.sign.detached(hashed, secretKey);
|
||||
return { RS: signature };
|
||||
@ -157,6 +159,7 @@ export async function verify(algo, hashAlgo, { RS }, m, publicKey, hashed) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
throw err;
|
||||
}
|
||||
const { default: ed25519 } = await import('@openpgp/tweetnacl');
|
||||
return ed25519.sign.detached.verify(hashed, RS, publicKey);
|
||||
}
|
||||
|
||||
@ -203,7 +206,7 @@ export async function validateParams(algo, A, seed) {
|
||||
if (err.name !== 'NotSupportedError') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { default: ed25519 } = await import('@openpgp/tweetnacl');
|
||||
const { publicKey } = ed25519.sign.keyPair.fromSeed(seed);
|
||||
return util.equalsUint8Array(A, publicKey);
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
* @fileoverview Wrapper of an instance of an Elliptic Curve
|
||||
* @module crypto/public_key/elliptic/curve
|
||||
*/
|
||||
import nacl from '@openpgp/tweetnacl';
|
||||
import enums from '../../../enums';
|
||||
import util from '../../../util';
|
||||
import { uint8ArrayToB64, b64ToUint8Array } from '../../../encoding/base64';
|
||||
|
||||
@ -323,7 +323,10 @@ export default () => describe('ECDH key exchange @lightweight', function () {
|
||||
const disableNative = () => {
|
||||
enableNative();
|
||||
// stubbed functions return undefined
|
||||
getWebCryptoStub = sinonSandbox.stub(util, 'getWebCrypto');
|
||||
getWebCryptoStub = sinonSandbox.stub(util, 'getWebCrypto').returns({
|
||||
generateKey: () => { const e = new Error('getWebCrypto is mocked'); e.name = 'NotSupportedError'; throw e; },
|
||||
importKey: () => { const e = new Error('getWebCrypto is mocked'); e.name = 'NotSupportedError'; throw e; }
|
||||
});
|
||||
getNodeCryptoStub = sinonSandbox.stub(util, 'getNodeCrypto');
|
||||
};
|
||||
const enableNative = () => {
|
||||
@ -331,6 +334,46 @@ export default () => describe('ECDH key exchange @lightweight', function () {
|
||||
getNodeCryptoStub && getNodeCryptoStub.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Test that the result of `encryptFunction` can be decrypted by `decryptFunction`
|
||||
* with and without native crypto support.
|
||||
* @param encryptFunction - `(data: Uint8Array) => encryptFunctionResult`
|
||||
* @param decryptFunction - `(encryptFunctionResult) => <decryption result>`
|
||||
* @param expectNative - whether native usage is expected for the algorithm
|
||||
*/
|
||||
const testRountripWithAndWithoutNative = async (
|
||||
encryptFunction,
|
||||
decryptFunction, // (encryptFunctionResult) => decryption result
|
||||
expectNative
|
||||
) => {
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const data = random.getRandomBytes(16);
|
||||
|
||||
const nativeSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'deriveBits') : sinonSandbox.spy(nodeCrypto, 'createECDH'); // functions used both for encryption and decryption
|
||||
const nativeResult = await encryptFunction(data);
|
||||
const expectedNativeEncryptCallCount = nativeSpy.callCount;
|
||||
disableNative();
|
||||
const nonNativeResult = await encryptFunction(data);
|
||||
expect(nativeSpy.callCount).to.equal(expectedNativeEncryptCallCount); // assert that fallback implementation was called
|
||||
if (expectNative) {
|
||||
expect(nativeSpy.calledOnce).to.be.true;
|
||||
}
|
||||
|
||||
enableNative();
|
||||
expect(await decryptFunction(nativeResult)).to.deep.equal(data);
|
||||
expect(await decryptFunction(nonNativeResult)).to.deep.equal(data);
|
||||
const expectedNativeCallCount = nativeSpy.callCount;
|
||||
disableNative();
|
||||
expect(await decryptFunction(nativeResult)).to.deep.equal(data);
|
||||
expect(await decryptFunction(nonNativeResult)).to.deep.equal(data);
|
||||
expect(nativeSpy.callCount).to.equal(expectedNativeCallCount); // assert that fallback implementation was called
|
||||
if (expectNative) {
|
||||
expect(nativeSpy.callCount).to.equal(3); // one encryption + two decryptions
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
allCurves.forEach(curveName => {
|
||||
it(`${curveName}`, async function () {
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
@ -344,21 +387,27 @@ export default () => describe('ECDH key exchange @lightweight', function () {
|
||||
const curve = new elliptic_curves.CurveWithOID(curveName);
|
||||
const oid = new OID(curve.oid);
|
||||
const kdfParams = new KDFParams({ hash: curve.hash, cipher: curve.cipher });
|
||||
const data = random.getRandomBytes(16);
|
||||
const Q = key_data[curveName].pub;
|
||||
const d = key_data[curveName].priv;
|
||||
const { publicKey: V, wrappedKey: C } = await ecdh.encrypt(oid, kdfParams, data, Q, fingerprint1);
|
||||
|
||||
const nativeDecryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'deriveBits') : sinonSandbox.spy(nodeCrypto, 'createECDH');
|
||||
expect(await ecdh.decrypt(oid, kdfParams, V, C, Q, d, fingerprint1)).to.deep.equal(data);
|
||||
const expectedNativeCallCount = nativeDecryptSpy.callCount;
|
||||
disableNative();
|
||||
expect(await ecdh.decrypt(oid, kdfParams, V, C, Q, d, fingerprint1)).to.deep.equal(data);
|
||||
expect(nativeDecryptSpy.callCount).to.equal(expectedNativeCallCount); // assert that fallback implementation was called
|
||||
if (expectNativeWeb.has(curveName)) {
|
||||
expect(nativeDecryptSpy.calledOnce).to.be.true;
|
||||
}
|
||||
await testRountripWithAndWithoutNative(
|
||||
data => ecdh.encrypt(oid, kdfParams, data, Q, fingerprint1),
|
||||
encryptResult => ecdh.decrypt(oid, kdfParams, encryptResult.publicKey, encryptResult.wrappedKey, Q, d, fingerprint1),
|
||||
expectNativeWeb.has(curveName) // all major browsers implement x25519
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Successful exchange x25519 (legacy)', async function () {
|
||||
const curve = new elliptic_curves.CurveWithOID(openpgp.enums.curve.curve25519Legacy);
|
||||
const oid = new OID(curve.oid);
|
||||
const kdfParams = new KDFParams({ hash: curve.hash, cipher: curve.cipher });
|
||||
|
||||
await testRountripWithAndWithoutNative(
|
||||
data => ecdh.encrypt(oid, kdfParams, data, Q1, fingerprint1),
|
||||
encryptResult => ecdh.decrypt(oid, kdfParams, encryptResult.publicKey, encryptResult.wrappedKey, Q1, d1, fingerprint1),
|
||||
false // all major browsers implement x25519, but webkit linux falls back due to bugs
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,17 +4,59 @@ import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/new
|
||||
chaiUse(chaiAsPromised);
|
||||
|
||||
import openpgp from '../initOpenpgp.js';
|
||||
import * as elliptic_curves from '../../src/crypto/public_key/elliptic';
|
||||
import { computeDigest } from '../../src/crypto/hash';
|
||||
import config from '../../src/config';
|
||||
import * as elliptic_curves from '../../src/crypto/public_key/elliptic/index.js';
|
||||
import { computeDigest } from '../../src/crypto/hash/index.js';
|
||||
import config from '../../src/config/index.js';
|
||||
import util from '../../src/util.js';
|
||||
|
||||
import elliptic_data from './elliptic_data';
|
||||
import elliptic_data from './elliptic_data.js';
|
||||
import OID from '../../src/type/oid.js';
|
||||
import { getRandomBytes } from '../../src/crypto/random.js';
|
||||
|
||||
/**
|
||||
* Test that the result of `signFunction` can be verified by `verifyFunction`
|
||||
* with and without native crypto support.
|
||||
* @param signFunction - `(data: Uint8Array) => signFunctionResult`
|
||||
* @param verifyFunction - `(encryptFunctionResult) => <decryption result>`
|
||||
* @param expectNative - whether native usage is expected for the algorithm
|
||||
*/
|
||||
const testRountripWithAndWithoutNative = async (
|
||||
{ sinonSandbox, enableNative, disableNative },
|
||||
signFunction,
|
||||
verifyFunction, // (signFunctionResult) => verification result
|
||||
expectNative
|
||||
) => {
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
const webCrypto = util.getWebCrypto();
|
||||
const data = getRandomBytes(16);
|
||||
const dataDigest = await computeDigest(openpgp.enums.hash.sha512, data);
|
||||
|
||||
const nativeSpySign = webCrypto ? sinonSandbox.spy(webCrypto, 'sign') : sinonSandbox.spy(nodeCrypto, 'createSign');
|
||||
const nativeResult = await signFunction(data, dataDigest);
|
||||
const expectedNativeSignCallCount = nativeSpySign.callCount;
|
||||
disableNative();
|
||||
const nonNativeResult = await signFunction(data, dataDigest);
|
||||
expect(nativeSpySign.callCount).to.equal(expectedNativeSignCallCount); // assert that fallback implementation was called
|
||||
if (expectNative) {
|
||||
expect(nativeSpySign.calledOnce).to.be.true;
|
||||
}
|
||||
|
||||
const nativeSpyVerify = webCrypto ? sinonSandbox.spy(webCrypto, 'verify') : sinonSandbox.spy(nodeCrypto, 'createVerify');
|
||||
enableNative();
|
||||
expect(await verifyFunction(nativeResult, data, dataDigest)).to.be.true;
|
||||
expect(await verifyFunction(nonNativeResult, data, dataDigest)).to.be.true;
|
||||
const expectedNativeVerifyCallCount = nativeSpyVerify.callCount;
|
||||
disableNative();
|
||||
expect(await verifyFunction(nativeResult, data, dataDigest)).to.be.true;
|
||||
expect(await verifyFunction(nonNativeResult, data, dataDigest)).be.true;
|
||||
expect(nativeSpyVerify.callCount).to.equal(expectedNativeVerifyCallCount); // assert that fallback implementation was called
|
||||
if (expectNative) {
|
||||
expect(nativeSpyVerify.callCount).to.equal(2);
|
||||
}
|
||||
};
|
||||
|
||||
const key_data = elliptic_data.key_data;
|
||||
/* eslint-disable no-invalid-this */
|
||||
export default () => describe('Elliptic Curve Cryptography @lightweight', function () {
|
||||
export default () => describe('ECC signatures', function () {
|
||||
const signature_data = {
|
||||
priv: new Uint8Array([
|
||||
0x14, 0x2B, 0xE2, 0xB7, 0x4D, 0xBD, 0x1B, 0x22,
|
||||
@ -241,19 +283,103 @@ export default () => describe('Elliptic Curve Cryptography @lightweight', functi
|
||||
);
|
||||
});
|
||||
const curves = ['secp256k1' , 'nistP256', 'nistP384', 'nistP521', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
|
||||
curves.forEach(curveName => it(`${curveName} - Sign and verify message`, async function () {
|
||||
curves.forEach(curveName => it(`${curveName} - Sign and verify message with generated key`, async function () {
|
||||
const sinonState = { sinonSandbox, enableNative, disableNative };
|
||||
|
||||
const curve = new elliptic_curves.CurveWithOID(curveName);
|
||||
const oid = new OID(curve.oid);
|
||||
const { Q: keyPublic, secret: keyPrivate } = await elliptic_curves.generate(curveName);
|
||||
const message = new Uint8Array([
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
]);
|
||||
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;
|
||||
const expectNativeWeb = new Set(['nistP256', 'nistP384']); // older versions of safari do not implement nistP521
|
||||
|
||||
const nativeKey = await elliptic_curves.generate(curveName);
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.ecdsa.sign(oid, openpgp.enums.hash.sha512, data, nativeKey.Q, nativeKey.secret, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.ecdsa.verify(oid, openpgp.enums.hash.sha512, signature, data, nativeKey.Q, dataDigest),
|
||||
expectNativeWeb.has(curveName)
|
||||
);
|
||||
|
||||
sinonSandbox.restore(); // reset spies
|
||||
disableNative();
|
||||
const nonNativeKey = await elliptic_curves.generate(curveName);
|
||||
enableNative();
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.ecdsa.sign(oid, openpgp.enums.hash.sha512, data, nonNativeKey.Q, nonNativeKey.secret, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.ecdsa.verify(oid, openpgp.enums.hash.sha512, signature, data, nonNativeKey.Q, dataDigest),
|
||||
expectNativeWeb.has(curveName)
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('EdDSA signature', function () {
|
||||
let sinonSandbox;
|
||||
let getWebCryptoStub;
|
||||
let getNodeCryptoStub;
|
||||
|
||||
beforeEach(function () {
|
||||
sinonSandbox = sinon.createSandbox();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinonSandbox.restore();
|
||||
});
|
||||
|
||||
const disableNative = () => {
|
||||
enableNative();
|
||||
// stubbed functions return undefined
|
||||
getWebCryptoStub = sinonSandbox.stub(util, 'getWebCrypto').returns({
|
||||
generateKey: () => { const e = new Error('getWebCrypto is mocked'); e.name = 'NotSupportedError'; throw e; },
|
||||
importKey: () => { const e = new Error('getWebCrypto is mocked'); e.name = 'NotSupportedError'; throw e; }
|
||||
});
|
||||
getNodeCryptoStub = sinonSandbox.stub(util, 'getNodeCrypto');
|
||||
};
|
||||
const enableNative = () => {
|
||||
getWebCryptoStub && getWebCryptoStub.restore();
|
||||
getNodeCryptoStub && getNodeCryptoStub.restore();
|
||||
};
|
||||
|
||||
it('ed25519Legacy - Sign and verify message with generated key', async function () {
|
||||
const sinonState = { sinonSandbox, enableNative, disableNative };
|
||||
const curve = new elliptic_curves.CurveWithOID(openpgp.enums.curve.ed25519Legacy);
|
||||
const oid = new OID(curve.oid);
|
||||
|
||||
const nativeKey = await elliptic_curves.generate(openpgp.enums.curve.ed25519Legacy);
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.eddsaLegacy.sign(oid, openpgp.enums.hash.sha512, data, nativeKey.Q, nativeKey.secret, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.eddsaLegacy.verify(oid, openpgp.enums.hash.sha512, signature, data, nativeKey.Q, dataDigest)
|
||||
);
|
||||
|
||||
sinonSandbox.restore(); // reset spies
|
||||
disableNative();
|
||||
const nonNativeKey = await elliptic_curves.generate(openpgp.enums.curve.ed25519Legacy);
|
||||
enableNative();
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.eddsaLegacy.sign(oid, openpgp.enums.hash.sha512, data, nonNativeKey.Q, nonNativeKey.secret, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.eddsaLegacy.verify(oid, openpgp.enums.hash.sha512, signature, data, nonNativeKey.Q, dataDigest)
|
||||
);
|
||||
});
|
||||
|
||||
['ed25519', 'ed448'].forEach(algoName => it(`${algoName} - Sign and verify message with native generated key`, async function () {
|
||||
const sinonState = { sinonSandbox, enableNative, disableNative };
|
||||
const algo = openpgp.enums.publicKey[algoName];
|
||||
const nativeKey = await elliptic_curves.eddsa.generate(algo);
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.eddsa.sign(algo, openpgp.enums.hash.sha512, data, nativeKey.A, nativeKey.seed, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.eddsa.verify(algo, openpgp.enums.hash.sha512, signature, data, nativeKey.A, dataDigest)
|
||||
);
|
||||
|
||||
sinonSandbox.restore(); // reset spies
|
||||
disableNative();
|
||||
const nonNativeKey = await elliptic_curves.eddsa.generate(algo);
|
||||
enableNative();
|
||||
await testRountripWithAndWithoutNative(
|
||||
sinonState,
|
||||
(data, dataDigest) => elliptic_curves.eddsa.sign(algo, openpgp.enums.hash.sha512, data, nonNativeKey.A, nonNativeKey.seed, dataDigest),
|
||||
(signature, data, dataDigest) => elliptic_curves.eddsa.verify(algo, openpgp.enums.hash.sha512, signature, data, nonNativeKey.A, dataDigest)
|
||||
);
|
||||
}));
|
||||
});
|
||||
});
|
||||
@ -2,7 +2,7 @@ import testBigInteger from './biginteger';
|
||||
import testCipher from './cipher';
|
||||
import testHash from './hash';
|
||||
import testCrypto from './crypto';
|
||||
import testElliptic from './elliptic';
|
||||
import testElliptic from './ecdsa_eddsa';
|
||||
import testBrainpoolRFC7027 from './brainpool_rfc7027';
|
||||
import testECDH from './ecdh';
|
||||
import testPKCS5 from './pkcs5';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user