Implement preferred AEAD algorithms
This commit is contained in:
parent
93f75f398f
commit
5f97a8c937
|
@ -51,6 +51,13 @@ export default {
|
||||||
* @property {Boolean} aead_protect
|
* @property {Boolean} aead_protect
|
||||||
*/
|
*/
|
||||||
aead_protect: false,
|
aead_protect: false,
|
||||||
|
/**
|
||||||
|
* Default Authenticated Encryption with Additional Data (AEAD) encryption mode
|
||||||
|
* Only has an effect when aead_protect is set to true.
|
||||||
|
* @memberof module:config
|
||||||
|
* @property {Integer} aead_mode Default AEAD mode {@link module:enums.aead}
|
||||||
|
*/
|
||||||
|
aead_mode: enums.aead.eax,
|
||||||
/**
|
/**
|
||||||
* Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode
|
* Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode
|
||||||
* Only has an effect when aead_protect is set to true.
|
* Only has an effect when aead_protect is set to true.
|
||||||
|
|
|
@ -366,7 +366,8 @@ export default {
|
||||||
reason_for_revocation: 29,
|
reason_for_revocation: 29,
|
||||||
features: 30,
|
features: 30,
|
||||||
signature_target: 31,
|
signature_target: 31,
|
||||||
embedded_signature: 32
|
embedded_signature: 32,
|
||||||
|
preferred_aead_algorithms: 34
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Key flags
|
/** Key flags
|
||||||
|
|
37
src/key.js
37
src/key.js
|
@ -1261,6 +1261,11 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
|
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
|
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
|
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
|
||||||
|
if (config.aead_protect === 'draft04') {
|
||||||
|
signaturePacket.preferredAeadAlgorithms = [];
|
||||||
|
signaturePacket.preferredAeadAlgorithms.push(enums.aead.eax);
|
||||||
|
signaturePacket.preferredAeadAlgorithms.push(enums.aead.ocb);
|
||||||
|
}
|
||||||
signaturePacket.preferredHashAlgorithms = [];
|
signaturePacket.preferredHashAlgorithms = [];
|
||||||
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
||||||
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256);
|
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256);
|
||||||
|
@ -1457,3 +1462,35 @@ export async function getPreferredSymAlgo(keys) {
|
||||||
}
|
}
|
||||||
return prefAlgo.algo;
|
return prefAlgo.algo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred aead algorithm for a set of keys
|
||||||
|
* @param {Array<module:key.Key>} keys Set of keys
|
||||||
|
* @returns {Promise<module:enums.aead>} Preferred aead algorithm
|
||||||
|
* @async
|
||||||
|
*/
|
||||||
|
export async function getPreferredAeadAlgo(keys) {
|
||||||
|
const prioMap = {};
|
||||||
|
await Promise.all(keys.map(async function(key) {
|
||||||
|
const primaryUser = await key.getPrimaryUser();
|
||||||
|
if (!primaryUser || !primaryUser.selfCertification.preferredAeadAlgorithms) {
|
||||||
|
return config.aead_mode;
|
||||||
|
}
|
||||||
|
primaryUser.selfCertification.preferredAeadAlgorithms.forEach(function(algo, index) {
|
||||||
|
const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo });
|
||||||
|
entry.prio += 64 >> index;
|
||||||
|
entry.count++;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
let prefAlgo = { prio: 0, algo: config.aead_mode };
|
||||||
|
for (const algo in prioMap) {
|
||||||
|
try {
|
||||||
|
if (enums.read(enums.aead, algo) && // known algorithm
|
||||||
|
prioMap[algo].count === keys.length && // available for all keys
|
||||||
|
prioMap[algo].prio > prefAlgo.prio) {
|
||||||
|
prefAlgo = prioMap[algo];
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
return prefAlgo.algo;
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import enums from './enums';
|
||||||
import util from './util';
|
import util from './util';
|
||||||
import packet from './packet';
|
import packet from './packet';
|
||||||
import { Signature } from './signature';
|
import { Signature } from './signature';
|
||||||
import { getPreferredHashAlgo, getPreferredSymAlgo } from './key';
|
import { getPreferredHashAlgo, getPreferredSymAlgo, getPreferredAeadAlgo } from './key';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,6 +252,7 @@ Message.prototype.getText = function() {
|
||||||
*/
|
*/
|
||||||
Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date()) {
|
Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date()) {
|
||||||
let symAlgo;
|
let symAlgo;
|
||||||
|
let aeadAlgo;
|
||||||
let symEncryptedPacket;
|
let symEncryptedPacket;
|
||||||
|
|
||||||
if (sessionKey) {
|
if (sessionKey) {
|
||||||
|
@ -259,11 +260,14 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
throw new Error('Invalid session key for encryption.');
|
throw new Error('Invalid session key for encryption.');
|
||||||
}
|
}
|
||||||
symAlgo = sessionKey.algorithm;
|
symAlgo = sessionKey.algorithm;
|
||||||
|
aeadAlgo = sessionKey.aeadAlgorithm || config.aead_mode;
|
||||||
sessionKey = sessionKey.data;
|
sessionKey = sessionKey.data;
|
||||||
} else if (keys && keys.length) {
|
} else if (keys && keys.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, await getPreferredSymAlgo(keys));
|
symAlgo = enums.read(enums.symmetric, await getPreferredSymAlgo(keys));
|
||||||
|
aeadAlgo = enums.read(enums.aead, await getPreferredAeadAlgo(keys));
|
||||||
} else if (passwords && passwords.length) {
|
} else if (passwords && passwords.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
||||||
|
aeadAlgo = enums.read(enums.aead, config.aead_mode);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No keys, passwords, or session key provided.');
|
throw new Error('No keys, passwords, or session key provided.');
|
||||||
}
|
}
|
||||||
|
@ -272,10 +276,11 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
sessionKey = await crypto.generateSessionKey(symAlgo);
|
sessionKey = await crypto.generateSessionKey(symAlgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, date);
|
const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date);
|
||||||
|
|
||||||
if (config.aead_protect) {
|
if (config.aead_protect) {
|
||||||
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
||||||
|
symEncryptedPacket.aeadAlgorithm = aeadAlgo;
|
||||||
} else if (config.integrity_protect) {
|
} else if (config.integrity_protect) {
|
||||||
symEncryptedPacket = new packet.SymEncryptedIntegrityProtected();
|
symEncryptedPacket = new packet.SymEncryptedIntegrityProtected();
|
||||||
} else {
|
} else {
|
||||||
|
@ -291,7 +296,8 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
message: msg,
|
message: msg,
|
||||||
sessionKey: {
|
sessionKey: {
|
||||||
data: sessionKey,
|
data: sessionKey,
|
||||||
algorithm: symAlgo
|
algorithm: symAlgo,
|
||||||
|
aeadAlgorithm: aeadAlgo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -300,6 +306,7 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
* Encrypt a session key either with public keys, passwords, or both at once.
|
* Encrypt a session key either with public keys, passwords, or both at once.
|
||||||
* @param {Uint8Array} sessionKey session key for encryption
|
* @param {Uint8Array} sessionKey session key for encryption
|
||||||
* @param {String} symAlgo session key algorithm
|
* @param {String} symAlgo session key algorithm
|
||||||
|
* @param {String} aeadAlgo (optional) aead algorithm, e.g. 'eax' or 'ocb'
|
||||||
* @param {Array<Key>} publicKeys (optional) public key(s) for message encryption
|
* @param {Array<Key>} publicKeys (optional) public key(s) for message encryption
|
||||||
* @param {Array<String>} passwords (optional) for message encryption
|
* @param {Array<String>} passwords (optional) for message encryption
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
@ -307,7 +314,7 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
* @returns {Promise<Message>} new message with encrypted content
|
* @returns {Promise<Message>} new message with encrypted content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, date=new Date()) {
|
export async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard=false, date=new Date()) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
if (publicKeys) {
|
if (publicKeys) {
|
||||||
|
@ -340,10 +347,13 @@ export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwor
|
||||||
|
|
||||||
const sum = (accumulator, currentValue) => accumulator + currentValue;
|
const sum = (accumulator, currentValue) => accumulator + currentValue;
|
||||||
|
|
||||||
const encryptPassword = async function(sessionKey, symAlgo, password) {
|
const encryptPassword = async function(sessionKey, symAlgo, aeadAlgo, password) {
|
||||||
const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey();
|
const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey();
|
||||||
symEncryptedSessionKeyPacket.sessionKey = sessionKey;
|
symEncryptedSessionKeyPacket.sessionKey = sessionKey;
|
||||||
symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo;
|
symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo;
|
||||||
|
if (aeadAlgo) {
|
||||||
|
symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgo;
|
||||||
|
}
|
||||||
await symEncryptedSessionKeyPacket.encrypt(password);
|
await symEncryptedSessionKeyPacket.encrypt(password);
|
||||||
|
|
||||||
if (config.password_collision_check) {
|
if (config.password_collision_check) {
|
||||||
|
@ -357,7 +367,7 @@ export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwor
|
||||||
return symEncryptedSessionKeyPacket;
|
return symEncryptedSessionKeyPacket;
|
||||||
};
|
};
|
||||||
|
|
||||||
const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, pwd)));
|
const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, aeadAlgo, pwd)));
|
||||||
packetlist.concat(results);
|
packetlist.concat(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -395,6 +395,7 @@ export function verify({ message, publicKeys, signature=null, date=new Date() })
|
||||||
* or passwords must be specified.
|
* or passwords must be specified.
|
||||||
* @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128)
|
* @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128)
|
||||||
* @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256'
|
* @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256'
|
||||||
|
* @param {String} aeadAlgorithm (optional) aead algorithm, e.g. 'eax' or 'ocb'
|
||||||
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, used to encrypt the key
|
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, used to encrypt the key
|
||||||
* @param {String|Array<String>} passwords (optional) passwords for the message
|
* @param {String|Array<String>} passwords (optional) passwords for the message
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
@ -402,16 +403,16 @@ export function verify({ message, publicKeys, signature=null, date=new Date() })
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wildcard=false }) {
|
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard=false }) {
|
||||||
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords);
|
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords, wildcard });
|
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
|
|
||||||
return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords, wildcard) };
|
return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard) };
|
||||||
|
|
||||||
}).catch(onError.bind(null, 'Error encrypting session key'));
|
}).catch(onError.bind(null, 'Error encrypting session key'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ function Signature(date=new Date()) {
|
||||||
this.signatureTargetHashAlgorithm = null;
|
this.signatureTargetHashAlgorithm = null;
|
||||||
this.signatureTargetHash = null;
|
this.signatureTargetHash = null;
|
||||||
this.embeddedSignature = null;
|
this.embeddedSignature = null;
|
||||||
|
this.preferredAeadAlgorithms = null;
|
||||||
|
|
||||||
this.verified = null;
|
this.verified = null;
|
||||||
this.revoked = null;
|
this.revoked = null;
|
||||||
|
@ -355,6 +356,10 @@ Signature.prototype.write_all_sub_packets = function () {
|
||||||
if (this.embeddedSignature !== null) {
|
if (this.embeddedSignature !== null) {
|
||||||
arr.push(write_sub_packet(sub.embedded_signature, this.embeddedSignature.write()));
|
arr.push(write_sub_packet(sub.embedded_signature, this.embeddedSignature.write()));
|
||||||
}
|
}
|
||||||
|
if (this.preferredAeadAlgorithms !== null) {
|
||||||
|
bytes = util.str_to_Uint8Array(util.Uint8Array_to_str(this.preferredAeadAlgorithms));
|
||||||
|
arr.push(write_sub_packet(sub.preferred_aead_algorithms, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
const result = util.concatUint8Array(arr);
|
const result = util.concatUint8Array(arr);
|
||||||
const length = util.writeNumber(result.length, 2);
|
const length = util.writeNumber(result.length, 2);
|
||||||
|
@ -531,6 +536,10 @@ Signature.prototype.read_sub_packet = function (bytes) {
|
||||||
this.embeddedSignature = new Signature();
|
this.embeddedSignature = new Signature();
|
||||||
this.embeddedSignature.read(bytes.subarray(mypos, bytes.length));
|
this.embeddedSignature.read(bytes.subarray(mypos, bytes.length));
|
||||||
break;
|
break;
|
||||||
|
case 34:
|
||||||
|
// Preferred AEAD Algorithms
|
||||||
|
read_array.call(this, 'preferredAeadAlgorithms', bytes.subarray(mypos, bytes.length));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
util.print_debug("Unknown signature subpacket type " + type + " @:" + mypos);
|
util.print_debug("Unknown signature subpacket type " + type + " @:" + mypos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ function SymEncryptedAEADProtected() {
|
||||||
this.tag = enums.packet.symEncryptedAEADProtected;
|
this.tag = enums.packet.symEncryptedAEADProtected;
|
||||||
this.version = VERSION;
|
this.version = VERSION;
|
||||||
this.cipherAlgo = null;
|
this.cipherAlgo = null;
|
||||||
|
this.aeadAlgorithm = 'eax';
|
||||||
this.aeadAlgo = null;
|
this.aeadAlgo = null;
|
||||||
this.chunkSizeByte = null;
|
this.chunkSizeByte = null;
|
||||||
this.iv = null;
|
this.iv = null;
|
||||||
|
@ -131,7 +132,7 @@ SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorith
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) {
|
SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) {
|
||||||
this.aeadAlgo = config.aead_protect === 'draft04' ? enums.aead.eax : enums.aead.gcm;
|
this.aeadAlgo = config.aead_protect === 'draft04' ? enums.write(enums.aead, this.aeadAlgorithm) : enums.aead.gcm;
|
||||||
const mode = crypto[enums.read(enums.aead, this.aeadAlgo)];
|
const mode = crypto[enums.read(enums.aead, this.aeadAlgo)];
|
||||||
this.iv = await crypto.random.getRandomBytes(mode.ivLength); // generate new random IV
|
this.iv = await crypto.random.getRandomBytes(mode.ivLength); // generate new random IV
|
||||||
let data = this.packets.write();
|
let data = this.packets.write();
|
||||||
|
|
|
@ -53,7 +53,7 @@ function SymEncryptedSessionKey() {
|
||||||
this.sessionKey = null;
|
this.sessionKey = null;
|
||||||
this.sessionKeyEncryptionAlgorithm = null;
|
this.sessionKeyEncryptionAlgorithm = null;
|
||||||
this.sessionKeyAlgorithm = 'aes256';
|
this.sessionKeyAlgorithm = 'aes256';
|
||||||
this.aeadAlgorithm = 'eax';
|
this.aeadAlgorithm = enums.read(enums.aead, config.aead_mode);
|
||||||
this.encrypted = null;
|
this.encrypted = null;
|
||||||
this.s2k = null;
|
this.s2k = null;
|
||||||
this.iv = null;
|
this.iv = null;
|
||||||
|
|
|
@ -1192,6 +1192,24 @@ p92yZgB3r2+f6/GIe2+7
|
||||||
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
|
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('getPreferredAeadAlgo() - one key - OCB', async function() {
|
||||||
|
const key1 = openpgp.key.readArmored(twoKeys).keys[0];
|
||||||
|
const primaryUser = await key1.getPrimaryUser();
|
||||||
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
|
const prefAlgo = await openpgp.key.getPreferredAeadAlgo([key1]);
|
||||||
|
expect(prefAlgo).to.equal(openpgp.enums.aead.ocb);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPreferredAeadAlgo() - two key - one without pref', async function() {
|
||||||
|
const keys = openpgp.key.readArmored(twoKeys).keys;
|
||||||
|
const key1 = keys[0];
|
||||||
|
const key2 = keys[1];
|
||||||
|
const primaryUser = await key1.getPrimaryUser();
|
||||||
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
|
const prefAlgo = await openpgp.key.getPreferredAeadAlgo([key1, key2]);
|
||||||
|
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
||||||
|
});
|
||||||
|
|
||||||
it('Preferences of generated key', function() {
|
it('Preferences of generated key', function() {
|
||||||
const testPref = function(key) {
|
const testPref = function(key) {
|
||||||
// key flags
|
// key flags
|
||||||
|
@ -1202,6 +1220,10 @@ p92yZgB3r2+f6/GIe2+7
|
||||||
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
|
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
|
||||||
const sym = openpgp.enums.symmetric;
|
const sym = openpgp.enums.symmetric;
|
||||||
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]);
|
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]);
|
||||||
|
if (openpgp.config.aead_protect === 'draft04') {
|
||||||
|
const aead = openpgp.enums.aead;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]);
|
||||||
|
}
|
||||||
const hash = openpgp.enums.hash;
|
const hash = openpgp.enums.hash;
|
||||||
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]);
|
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]);
|
||||||
const compr = openpgp.enums.compression;
|
const compr = openpgp.enums.compression;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user