Remove duplicate tests
Many tests would run for every encryption mode, or for both V4 and V5 keys, without there being any difference between the different test runs. `grunt coverage` before and after this commit reports almost identical statistics, providing some confidence that no code coverage was lost.
This commit is contained in:
parent
225f586970
commit
67b067b1da
|
@ -6,40 +6,6 @@ chai.use(require('chai-as-promised'));
|
||||||
|
|
||||||
const { expect } = chai;
|
const { expect } = chai;
|
||||||
|
|
||||||
describe('Key', function() {
|
|
||||||
let rsaGenStub;
|
|
||||||
let rsaGenValue = openpgp.crypto.publicKey.rsa.generate(openpgp.util.getWebCryptoAll() ? 2048 : 512, "10001");
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate');
|
|
||||||
rsaGenStub.returns(rsaGenValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
rsaGenStub.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('V4', tests);
|
|
||||||
|
|
||||||
describe('V5', function() {
|
|
||||||
let aead_protectVal;
|
|
||||||
let aead_protect_versionVal;
|
|
||||||
beforeEach(function() {
|
|
||||||
aead_protectVal = openpgp.config.aead_protect;
|
|
||||||
aead_protect_versionVal = openpgp.config.aead_protect_version;
|
|
||||||
openpgp.config.aead_protect = true;
|
|
||||||
openpgp.config.aead_protect_version = 4;
|
|
||||||
});
|
|
||||||
afterEach(function() {
|
|
||||||
openpgp.config.aead_protect = aead_protectVal;
|
|
||||||
openpgp.config.aead_protect_version = aead_protect_versionVal;
|
|
||||||
});
|
|
||||||
|
|
||||||
tests();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function tests() {
|
|
||||||
const priv_key_arm2 =
|
const priv_key_arm2 =
|
||||||
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
'Version: GnuPG v2.0.19 (GNU/Linux)',
|
'Version: GnuPG v2.0.19 (GNU/Linux)',
|
||||||
|
@ -821,15 +787,6 @@ zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa
|
||||||
'-----END PGP PRIVATE KEY BLOCK-----'
|
'-----END PGP PRIVATE KEY BLOCK-----'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
it('Parsing armored text with RSA key and ECC subkey', async function() {
|
|
||||||
openpgp.config.tolerant = true;
|
|
||||||
const pubKeys = await openpgp.key.readArmored(rsa_ecc_pub);
|
|
||||||
expect(pubKeys).to.exist;
|
|
||||||
expect(pubKeys.err).to.not.exist;
|
|
||||||
expect(pubKeys.keys).to.have.length(1);
|
|
||||||
expect(pubKeys.keys[0].getKeyId().toHex()).to.equal('b8e4105cc9dedc77');
|
|
||||||
});
|
|
||||||
|
|
||||||
const multi_uid_key =
|
const multi_uid_key =
|
||||||
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||||
'Version: GnuPG v1',
|
'Version: GnuPG v1',
|
||||||
|
@ -1264,6 +1221,462 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
|
||||||
=C0fJ
|
=C0fJ
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
function versionSpecificTests() {
|
||||||
|
it('Preferences of generated key', function() {
|
||||||
|
const testPref = function(key) {
|
||||||
|
// key flags
|
||||||
|
const keyFlags = openpgp.enums.keyFlags;
|
||||||
|
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys);
|
||||||
|
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data);
|
||||||
|
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication);
|
||||||
|
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
|
||||||
|
const sym = openpgp.enums.symmetric;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]);
|
||||||
|
if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) {
|
||||||
|
const aead = openpgp.enums.aead;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]);
|
||||||
|
}
|
||||||
|
const hash = openpgp.enums.hash;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]);
|
||||||
|
const compr = openpgp.enums.compression;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
|
||||||
|
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]);
|
||||||
|
};
|
||||||
|
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(async function(key) {
|
||||||
|
testPref(key.key);
|
||||||
|
testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generated key is not unlocked by default', function() {
|
||||||
|
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
let key;
|
||||||
|
return openpgp.generateKey(opt).then(function(newKey) {
|
||||||
|
key = newKey.key;
|
||||||
|
return openpgp.message.fromText('hello').encrypt([key]);
|
||||||
|
}).then(function(msg) {
|
||||||
|
return msg.message.decrypt([key]);
|
||||||
|
}).catch(function(err) {
|
||||||
|
expect(err.message).to.equal('Private key is not decrypted.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - single userid', function() {
|
||||||
|
const userId = { name: 'test', email: 'a@b.com', comment: 'test comment' };
|
||||||
|
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal('test <a@b.com> (test comment)');
|
||||||
|
expect(key.users[0].userId.name).to.equal(userId.name);
|
||||||
|
expect(key.users[0].userId.email).to.equal(userId.email);
|
||||||
|
expect(key.users[0].userId.comment).to.equal(userId.comment);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - setting date to the past', function() {
|
||||||
|
const past = new Date(0);
|
||||||
|
const opt = {
|
||||||
|
numBits: 512,
|
||||||
|
userIds: { name: 'Test User', email: 'text@example.com' },
|
||||||
|
passphrase: 'secret',
|
||||||
|
date: past
|
||||||
|
};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
|
||||||
|
return openpgp.generateKey(opt).then(function(newKey) {
|
||||||
|
expect(newKey.key).to.exist;
|
||||||
|
expect(+newKey.key.getCreationTime()).to.equal(+past);
|
||||||
|
expect(+newKey.key.subKeys[0].getCreationTime()).to.equal(+past);
|
||||||
|
expect(+newKey.key.subKeys[0].bindingSignatures[0].created).to.equal(+past);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Generate key - multi userid', function() {
|
||||||
|
const userId1 = 'test <a@b.com>';
|
||||||
|
const userId2 = 'test <b@c.com>';
|
||||||
|
const opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(2);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId1);
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.users[1].userId.userid).to.equal(userId2);
|
||||||
|
expect(key.users[1].selfCertifications[0].isPrimaryUserID).to.be.null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - two subkeys with default values', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]};
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.subKeys).to.have.lengthOf(2);
|
||||||
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - one signing subkey', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.subKeys).to.have.lengthOf(2);
|
||||||
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('eddsa');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - override main key options for subkey', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {numBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign');
|
||||||
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Encrypt key with new passphrase', async function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
const key = (await openpgp.generateKey(opt)).key;
|
||||||
|
const armor1 = key.armor();
|
||||||
|
const armor2 = key.armor();
|
||||||
|
expect(armor1).to.equal(armor2);
|
||||||
|
expect(await key.decrypt('passphrase')).to.be.true;
|
||||||
|
expect(key.isDecrypted()).to.be.true;
|
||||||
|
await key.encrypt('new_passphrase');
|
||||||
|
expect(key.isDecrypted()).to.be.false;
|
||||||
|
await expect(key.decrypt('passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase');
|
||||||
|
expect(key.isDecrypted()).to.be.false;
|
||||||
|
expect(await key.decrypt('new_passphrase')).to.be.true;
|
||||||
|
expect(key.isDecrypted()).to.be.true;
|
||||||
|
const armor3 = key.armor();
|
||||||
|
expect(armor3).to.not.equal(armor1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - ensure keyExpirationTime works', function() {
|
||||||
|
const expect_delta = 365 * 24 * 60 * 60;
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(async function(key) {
|
||||||
|
key = key.key;
|
||||||
|
|
||||||
|
const expiration = await key.getExpirationTime();
|
||||||
|
expect(expiration).to.exist;
|
||||||
|
|
||||||
|
const actual_delta = (new Date(expiration) - new Date()) / 1000;
|
||||||
|
expect(Math.abs(actual_delta - expect_delta)).to.be.below(60);
|
||||||
|
|
||||||
|
const subKeyExpiration = await key.subKeys[0].getExpirationTime();
|
||||||
|
expect(subKeyExpiration).to.exist;
|
||||||
|
|
||||||
|
const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000;
|
||||||
|
expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign and verify key - primary user', async function() {
|
||||||
|
let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0];
|
||||||
|
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
||||||
|
await privateKey.decrypt('hello world');
|
||||||
|
publicKey = await publicKey.signPrimaryUser([privateKey]);
|
||||||
|
const signatures = await publicKey.verifyPrimaryUser([privateKey]);
|
||||||
|
const publicSigningKey = await publicKey.getSigningKey();
|
||||||
|
const privateSigningKey = await privateKey.getSigningKey();
|
||||||
|
expect(signatures.length).to.equal(2);
|
||||||
|
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[0].valid).to.be.null;
|
||||||
|
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[1].valid).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign key and verify with wrong key - primary user', async function() {
|
||||||
|
let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0];
|
||||||
|
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
||||||
|
const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0];
|
||||||
|
await privateKey.decrypt('hello world');
|
||||||
|
publicKey = await publicKey.signPrimaryUser([privateKey]);
|
||||||
|
const signatures = await publicKey.verifyPrimaryUser([wrongKey]);
|
||||||
|
const publicSigningKey = await publicKey.getSigningKey();
|
||||||
|
const privateSigningKey = await privateKey.getSigningKey();
|
||||||
|
expect(signatures.length).to.equal(2);
|
||||||
|
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[0].valid).to.be.null;
|
||||||
|
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[1].valid).to.be.null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign and verify key - all users', async function() {
|
||||||
|
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
||||||
|
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
||||||
|
await privateKey.decrypt('hello world');
|
||||||
|
publicKey = await publicKey.signAllUsers([privateKey]);
|
||||||
|
const signatures = await publicKey.verifyAllUsers([privateKey]);
|
||||||
|
const publicSigningKey = await publicKey.getSigningKey();
|
||||||
|
const privateSigningKey = await privateKey.getSigningKey();
|
||||||
|
expect(signatures.length).to.equal(4);
|
||||||
|
expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
|
||||||
|
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[0].valid).to.be.null;
|
||||||
|
expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
|
||||||
|
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[1].valid).to.be.true;
|
||||||
|
expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
|
||||||
|
expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[2].valid).to.be.null;
|
||||||
|
expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
|
||||||
|
expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[3].valid).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign key and verify with wrong key - all users', async function() {
|
||||||
|
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
||||||
|
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
||||||
|
const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0];
|
||||||
|
await privateKey.decrypt('hello world');
|
||||||
|
publicKey = await publicKey.signAllUsers([privateKey]);
|
||||||
|
const signatures = await publicKey.verifyAllUsers([wrongKey]);
|
||||||
|
const publicSigningKey = await publicKey.getSigningKey();
|
||||||
|
const privateSigningKey = await privateKey.getSigningKey();
|
||||||
|
expect(signatures.length).to.equal(4);
|
||||||
|
expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
|
||||||
|
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[0].valid).to.be.null;
|
||||||
|
expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
|
||||||
|
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[1].valid).to.be.null;
|
||||||
|
expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
|
||||||
|
expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[2].valid).to.be.null;
|
||||||
|
expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
|
||||||
|
expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
||||||
|
expect(signatures[3].valid).to.be.null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reformat key without passphrase', function() {
|
||||||
|
const userId1 = 'test1 <a@b.com>';
|
||||||
|
const userId2 = 'test2 <b@a.com>';
|
||||||
|
const opt = {numBits: 512, userIds: userId1};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId1);
|
||||||
|
expect(key.isDecrypted()).to.be.true;
|
||||||
|
opt.privateKey = key;
|
||||||
|
opt.userIds = userId2;
|
||||||
|
return openpgp.reformatKey(opt).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users.length).to.equal(1);
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId2);
|
||||||
|
expect(newKey.isDecrypted()).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reformat key with no subkey with passphrase', async function() {
|
||||||
|
const userId = 'test1 <a@b.com>';
|
||||||
|
const keys = (await openpgp.key.readArmored(key_without_subkey)).keys;
|
||||||
|
const opt = {privateKey: keys[0], userIds: [userId], passphrase: "test"};
|
||||||
|
return openpgp.reformatKey(opt).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users.length).to.equal(1);
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(newKey.isDecrypted()).to.be.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reformat key with two subkeys with passphrase', function() {
|
||||||
|
const userId1 = 'test <a@b.com>';
|
||||||
|
const userId2 = 'test <b@c.com>';
|
||||||
|
const now = openpgp.util.normalizeDate(new Date());
|
||||||
|
const before = openpgp.util.normalizeDate(new Date(0));
|
||||||
|
const opt1 = {curve: 'curve25519', userIds: [userId1], date: now};
|
||||||
|
return openpgp.generateKey(opt1).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId1);
|
||||||
|
expect(+newKey.getCreationTime()).to.equal(+now);
|
||||||
|
expect(+newKey.subKeys[0].getCreationTime()).to.equal(+now);
|
||||||
|
expect(+newKey.subKeys[0].bindingSignatures[0].created).to.equal(+now);
|
||||||
|
const opt2 = {privateKey: newKey, userIds: [userId2], date: before};
|
||||||
|
return openpgp.reformatKey(opt2).then(function(refKey) {
|
||||||
|
refKey = refKey.key;
|
||||||
|
expect(refKey.users.length).to.equal(1);
|
||||||
|
expect(refKey.users[0].userId.userid).to.equal(userId2);
|
||||||
|
expect(+refKey.subKeys[0].bindingSignatures[0].created).to.equal(+before);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reformat key with no subkey without passphrase', async function() {
|
||||||
|
const userId = 'test1 <a@b.com>';
|
||||||
|
const keys = (await openpgp.key.readArmored(key_without_subkey)).keys;
|
||||||
|
const opt = {privateKey: keys[0], userIds: [userId]};
|
||||||
|
return openpgp.reformatKey(opt).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users.length).to.equal(1);
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(newKey.isDecrypted()).to.be.true;
|
||||||
|
return openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: newKey, armor: true}).then(async function(signed) {
|
||||||
|
return openpgp.verify(
|
||||||
|
{message: await openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()}
|
||||||
|
).then(async function(verified) {
|
||||||
|
expect(verified.signatures[0].valid).to.be.true;
|
||||||
|
const newSigningKey = await newKey.getSigningKey();
|
||||||
|
expect(verified.signatures[0].keyid.toHex()).to.equal(newSigningKey.getKeyId().toHex());
|
||||||
|
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reformat and encrypt key', function() {
|
||||||
|
const userId1 = 'test1 <a@b.com>';
|
||||||
|
const userId2 = 'test2 <b@c.com>';
|
||||||
|
const userId3 = 'test3 <c@d.com>';
|
||||||
|
const opt = {numBits: 512, userIds: userId1};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
opt.privateKey = key;
|
||||||
|
opt.userIds = [userId2, userId3];
|
||||||
|
opt.passphrase = '123';
|
||||||
|
return openpgp.reformatKey(opt).then(async function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users.length).to.equal(2);
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId2);
|
||||||
|
expect(newKey.isDecrypted()).to.be.false;
|
||||||
|
await newKey.decrypt('123');
|
||||||
|
expect(newKey.isDecrypted()).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign and encrypt with reformatted key', function() {
|
||||||
|
const userId1 = 'test1 <a@b.com>';
|
||||||
|
const userId2 = 'test2 <b@a.com>';
|
||||||
|
const opt = {numBits: 512, userIds: userId1};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(key) {
|
||||||
|
key = key.key;
|
||||||
|
opt.privateKey = key;
|
||||||
|
opt.userIds = userId2;
|
||||||
|
return openpgp.reformatKey(opt).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
return openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(async function(encrypted) {
|
||||||
|
return openpgp.decrypt({message: await openpgp.message.readArmored(encrypted.data), privateKeys: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) {
|
||||||
|
expect(decrypted.data).to.equal('hello');
|
||||||
|
expect(decrypted.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reject with user-friendly error when reformatting encrypted key', function() {
|
||||||
|
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(original) {
|
||||||
|
return openpgp.reformatKey({privateKey: original.key, userIds: 'test2 <b@a.com>', passphrase: '1234'}).then(function() {
|
||||||
|
throw new Error('reformatKey should result in error when key not decrypted');
|
||||||
|
}).catch(function(error) {
|
||||||
|
expect(error.message).to.equal('Error reformatting keypair: Key not decrypted');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Revoke generated key with revocation certificate', function() {
|
||||||
|
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(function(original) {
|
||||||
|
return openpgp.revokeKey({key: original.key.toPublic(), revocationCertificate: original.revocationCertificate}).then(function(revKey) {
|
||||||
|
revKey = revKey.publicKey;
|
||||||
|
expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason);
|
||||||
|
expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('');
|
||||||
|
return revKey.verifyPrimaryKey().then(function(status) {
|
||||||
|
expect(status).to.equal(openpgp.enums.keyStatus.revoked);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Revoke generated key with private key', function() {
|
||||||
|
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
return openpgp.generateKey(opt).then(async function(original) {
|
||||||
|
await original.key.decrypt('1234');
|
||||||
|
return openpgp.revokeKey({key: original.key, reasonForRevocation: {string: 'Testing key revocation'}}).then(function(revKey) {
|
||||||
|
revKey = revKey.publicKey;
|
||||||
|
expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason);
|
||||||
|
expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('Testing key revocation');
|
||||||
|
return revKey.verifyPrimaryKey().then(function(status) {
|
||||||
|
expect(status).to.equal(openpgp.enums.keyStatus.revoked);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Key', function() {
|
||||||
|
let rsaGenStub;
|
||||||
|
let rsaGenValue = openpgp.crypto.publicKey.rsa.generate(openpgp.util.getWebCryptoAll() ? 2048 : 512, "10001");
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate');
|
||||||
|
rsaGenStub.returns(rsaGenValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
rsaGenStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('V4', versionSpecificTests);
|
||||||
|
|
||||||
|
describe('V5', function() {
|
||||||
|
let aead_protectVal;
|
||||||
|
let aead_protect_versionVal;
|
||||||
|
beforeEach(function() {
|
||||||
|
aead_protectVal = openpgp.config.aead_protect;
|
||||||
|
aead_protect_versionVal = openpgp.config.aead_protect_version;
|
||||||
|
openpgp.config.aead_protect = true;
|
||||||
|
openpgp.config.aead_protect_version = 4;
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
openpgp.config.aead_protect = aead_protectVal;
|
||||||
|
openpgp.config.aead_protect_version = aead_protect_versionVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
versionSpecificTests();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Parsing armored text with RSA key and ECC subkey', async function() {
|
||||||
|
openpgp.config.tolerant = true;
|
||||||
|
const pubKeys = await openpgp.key.readArmored(rsa_ecc_pub);
|
||||||
|
expect(pubKeys).to.exist;
|
||||||
|
expect(pubKeys.err).to.not.exist;
|
||||||
|
expect(pubKeys.keys).to.have.length(1);
|
||||||
|
expect(pubKeys.keys[0].getKeyId().toHex()).to.equal('b8e4105cc9dedc77');
|
||||||
|
});
|
||||||
|
|
||||||
it('Parsing armored text with two keys', async function() {
|
it('Parsing armored text with two keys', async function() {
|
||||||
const pubKeys = await openpgp.key.readArmored(twoKeys);
|
const pubKeys = await openpgp.key.readArmored(twoKeys);
|
||||||
|
@ -1659,34 +2072,6 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
|
||||||
expect(supported).to.be.false;
|
expect(supported).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Preferences of generated key', function() {
|
|
||||||
const testPref = function(key) {
|
|
||||||
// key flags
|
|
||||||
const keyFlags = openpgp.enums.keyFlags;
|
|
||||||
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys);
|
|
||||||
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data);
|
|
||||||
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication);
|
|
||||||
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
|
|
||||||
const sym = openpgp.enums.symmetric;
|
|
||||||
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]);
|
|
||||||
if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) {
|
|
||||||
const aead = openpgp.enums.aead;
|
|
||||||
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]);
|
|
||||||
}
|
|
||||||
const hash = openpgp.enums.hash;
|
|
||||||
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]);
|
|
||||||
const compr = openpgp.enums.compression;
|
|
||||||
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
|
|
||||||
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]);
|
|
||||||
};
|
|
||||||
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(async function(key) {
|
|
||||||
testPref(key.key);
|
|
||||||
testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('User attribute packet read & write', async function() {
|
it('User attribute packet read & write', async function() {
|
||||||
const key = (await openpgp.key.readArmored(user_attr_key)).keys[0];
|
const key = (await openpgp.key.readArmored(user_attr_key)).keys[0];
|
||||||
const key2 = (await openpgp.key.readArmored(key.armor())).keys[0];
|
const key2 = (await openpgp.key.readArmored(key.armor())).keys[0];
|
||||||
|
@ -1722,229 +2107,6 @@ VYGdb3eNlV8CfoEC
|
||||||
expect(primUser).to.be.null;
|
expect(primUser).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Generated key is not unlocked by default', function() {
|
|
||||||
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
let key;
|
|
||||||
return openpgp.generateKey(opt).then(function(newKey) {
|
|
||||||
key = newKey.key;
|
|
||||||
return openpgp.message.fromText('hello').encrypt([key]);
|
|
||||||
}).then(function(msg) {
|
|
||||||
return msg.message.decrypt([key]);
|
|
||||||
}).catch(function(err) {
|
|
||||||
expect(err.message).to.equal('Private key is not decrypted.');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - single userid', function() {
|
|
||||||
const userId = { name: 'test', email: 'a@b.com', comment: 'test comment' };
|
|
||||||
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
|
||||||
expect(key.users[0].userId.userid).to.equal('test <a@b.com> (test comment)');
|
|
||||||
expect(key.users[0].userId.name).to.equal(userId.name);
|
|
||||||
expect(key.users[0].userId.email).to.equal(userId.email);
|
|
||||||
expect(key.users[0].userId.comment).to.equal(userId.comment);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - setting date to the past', function() {
|
|
||||||
const past = new Date(0);
|
|
||||||
const opt = {
|
|
||||||
numBits: 512,
|
|
||||||
userIds: { name: 'Test User', email: 'text@example.com' },
|
|
||||||
passphrase: 'secret',
|
|
||||||
date: past
|
|
||||||
};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
|
|
||||||
return openpgp.generateKey(opt).then(function(newKey) {
|
|
||||||
expect(newKey.key).to.exist;
|
|
||||||
expect(+newKey.key.getCreationTime()).to.equal(+past);
|
|
||||||
expect(+newKey.key.subKeys[0].getCreationTime()).to.equal(+past);
|
|
||||||
expect(+newKey.key.subKeys[0].bindingSignatures[0].created).to.equal(+past);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Generate key - multi userid', function() {
|
|
||||||
const userId1 = 'test <a@b.com>';
|
|
||||||
const userId2 = 'test <b@c.com>';
|
|
||||||
const opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(2);
|
|
||||||
expect(key.users[0].userId.userid).to.equal(userId1);
|
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
|
||||||
expect(key.users[1].userId.userid).to.equal(userId2);
|
|
||||||
expect(key.users[1].selfCertifications[0].isPrimaryUserID).to.be.null;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - two subkeys with default values', function() {
|
|
||||||
const userId = 'test <a@b.com>';
|
|
||||||
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]};
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
|
||||||
expect(key.users[0].userId.userid).to.equal(userId);
|
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
|
||||||
expect(key.subKeys).to.have.lengthOf(2);
|
|
||||||
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
|
||||||
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - one signing subkey', function() {
|
|
||||||
const userId = 'test <a@b.com>';
|
|
||||||
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
|
||||||
expect(key.users[0].userId.userid).to.equal(userId);
|
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
|
||||||
expect(key.subKeys).to.have.lengthOf(2);
|
|
||||||
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
|
||||||
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('eddsa');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - override main key options for subkey', function() {
|
|
||||||
const userId = 'test <a@b.com>';
|
|
||||||
const opt = {numBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
|
||||||
expect(key.users[0].userId.userid).to.equal(userId);
|
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
|
||||||
expect(key.getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign');
|
|
||||||
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Encrypt key with new passphrase', async function() {
|
|
||||||
const userId = 'test <a@b.com>';
|
|
||||||
const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
const key = (await openpgp.generateKey(opt)).key;
|
|
||||||
const armor1 = key.armor();
|
|
||||||
const armor2 = key.armor();
|
|
||||||
expect(armor1).to.equal(armor2);
|
|
||||||
expect(await key.decrypt('passphrase')).to.be.true;
|
|
||||||
expect(key.isDecrypted()).to.be.true;
|
|
||||||
await key.encrypt('new_passphrase');
|
|
||||||
expect(key.isDecrypted()).to.be.false;
|
|
||||||
await expect(key.decrypt('passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase');
|
|
||||||
expect(key.isDecrypted()).to.be.false;
|
|
||||||
expect(await key.decrypt('new_passphrase')).to.be.true;
|
|
||||||
expect(key.isDecrypted()).to.be.true;
|
|
||||||
const armor3 = key.armor();
|
|
||||||
expect(armor3).to.not.equal(armor1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate key - ensure keyExpirationTime works', function() {
|
|
||||||
const expect_delta = 365 * 24 * 60 * 60;
|
|
||||||
const userId = 'test <a@b.com>';
|
|
||||||
const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(async function(key) {
|
|
||||||
key = key.key;
|
|
||||||
|
|
||||||
const expiration = await key.getExpirationTime();
|
|
||||||
expect(expiration).to.exist;
|
|
||||||
|
|
||||||
const actual_delta = (new Date(expiration) - new Date()) / 1000;
|
|
||||||
expect(Math.abs(actual_delta - expect_delta)).to.be.below(60);
|
|
||||||
|
|
||||||
const subKeyExpiration = await key.subKeys[0].getExpirationTime();
|
|
||||||
expect(subKeyExpiration).to.exist;
|
|
||||||
|
|
||||||
const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000;
|
|
||||||
expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sign and verify key - primary user', async function() {
|
|
||||||
let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0];
|
|
||||||
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
|
||||||
await privateKey.decrypt('hello world');
|
|
||||||
publicKey = await publicKey.signPrimaryUser([privateKey]);
|
|
||||||
const signatures = await publicKey.verifyPrimaryUser([privateKey]);
|
|
||||||
const publicSigningKey = await publicKey.getSigningKey();
|
|
||||||
const privateSigningKey = await privateKey.getSigningKey();
|
|
||||||
expect(signatures.length).to.equal(2);
|
|
||||||
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[0].valid).to.be.null;
|
|
||||||
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[1].valid).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sign key and verify with wrong key - primary user', async function() {
|
|
||||||
let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0];
|
|
||||||
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
|
||||||
const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0];
|
|
||||||
await privateKey.decrypt('hello world');
|
|
||||||
publicKey = await publicKey.signPrimaryUser([privateKey]);
|
|
||||||
const signatures = await publicKey.verifyPrimaryUser([wrongKey]);
|
|
||||||
const publicSigningKey = await publicKey.getSigningKey();
|
|
||||||
const privateSigningKey = await privateKey.getSigningKey();
|
|
||||||
expect(signatures.length).to.equal(2);
|
|
||||||
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[0].valid).to.be.null;
|
|
||||||
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[1].valid).to.be.null;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sign and verify key - all users', async function() {
|
|
||||||
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
|
||||||
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
|
||||||
await privateKey.decrypt('hello world');
|
|
||||||
publicKey = await publicKey.signAllUsers([privateKey]);
|
|
||||||
const signatures = await publicKey.verifyAllUsers([privateKey]);
|
|
||||||
const publicSigningKey = await publicKey.getSigningKey();
|
|
||||||
const privateSigningKey = await privateKey.getSigningKey();
|
|
||||||
expect(signatures.length).to.equal(4);
|
|
||||||
expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
|
|
||||||
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[0].valid).to.be.null;
|
|
||||||
expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
|
|
||||||
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[1].valid).to.be.true;
|
|
||||||
expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
|
|
||||||
expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[2].valid).to.be.null;
|
|
||||||
expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
|
|
||||||
expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[3].valid).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sign key and verify with wrong key - all users', async function() {
|
|
||||||
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
|
||||||
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
|
||||||
const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0];
|
|
||||||
await privateKey.decrypt('hello world');
|
|
||||||
publicKey = await publicKey.signAllUsers([privateKey]);
|
|
||||||
const signatures = await publicKey.verifyAllUsers([wrongKey]);
|
|
||||||
const publicSigningKey = await publicKey.getSigningKey();
|
|
||||||
const privateSigningKey = await privateKey.getSigningKey();
|
|
||||||
expect(signatures.length).to.equal(4);
|
|
||||||
expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
|
|
||||||
expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[0].valid).to.be.null;
|
|
||||||
expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
|
|
||||||
expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[1].valid).to.be.null;
|
|
||||||
expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
|
|
||||||
expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[2].valid).to.be.null;
|
|
||||||
expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
|
|
||||||
expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex());
|
|
||||||
expect(signatures[3].valid).to.be.null;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Encrypt - latest created user', async function() {
|
it('Encrypt - latest created user', async function() {
|
||||||
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0];
|
||||||
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0];
|
||||||
|
@ -2000,138 +2162,6 @@ VYGdb3eNlV8CfoEC
|
||||||
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserId: {name: 'Not Test McTestington', email: 'test@example.com'}, detached: true, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserId: {name: 'Not Test McTestington', email: 'test@example.com'}, detached: true, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Reformat key without passphrase', function() {
|
|
||||||
const userId1 = 'test1 <a@b.com>';
|
|
||||||
const userId2 = 'test2 <b@a.com>';
|
|
||||||
const opt = {numBits: 512, userIds: userId1};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
|
||||||
expect(key.users[0].userId.userid).to.equal(userId1);
|
|
||||||
expect(key.isDecrypted()).to.be.true;
|
|
||||||
opt.privateKey = key;
|
|
||||||
opt.userIds = userId2;
|
|
||||||
return openpgp.reformatKey(opt).then(function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
expect(newKey.users.length).to.equal(1);
|
|
||||||
expect(newKey.users[0].userId.userid).to.equal(userId2);
|
|
||||||
expect(newKey.isDecrypted()).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Reformat key with no subkey with passphrase', async function() {
|
|
||||||
const userId = 'test1 <a@b.com>';
|
|
||||||
const keys = (await openpgp.key.readArmored(key_without_subkey)).keys;
|
|
||||||
const opt = {privateKey: keys[0], userIds: [userId], passphrase: "test"};
|
|
||||||
return openpgp.reformatKey(opt).then(function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
expect(newKey.users.length).to.equal(1);
|
|
||||||
expect(newKey.users[0].userId.userid).to.equal(userId);
|
|
||||||
expect(newKey.isDecrypted()).to.be.false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Reformat key with two subkeys with passphrase', function() {
|
|
||||||
const userId1 = 'test <a@b.com>';
|
|
||||||
const userId2 = 'test <b@c.com>';
|
|
||||||
const now = openpgp.util.normalizeDate(new Date());
|
|
||||||
const before = openpgp.util.normalizeDate(new Date(0));
|
|
||||||
const opt1 = {curve: 'curve25519', userIds: [userId1], date: now};
|
|
||||||
return openpgp.generateKey(opt1).then(function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
expect(newKey.users[0].userId.userid).to.equal(userId1);
|
|
||||||
expect(+newKey.getCreationTime()).to.equal(+now);
|
|
||||||
expect(+newKey.subKeys[0].getCreationTime()).to.equal(+now);
|
|
||||||
expect(+newKey.subKeys[0].bindingSignatures[0].created).to.equal(+now);
|
|
||||||
const opt2 = {privateKey: newKey, userIds: [userId2], date: before};
|
|
||||||
return openpgp.reformatKey(opt2).then(function(refKey) {
|
|
||||||
refKey = refKey.key;
|
|
||||||
expect(refKey.users.length).to.equal(1);
|
|
||||||
expect(refKey.users[0].userId.userid).to.equal(userId2);
|
|
||||||
expect(+refKey.subKeys[0].bindingSignatures[0].created).to.equal(+before);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Reformat key with no subkey without passphrase', async function() {
|
|
||||||
const userId = 'test1 <a@b.com>';
|
|
||||||
const keys = (await openpgp.key.readArmored(key_without_subkey)).keys;
|
|
||||||
const opt = {privateKey: keys[0], userIds: [userId]};
|
|
||||||
return openpgp.reformatKey(opt).then(function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
expect(newKey.users.length).to.equal(1);
|
|
||||||
expect(newKey.users[0].userId.userid).to.equal(userId);
|
|
||||||
expect(newKey.isDecrypted()).to.be.true;
|
|
||||||
return openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: newKey, armor: true}).then(async function(signed) {
|
|
||||||
return openpgp.verify(
|
|
||||||
{message: await openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()}
|
|
||||||
).then(async function(verified) {
|
|
||||||
expect(verified.signatures[0].valid).to.be.true;
|
|
||||||
const newSigningKey = await newKey.getSigningKey();
|
|
||||||
expect(verified.signatures[0].keyid.toHex()).to.equal(newSigningKey.getKeyId().toHex());
|
|
||||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Reformat and encrypt key', function() {
|
|
||||||
const userId1 = 'test1 <a@b.com>';
|
|
||||||
const userId2 = 'test2 <b@c.com>';
|
|
||||||
const userId3 = 'test3 <c@d.com>';
|
|
||||||
const opt = {numBits: 512, userIds: userId1};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
opt.privateKey = key;
|
|
||||||
opt.userIds = [userId2, userId3];
|
|
||||||
opt.passphrase = '123';
|
|
||||||
return openpgp.reformatKey(opt).then(async function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
expect(newKey.users.length).to.equal(2);
|
|
||||||
expect(newKey.users[0].userId.userid).to.equal(userId2);
|
|
||||||
expect(newKey.isDecrypted()).to.be.false;
|
|
||||||
await newKey.decrypt('123');
|
|
||||||
expect(newKey.isDecrypted()).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sign and encrypt with reformatted key', function() {
|
|
||||||
const userId1 = 'test1 <a@b.com>';
|
|
||||||
const userId2 = 'test2 <b@a.com>';
|
|
||||||
const opt = {numBits: 512, userIds: userId1};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
|
||||||
key = key.key;
|
|
||||||
opt.privateKey = key;
|
|
||||||
opt.userIds = userId2;
|
|
||||||
return openpgp.reformatKey(opt).then(function(newKey) {
|
|
||||||
newKey = newKey.key;
|
|
||||||
return openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(async function(encrypted) {
|
|
||||||
return openpgp.decrypt({message: await openpgp.message.readArmored(encrypted.data), privateKeys: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) {
|
|
||||||
expect(decrypted.data).to.equal('hello');
|
|
||||||
expect(decrypted.signatures[0].valid).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Reject with user-friendly error when reformatting encrypted key', function() {
|
|
||||||
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(original) {
|
|
||||||
return openpgp.reformatKey({privateKey: original.key, userIds: 'test2 <b@a.com>', passphrase: '1234'}).then(function() {
|
|
||||||
throw new Error('reformatKey should result in error when key not decrypted');
|
|
||||||
}).catch(function(error) {
|
|
||||||
expect(error.message).to.equal('Error reformatting keypair: Key not decrypted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Find a valid subkey binding signature among many invalid ones', async function() {
|
it('Find a valid subkey binding signature among many invalid ones', async function() {
|
||||||
const key = (await openpgp.key.readArmored(valid_binding_sig_among_many_expired_sigs_pub)).keys[0];
|
const key = (await openpgp.key.readArmored(valid_binding_sig_among_many_expired_sigs_pub)).keys[0];
|
||||||
expect(await key.getEncryptionKey()).to.not.be.null;
|
expect(await key.getEncryptionKey()).to.not.be.null;
|
||||||
|
@ -2160,37 +2190,6 @@ VYGdb3eNlV8CfoEC
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Revoke generated key with revocation certificate', function() {
|
|
||||||
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(function(original) {
|
|
||||||
return openpgp.revokeKey({key: original.key.toPublic(), revocationCertificate: original.revocationCertificate}).then(function(revKey) {
|
|
||||||
revKey = revKey.publicKey;
|
|
||||||
expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason);
|
|
||||||
expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('');
|
|
||||||
return revKey.verifyPrimaryKey().then(function(status) {
|
|
||||||
expect(status).to.equal(openpgp.enums.keyStatus.revoked);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Revoke generated key with private key', function() {
|
|
||||||
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
|
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
|
||||||
return openpgp.generateKey(opt).then(async function(original) {
|
|
||||||
await original.key.decrypt('1234');
|
|
||||||
return openpgp.revokeKey({key: original.key, reasonForRevocation: {string: 'Testing key revocation'}}).then(function(revKey) {
|
|
||||||
revKey = revKey.publicKey;
|
|
||||||
expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason);
|
|
||||||
expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('Testing key revocation');
|
|
||||||
return revKey.verifyPrimaryKey().then(function(status) {
|
|
||||||
expect(status).to.equal(openpgp.enums.keyStatus.revoked);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Merge key with another key with non-ID user attributes', async function() {
|
it('Merge key with another key with non-ID user attributes', async function() {
|
||||||
const key = (await openpgp.key.readArmored(mergeKey1)).keys[0];
|
const key = (await openpgp.key.readArmored(mergeKey1)).keys[0];
|
||||||
const updateKey = (await openpgp.key.readArmored(mergeKey2)).keys[0];
|
const updateKey = (await openpgp.key.readArmored(mergeKey2)).keys[0];
|
||||||
|
@ -2204,4 +2203,4 @@ VYGdb3eNlV8CfoEC
|
||||||
expect(key.users[1].userId).to.be.null;
|
expect(key.users[1].userId).to.be.null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
|
@ -654,6 +654,53 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal;
|
openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Configuration', function() {
|
||||||
|
openpgp.config.show_version = false;
|
||||||
|
openpgp.config.commentstring = 'different';
|
||||||
|
if (openpgp.getWorker()) { // init again to trigger config event
|
||||||
|
openpgp.initWorker({ path:'../dist/openpgp.worker.js' });
|
||||||
|
}
|
||||||
|
return openpgp.encrypt({ publicKeys:publicKey.keys, message:openpgp.message.fromText(plaintext) }).then(function(encrypted) {
|
||||||
|
expect(encrypted.data).to.exist;
|
||||||
|
expect(encrypted.data).not.to.match(/^Version:/);
|
||||||
|
expect(encrypted.data).to.match(/Comment: different/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Test multiple workers', async function() {
|
||||||
|
openpgp.config.show_version = false;
|
||||||
|
openpgp.config.commentstring = 'different';
|
||||||
|
if (!openpgp.getWorker()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { workers } = openpgp.getWorker();
|
||||||
|
try {
|
||||||
|
await privateKey.keys[0].decrypt(passphrase)
|
||||||
|
openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 2});
|
||||||
|
|
||||||
|
const workerTest = (_, index) => {
|
||||||
|
const plaintext = input.createSomeMessage() + index;
|
||||||
|
return openpgp.encrypt({
|
||||||
|
publicKeys: publicKey.keys,
|
||||||
|
data: plaintext
|
||||||
|
}).then(function (encrypted) {
|
||||||
|
expect(encrypted.data).to.exist;
|
||||||
|
expect(encrypted.data).not.to.match(/^Version:/);
|
||||||
|
expect(encrypted.data).to.match(/Comment: different/);
|
||||||
|
return openpgp.decrypt({
|
||||||
|
privateKeys: privateKey.keys[0],
|
||||||
|
message: openpgp.message.readArmored(encrypted.data)
|
||||||
|
});
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
await Promise.all(Array(10).fill(null).map(workerTest));
|
||||||
|
} finally {
|
||||||
|
openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 1 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('Decrypting key with wrong passphrase rejected', async function () {
|
it('Decrypting key with wrong passphrase rejected', async function () {
|
||||||
await expect(privateKey.keys[0].decrypt('wrong passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase');
|
await expect(privateKey.keys[0].decrypt('wrong passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase');
|
||||||
});
|
});
|
||||||
|
@ -662,6 +709,43 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true;
|
expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('decryptKey', function() {
|
||||||
|
it('should work for correct passphrase', function() {
|
||||||
|
return openpgp.decryptKey({
|
||||||
|
privateKey: privateKey.keys[0],
|
||||||
|
passphrase: passphrase
|
||||||
|
}).then(function(unlocked){
|
||||||
|
expect(unlocked.key.getKeyId().toHex()).to.equal(privateKey.keys[0].getKeyId().toHex());
|
||||||
|
expect(unlocked.key.isDecrypted()).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail for incorrect passphrase', function() {
|
||||||
|
return openpgp.decryptKey({
|
||||||
|
privateKey: privateKey.keys[0],
|
||||||
|
passphrase: 'incorrect'
|
||||||
|
}).catch(function(error){
|
||||||
|
expect(error.message).to.match(/Incorrect key passphrase/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Calling decrypt with not decrypted key leads to exception', function() {
|
||||||
|
const encOpt = {
|
||||||
|
message: openpgp.message.fromText(plaintext),
|
||||||
|
publicKeys: publicKey.keys
|
||||||
|
};
|
||||||
|
const decOpt = {
|
||||||
|
privateKeys: privateKey.keys[0]
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(async function(encrypted) {
|
||||||
|
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).catch(function(error) {
|
||||||
|
expect(error.message).to.match(/not decrypted/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
tryTests('CFB mode (asm.js)', tests, {
|
tryTests('CFB mode (asm.js)', tests, {
|
||||||
if: !(typeof window !== 'undefined' && window.Worker),
|
if: !(typeof window !== 'undefined' && window.Worker),
|
||||||
beforeEach: function() {
|
beforeEach: function() {
|
||||||
|
@ -730,90 +814,6 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function tests() {
|
function tests() {
|
||||||
it('Configuration', function() {
|
|
||||||
openpgp.config.show_version = false;
|
|
||||||
openpgp.config.commentstring = 'different';
|
|
||||||
if (openpgp.getWorker()) { // init again to trigger config event
|
|
||||||
openpgp.initWorker({ path:'../dist/openpgp.worker.js' });
|
|
||||||
}
|
|
||||||
return openpgp.encrypt({ publicKeys:publicKey.keys, message:openpgp.message.fromText(plaintext) }).then(function(encrypted) {
|
|
||||||
expect(encrypted.data).to.exist;
|
|
||||||
expect(encrypted.data).not.to.match(/^Version:/);
|
|
||||||
expect(encrypted.data).to.match(/Comment: different/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test multiple workers', async function() {
|
|
||||||
openpgp.config.show_version = false;
|
|
||||||
openpgp.config.commentstring = 'different';
|
|
||||||
if (!openpgp.getWorker()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { workers } = openpgp.getWorker();
|
|
||||||
try {
|
|
||||||
await privateKey.keys[0].decrypt(passphrase)
|
|
||||||
openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 2});
|
|
||||||
|
|
||||||
const workerTest = (_, index) => {
|
|
||||||
const plaintext = input.createSomeMessage() + index;
|
|
||||||
return openpgp.encrypt({
|
|
||||||
publicKeys: publicKey.keys,
|
|
||||||
data: plaintext
|
|
||||||
}).then(function (encrypted) {
|
|
||||||
expect(encrypted.data).to.exist;
|
|
||||||
expect(encrypted.data).not.to.match(/^Version:/);
|
|
||||||
expect(encrypted.data).to.match(/Comment: different/);
|
|
||||||
return openpgp.decrypt({
|
|
||||||
privateKeys: privateKey.keys[0],
|
|
||||||
message: openpgp.message.readArmored(encrypted.data)
|
|
||||||
});
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
await Promise.all(Array(10).fill(null).map(workerTest));
|
|
||||||
} finally {
|
|
||||||
openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 1 });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Calling decrypt with not decrypted key leads to exception', function() {
|
|
||||||
const encOpt = {
|
|
||||||
message: openpgp.message.fromText(plaintext),
|
|
||||||
publicKeys: publicKey.keys
|
|
||||||
};
|
|
||||||
const decOpt = {
|
|
||||||
privateKeys: privateKey.keys[0]
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(async function(encrypted) {
|
|
||||||
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).catch(function(error) {
|
|
||||||
expect(error.message).to.match(/not decrypted/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('decryptKey', function() {
|
|
||||||
it('should work for correct passphrase', function() {
|
|
||||||
return openpgp.decryptKey({
|
|
||||||
privateKey: privateKey.keys[0],
|
|
||||||
passphrase: passphrase
|
|
||||||
}).then(function(unlocked){
|
|
||||||
expect(unlocked.key.getKeyId().toHex()).to.equal(privateKey.keys[0].getKeyId().toHex());
|
|
||||||
expect(unlocked.key.isDecrypted()).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail for incorrect passphrase', function() {
|
|
||||||
return openpgp.decryptKey({
|
|
||||||
privateKey: privateKey.keys[0],
|
|
||||||
passphrase: 'incorrect'
|
|
||||||
}).catch(function(error){
|
|
||||||
expect(error.message).to.match(/Incorrect key passphrase/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('encryptSessionKey, decryptSessionKeys', function() {
|
describe('encryptSessionKey, decryptSessionKeys', function() {
|
||||||
const sk = new Uint8Array([0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01]);
|
const sk = new Uint8Array([0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01]);
|
||||||
|
|
||||||
|
@ -1538,6 +1538,265 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
expect(decrypted.signatures[1].signature.packets.length).to.equal(1);
|
expect(decrypted.signatures[1].signature.packets.length).to.equal(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ELG / DSA encrypt, decrypt, sign, verify', function() {
|
||||||
|
|
||||||
|
it('round trip test', async function () {
|
||||||
|
const pubKeyDE = (await openpgp.key.readArmored(pub_key_de)).keys[0];
|
||||||
|
const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0];
|
||||||
|
await privKeyDE.decrypt(passphrase);
|
||||||
|
pubKeyDE.users[0].selfCertifications[0].features = [7]; // Monkey-patch AEAD feature flag
|
||||||
|
return openpgp.encrypt({
|
||||||
|
publicKeys: pubKeyDE,
|
||||||
|
privateKeys: privKeyDE,
|
||||||
|
message: openpgp.message.fromText(plaintext)
|
||||||
|
}).then(async function (encrypted) {
|
||||||
|
return openpgp.decrypt({
|
||||||
|
privateKeys: privKeyDE,
|
||||||
|
publicKeys: pubKeyDE,
|
||||||
|
message: await openpgp.message.readArmored(encrypted.data)
|
||||||
|
});
|
||||||
|
}).then(async function (decrypted) {
|
||||||
|
expect(decrypted.data).to.exist;
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
expect(decrypted.signatures[0].valid).to.be.true;
|
||||||
|
const signingKey = await privKeyDE.getSigningKey();
|
||||||
|
expect(decrypted.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex());
|
||||||
|
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("3DES decrypt", function() {
|
||||||
|
const pgp_msg =
|
||||||
|
['-----BEGIN PGP MESSAGE-----',
|
||||||
|
'Version: GnuPG/MacGPG2 v2.0.19 (Darwin)',
|
||||||
|
'Comment: GPGTools - https://gpgtools.org',
|
||||||
|
'',
|
||||||
|
'hIwDBU4Dycfvp2EBA/9tuhQgOrcATcm2PRmIOcs6q947YhlsBTZZdVJDfVjkKlyM',
|
||||||
|
'M0yE+lnNplWb041Cpfkkl6IvorKQd2iPbAkOL0IXwmVN41l+PvVgMcuFvvzetehG',
|
||||||
|
'Ca0/VEYOaTZRNqyr9FIzcnVy1I/PaWT3iqVAYa+G8TEA5Dh9RLfsx8ZA9UNIaNI+',
|
||||||
|
'ASm9aZ3H6FerNhm8RezDY5vRn6xw3o/wH5YEBvV2BEmmFKZ2BlqFQxqChr8UNwd1',
|
||||||
|
'Ieebnq0HtBPE8YU/L0U=',
|
||||||
|
'=JyIa',
|
||||||
|
'-----END PGP MESSAGE-----'].join('\n');
|
||||||
|
|
||||||
|
const priv_key =
|
||||||
|
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
|
'Version: GnuPG/MacGPG2 v2.0.19 (Darwin)',
|
||||||
|
'Comment: GPGTools - https://gpgtools.org',
|
||||||
|
'',
|
||||||
|
'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',
|
||||||
|
'22q10ausyQXoOxXfDWVwKA==',
|
||||||
|
'=IkKW',
|
||||||
|
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
||||||
|
|
||||||
|
it('Decrypt message', async function() {
|
||||||
|
const privKey = (await openpgp.key.readArmored(priv_key)).keys[0];
|
||||||
|
await privKey.decrypt('1234');
|
||||||
|
const message = await openpgp.message.readArmored(pgp_msg);
|
||||||
|
|
||||||
|
return openpgp.decrypt({ privateKeys:privKey, message:message }).then(function(decrypted) {
|
||||||
|
expect(decrypted.data).to.equal('hello 3des\n');
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('AES encrypt, decrypt', function() {
|
||||||
|
|
||||||
|
it('should encrypt and decrypt with one password', function () {
|
||||||
|
const encOpt = {
|
||||||
|
message: openpgp.message.fromText(plaintext),
|
||||||
|
passwords: password1
|
||||||
|
};
|
||||||
|
const decOpt = {
|
||||||
|
passwords: password1
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
||||||
|
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt and decrypt with two passwords', function () {
|
||||||
|
const encOpt = {
|
||||||
|
message: openpgp.message.fromText(plaintext),
|
||||||
|
passwords: [password1, password2]
|
||||||
|
};
|
||||||
|
const decOpt = {
|
||||||
|
passwords: password2
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
||||||
|
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should decrypt with two passwords message which GPG fails on', async function () {
|
||||||
|
|
||||||
|
const decOpt = {
|
||||||
|
message: await openpgp.message.readArmored(twoPasswordGPGFail),
|
||||||
|
passwords: password2
|
||||||
|
};
|
||||||
|
return openpgp.decrypt(decOpt).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal('short message\nnext line\n한국어/조선말');
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt and decrypt with password and not ascii armor', function () {
|
||||||
|
const encOpt = {
|
||||||
|
message: openpgp.message.fromText(plaintext),
|
||||||
|
passwords: password1,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decOpt = {
|
||||||
|
passwords: password1
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(function (encrypted) {
|
||||||
|
decOpt.message = encrypted.message;
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt and decrypt with binary data and transferable objects', function () {
|
||||||
|
openpgp.config.zero_copy = true; // activate transferable objects
|
||||||
|
const encOpt = {
|
||||||
|
message: openpgp.message.fromBinary(new Uint8Array([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01])),
|
||||||
|
passwords: password1,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decOpt = {
|
||||||
|
passwords: password1,
|
||||||
|
format: 'binary'
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(function (encrypted) {
|
||||||
|
decOpt.message = encrypted.message;
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
if (openpgp.getWorker()) {
|
||||||
|
expect(encOpt.message.packets[0].data.byteLength).to.equal(0); // transferred buffer should be empty
|
||||||
|
}
|
||||||
|
expect(decrypted.data).to.deep.equal(new Uint8Array([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]));
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Encrypt, decrypt with compression', function() {
|
||||||
|
withCompression(function (modifyCompressionEncryptOptions, verifyCompressionDecrypted) {
|
||||||
|
it('should encrypt and decrypt with one password', function () {
|
||||||
|
const encOpt = modifyCompressionEncryptOptions({
|
||||||
|
message: openpgp.message.fromText(plaintext),
|
||||||
|
passwords: password1
|
||||||
|
});
|
||||||
|
const decOpt = {
|
||||||
|
passwords: password1
|
||||||
|
};
|
||||||
|
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
||||||
|
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
||||||
|
return openpgp.decrypt(decOpt);
|
||||||
|
}).then(function (decrypted) {
|
||||||
|
expect(decrypted.data).to.equal(plaintext);
|
||||||
|
expect(decrypted.signatures.length).to.equal(0);
|
||||||
|
verifyCompressionDecrypted(decrypted);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Streaming encrypt and decrypt small message roundtrip', async function() {
|
||||||
|
let plaintext = [];
|
||||||
|
let i = 0;
|
||||||
|
const data = new ReadableStream({
|
||||||
|
async pull(controller) {
|
||||||
|
if (i++ < 4) {
|
||||||
|
let randomBytes = await openpgp.crypto.random.getRandomBytes(10);
|
||||||
|
controller.enqueue(randomBytes);
|
||||||
|
plaintext.push(randomBytes);
|
||||||
|
} else {
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const encrypted = await openpgp.encrypt(modifyCompressionEncryptOptions({
|
||||||
|
message: openpgp.message.fromBinary(data),
|
||||||
|
passwords: ['test'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const msgAsciiArmored = encrypted.data;
|
||||||
|
const message = await openpgp.message.readArmored(msgAsciiArmored);
|
||||||
|
const decrypted = await openpgp.decrypt({
|
||||||
|
passwords: ['test'],
|
||||||
|
message,
|
||||||
|
format: 'binary'
|
||||||
|
});
|
||||||
|
expect(openpgp.util.isStream(decrypted.data)).to.equal('web');
|
||||||
|
expect(await openpgp.stream.readToEnd(decrypted.data)).to.deep.equal(openpgp.util.concatUint8Array(plaintext));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('AES / RSA sign, verify', function() {
|
||||||
|
const wrong_pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' +
|
||||||
|
'Version: OpenPGP.js v0.9.0\r\n' +
|
||||||
|
'Comment: Hoodiecrow - https://hoodiecrow.com\r\n' +
|
||||||
|
'\r\n' +
|
||||||
|
'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' +
|
||||||
|
'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' +
|
||||||
|
'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' +
|
||||||
|
'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' +
|
||||||
|
'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' +
|
||||||
|
'=6XMW\r\n' +
|
||||||
|
'-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n';
|
||||||
|
|
||||||
|
let decryptedPrivateKey;
|
||||||
|
beforeEach(async function() {
|
||||||
|
if (!decryptedPrivateKey) {
|
||||||
|
expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true;
|
||||||
|
decryptedPrivateKey = privateKey;
|
||||||
|
}
|
||||||
|
privateKey = decryptedPrivateKey;
|
||||||
|
});
|
||||||
|
|
||||||
it('should sign and verify cleartext data', function () {
|
it('should sign and verify cleartext data', function () {
|
||||||
const message = openpgp.cleartext.fromText(plaintext);
|
const message = openpgp.cleartext.fromText(plaintext);
|
||||||
|
@ -1988,240 +2247,7 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('ELG / DSA encrypt, decrypt, sign, verify', function() {
|
|
||||||
|
|
||||||
it('round trip test', async function () {
|
|
||||||
const pubKeyDE = (await openpgp.key.readArmored(pub_key_de)).keys[0];
|
|
||||||
const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0];
|
|
||||||
await privKeyDE.decrypt(passphrase);
|
|
||||||
pubKeyDE.users[0].selfCertifications[0].features = [7]; // Monkey-patch AEAD feature flag
|
|
||||||
return openpgp.encrypt({
|
|
||||||
publicKeys: pubKeyDE,
|
|
||||||
privateKeys: privKeyDE,
|
|
||||||
message: openpgp.message.fromText(plaintext)
|
|
||||||
}).then(async function (encrypted) {
|
|
||||||
return openpgp.decrypt({
|
|
||||||
privateKeys: privKeyDE,
|
|
||||||
publicKeys: pubKeyDE,
|
|
||||||
message: await openpgp.message.readArmored(encrypted.data)
|
|
||||||
});
|
|
||||||
}).then(async function (decrypted) {
|
|
||||||
expect(decrypted.data).to.exist;
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
expect(decrypted.signatures[0].valid).to.be.true;
|
|
||||||
const signingKey = await privKeyDE.getSigningKey();
|
|
||||||
expect(decrypted.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex());
|
|
||||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("3DES decrypt", function() {
|
|
||||||
const pgp_msg =
|
|
||||||
['-----BEGIN PGP MESSAGE-----',
|
|
||||||
'Version: GnuPG/MacGPG2 v2.0.19 (Darwin)',
|
|
||||||
'Comment: GPGTools - https://gpgtools.org',
|
|
||||||
'',
|
|
||||||
'hIwDBU4Dycfvp2EBA/9tuhQgOrcATcm2PRmIOcs6q947YhlsBTZZdVJDfVjkKlyM',
|
|
||||||
'M0yE+lnNplWb041Cpfkkl6IvorKQd2iPbAkOL0IXwmVN41l+PvVgMcuFvvzetehG',
|
|
||||||
'Ca0/VEYOaTZRNqyr9FIzcnVy1I/PaWT3iqVAYa+G8TEA5Dh9RLfsx8ZA9UNIaNI+',
|
|
||||||
'ASm9aZ3H6FerNhm8RezDY5vRn6xw3o/wH5YEBvV2BEmmFKZ2BlqFQxqChr8UNwd1',
|
|
||||||
'Ieebnq0HtBPE8YU/L0U=',
|
|
||||||
'=JyIa',
|
|
||||||
'-----END PGP MESSAGE-----'].join('\n');
|
|
||||||
|
|
||||||
const priv_key =
|
|
||||||
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
|
||||||
'Version: GnuPG/MacGPG2 v2.0.19 (Darwin)',
|
|
||||||
'Comment: GPGTools - https://gpgtools.org',
|
|
||||||
'',
|
|
||||||
'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',
|
|
||||||
'22q10ausyQXoOxXfDWVwKA==',
|
|
||||||
'=IkKW',
|
|
||||||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
|
||||||
|
|
||||||
it('Decrypt message', async function() {
|
|
||||||
const privKey = (await openpgp.key.readArmored(priv_key)).keys[0];
|
|
||||||
await privKey.decrypt('1234');
|
|
||||||
const message = await openpgp.message.readArmored(pgp_msg);
|
|
||||||
|
|
||||||
return openpgp.decrypt({ privateKeys:privKey, message:message }).then(function(decrypted) {
|
|
||||||
expect(decrypted.data).to.equal('hello 3des\n');
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('AES encrypt, decrypt', function() {
|
|
||||||
|
|
||||||
it('should encrypt and decrypt with one password', function () {
|
|
||||||
const encOpt = {
|
|
||||||
message: openpgp.message.fromText(plaintext),
|
|
||||||
passwords: password1
|
|
||||||
};
|
|
||||||
const decOpt = {
|
|
||||||
passwords: password1
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
|
||||||
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should encrypt and decrypt with two passwords', function () {
|
|
||||||
const encOpt = {
|
|
||||||
message: openpgp.message.fromText(plaintext),
|
|
||||||
passwords: [password1, password2]
|
|
||||||
};
|
|
||||||
const decOpt = {
|
|
||||||
passwords: password2
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
|
||||||
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should decrypt with two passwords message which GPG fails on', async function () {
|
|
||||||
|
|
||||||
const decOpt = {
|
|
||||||
message: await openpgp.message.readArmored(twoPasswordGPGFail),
|
|
||||||
passwords: password2
|
|
||||||
};
|
|
||||||
return openpgp.decrypt(decOpt).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal('short message\nnext line\n한국어/조선말');
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should encrypt and decrypt with password and not ascii armor', function () {
|
|
||||||
const encOpt = {
|
|
||||||
message: openpgp.message.fromText(plaintext),
|
|
||||||
passwords: password1,
|
|
||||||
armor: false
|
|
||||||
};
|
|
||||||
const decOpt = {
|
|
||||||
passwords: password1
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(function (encrypted) {
|
|
||||||
decOpt.message = encrypted.message;
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should encrypt and decrypt with binary data and transferable objects', function () {
|
|
||||||
openpgp.config.zero_copy = true; // activate transferable objects
|
|
||||||
const encOpt = {
|
|
||||||
message: openpgp.message.fromBinary(new Uint8Array([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01])),
|
|
||||||
passwords: password1,
|
|
||||||
armor: false
|
|
||||||
};
|
|
||||||
const decOpt = {
|
|
||||||
passwords: password1,
|
|
||||||
format: 'binary'
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(function (encrypted) {
|
|
||||||
decOpt.message = encrypted.message;
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
if (openpgp.getWorker()) {
|
|
||||||
expect(encOpt.message.packets[0].data.byteLength).to.equal(0); // transferred buffer should be empty
|
|
||||||
}
|
|
||||||
expect(decrypted.data).to.deep.equal(new Uint8Array([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]));
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Encrypt, decrypt with compression', function() {
|
|
||||||
withCompression(function (modifyCompressionEncryptOptions, verifyCompressionDecrypted) {
|
|
||||||
it('should encrypt and decrypt with one password', function () {
|
|
||||||
const encOpt = modifyCompressionEncryptOptions({
|
|
||||||
message: openpgp.message.fromText(plaintext),
|
|
||||||
passwords: password1
|
|
||||||
});
|
|
||||||
const decOpt = {
|
|
||||||
passwords: password1
|
|
||||||
};
|
|
||||||
return openpgp.encrypt(encOpt).then(async function (encrypted) {
|
|
||||||
decOpt.message = await openpgp.message.readArmored(encrypted.data);
|
|
||||||
return openpgp.decrypt(decOpt);
|
|
||||||
}).then(function (decrypted) {
|
|
||||||
expect(decrypted.data).to.equal(plaintext);
|
|
||||||
expect(decrypted.signatures.length).to.equal(0);
|
|
||||||
verifyCompressionDecrypted(decrypted);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Streaming encrypt and decrypt small message roundtrip', async function() {
|
|
||||||
let plaintext = [];
|
|
||||||
let i = 0;
|
|
||||||
const data = new ReadableStream({
|
|
||||||
async pull(controller) {
|
|
||||||
if (i++ < 4) {
|
|
||||||
let randomBytes = await openpgp.crypto.random.getRandomBytes(10);
|
|
||||||
controller.enqueue(randomBytes);
|
|
||||||
plaintext.push(randomBytes);
|
|
||||||
} else {
|
|
||||||
controller.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const encrypted = await openpgp.encrypt(modifyCompressionEncryptOptions({
|
|
||||||
message: openpgp.message.fromBinary(data),
|
|
||||||
passwords: ['test'],
|
|
||||||
}));
|
|
||||||
|
|
||||||
const msgAsciiArmored = encrypted.data;
|
|
||||||
const message = await openpgp.message.readArmored(msgAsciiArmored);
|
|
||||||
const decrypted = await openpgp.decrypt({
|
|
||||||
passwords: ['test'],
|
|
||||||
message,
|
|
||||||
format: 'binary'
|
|
||||||
});
|
|
||||||
expect(openpgp.util.isStream(decrypted.data)).to.equal('web');
|
|
||||||
expect(await openpgp.stream.readToEnd(decrypted.data)).to.deep.equal(openpgp.util.concatUint8Array(plaintext));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Errors', function() {
|
describe('Errors', function() {
|
||||||
|
@ -2241,8 +2267,6 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user