Add 'armor' parameter to sign api

This commit is contained in:
Tankred Hase 2016-02-09 12:57:23 +07:00
parent c0cc0ee991
commit 206f1f9c0f
3 changed files with 181 additions and 105 deletions

View File

@ -26,8 +26,6 @@
import * as messageLib from './message.js';
import * as cleartext from './cleartext.js';
import * as key from './key.js';
import armorLib from './encoding/armor.js';
import enums from './enums.js';
import config from './config/config.js';
import util from './util';
import AsyncProxy from './worker/async_proxy.js';
@ -154,7 +152,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, filename, ar
if(armor) {
return {
data: armorLib.encode(enums.armor.message, message.packets.write())
data: message.armor()
};
}
@ -207,25 +205,33 @@ export function decrypt({ message, privateKey, publicKeys, sessionKey, password,
/**
* Signs a cleartext message
* @param {String} data cleartext input to be signed
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
* @return {Promise<String>} ASCII armored message
* @param {String} data cleartext input to be signed
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
* @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
* @return {Promise<String|CleartextMessage>} ASCII armored message or the message of type CleartextMessage
* @static
*/
export function sign({ data, privateKeys }) {
export function sign({ data, privateKeys, armor=true }) {
checkString(data);
privateKeys = toArray(privateKeys);
if (asyncProxy) { // use web worker if available
return asyncProxy.delegate('sign', { data, privateKeys });
return asyncProxy.delegate('sign', { data, privateKeys, armor });
}
return execute(() => {
const cleartextMessage = new cleartext.CleartextMessage(data);
cleartextMessage.sign(privateKeys);
if(armor) {
return {
data: cleartextMessage.armor()
};
}
return {
data: cleartextMessage.armor()
message: cleartextMessage
};
}, 'Error signing cleartext message');

View File

@ -30,6 +30,7 @@ import crypto from '../crypto';
import packet from '../packet';
import * as key from '../key.js';
import * as message from '../message.js';
import * as cleartext from '../cleartext.js';
import type_keyid from '../type/keyid.js';
const INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
@ -137,7 +138,7 @@ AsyncProxy.prototype.delegate = function(method, options) {
this.worker.postMessage({ event:method, options:clonePackets(options) });
// remember to handle parsing cloned packets from worker
this.tasks.push({ resolve: data => resolve(parseClonedPackets(data)), reject });
this.tasks.push({ resolve: data => resolve(parseClonedPackets(data, method)), reject });
});
};
@ -154,11 +155,13 @@ function clonePackets(options) {
return options;
}
function parseClonedPackets(data) {
function parseClonedPackets(data, method) {
if (data.key) {
data.key = packetlistCloneToKey(data.key);
}
if (data.message) {
if (data.message && method === 'sign') { // sign supports only CleartextMessage
data.message = packetlistCloneToCleartextMessage(data.message);
} else if (data.message) {
data.message = packetlistCloneToMessage(data.message);
}
if (data.signatures) {
@ -177,6 +180,11 @@ function packetlistCloneToMessage(clone) {
return new message.Message(packetlist);
}
function packetlistCloneToCleartextMessage(clone) {
var packetlist = packet.List.fromStructuredClone(clone.packets);
return new cleartext.CleartextMessage(clone.text, packetlist);
}
function packetlistCloneToSignature(clone) {
clone.keyid = type_keyid.fromClone(clone.keyid);
return clone;

View File

@ -264,7 +264,7 @@ describe('OpenPGP.js public api tests', function() {
});
});
describe('encrypt, decrypt - integration tests', function() {
describe('encrypt, decrypt, sign, verify - integration tests', function() {
var pub_key =
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
@ -385,12 +385,24 @@ describe('OpenPGP.js public api tests', function() {
});
});
describe('with unlocked key', function() {
describe('with pgp key pair', function() {
var 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';
beforeEach(function() {
expect(privateKey.keys[0].decrypt(passphrase)).to.be.true;
});
it('should encrypt then decrypt with pgp key pair', function(done) {
it('should encrypt then decrypt', function(done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
@ -408,7 +420,7 @@ describe('OpenPGP.js public api tests', function() {
});
});
it('should encrypt/sign and decrypt/verify with pgp key pair', function(done) {
it('should encrypt/sign and decrypt/verify', function(done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
@ -424,23 +436,12 @@ describe('OpenPGP.js public api tests', function() {
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].primaryKey.getKeyId().toHex());
done();
});
});
it('should fail to verify with wrong public pgp key', function(done) {
var 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';
it('should fail to verify decrypted data with wrong public pgp key', function(done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
@ -456,95 +457,156 @@ describe('OpenPGP.js public api tests', function() {
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].primaryKey.getKeyId().toHex());
done();
});
});
it('should sign and verify cleartext data', function(done) {
var signOpt = {
data: plaintext,
privateKeys: privateKey.keys
};
var verifyOpt = {
publicKeys: publicKey.keys
};
openpgp.sign(signOpt).then(function(signed) {
verifyOpt.message = openpgp.cleartext.readArmored(signed.data);
return openpgp.verify(verifyOpt);
}).then(function(verified) {
expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].primaryKey.getKeyId().toHex());
done();
});
});
it('should sign and fail to verify cleartext data with wrong public pgp key', function(done) {
var signOpt = {
data: plaintext,
privateKeys: privateKey.keys
};
var verifyOpt = {
publicKeys: openpgp.key.readArmored(wrong_pubkey).keys
};
openpgp.sign(signOpt).then(function(signed) {
verifyOpt.message = openpgp.cleartext.readArmored(signed.data);
return openpgp.verify(verifyOpt);
}).then(function(verified) {
expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.null;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].primaryKey.getKeyId().toHex());
done();
});
});
it('should sign and verify cleartext data and not armor', function(done) {
var signOpt = {
data: plaintext,
privateKeys: privateKey.keys,
armor: false
};
var verifyOpt = {
publicKeys: publicKey.keys
};
openpgp.sign(signOpt).then(function(signed) {
verifyOpt.message = signed.message;
return openpgp.verify(verifyOpt);
}).then(function(verified) {
expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].primaryKey.getKeyId().toHex());
done();
});
});
});
it('should encrypt and decrypt with one password', function(done) {
var encOpt = {
data: plaintext,
passwords: password1
};
var decOpt = {
password: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
describe('with symmetric entryption', function() {
it('should encrypt and decrypt with one password', function(done) {
var encOpt = {
data: plaintext,
passwords: password1
};
var decOpt = {
password: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
it('should encrypt and decrypt with two passwords', function(done) {
var encOpt = {
data: plaintext,
passwords: [password1, password2]
};
var decOpt = {
password: password2
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
it('should encrypt and decrypt with two passwords', function(done) {
var encOpt = {
data: plaintext,
passwords: [password1, password2]
};
var decOpt = {
password: password2
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
it('should encrypt and decrypt with password and not ascii armor', function(done) {
var encOpt = {
data: plaintext,
passwords: password1,
armor: false
};
var decOpt = {
password: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = encrypted.message;
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
it('should encrypt and decrypt with password and not ascii armor', function(done) {
var encOpt = {
data: plaintext,
passwords: password1,
armor: false
};
var decOpt = {
password: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = encrypted.message;
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
it('should encrypt and decrypt with one session key', function(done) {
var encOpt = {
data: plaintext,
passwords: password1
};
var decOpt = {
sessionKey: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
it('should encrypt and decrypt with one session key', function(done) {
var encOpt = {
data: plaintext,
passwords: password1
};
var decOpt = {
sessionKey: password1
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
it('should encrypt and decrypt with two session keys and not ascii armor', function(done) {
var encOpt = {
data: plaintext,
passwords: [password1, password2],
armor: false
};
var decOpt = {
sessionKey: password2
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = encrypted.message;
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
it('should encrypt and decrypt with two session keys and not ascii armor', function(done) {
var encOpt = {
data: plaintext,
passwords: [password1, password2],
armor: false
};
var decOpt = {
sessionKey: password2
};
openpgp.encrypt(encOpt).then(function(encrypted) {
decOpt.message = encrypted.message;
return openpgp.decrypt(decOpt);
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
}