diff --git a/src/openpgp.js b/src/openpgp.js index 42cad0a3..39b48dc7 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -317,7 +317,7 @@ export function encrypt({ data, dataType, publicKeys, privateKeys, passwords, se if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified if (detached) { const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserId); - result.signature = armor ? detachedSignature.armor() : detachedSignature; + result.signature = armor ? await convertStream(detachedSignature.armor(), asStream) : detachedSignature; } else { message = await message.sign(privateKeys, signature, date, fromUserId); } @@ -425,7 +425,7 @@ export function sign({ data, dataType, privateKeys, armor=true, asStream, detach if (detached) { const signature = await message.signDetached(privateKeys, undefined, date, fromUserId); - result.signature = armor ? signature.armor() : signature; + result.signature = armor ? await convertStream(signature.armor(), asStream) : signature; } else { message = await message.sign(privateKeys, undefined, date, fromUserId); if (armor) { diff --git a/src/packet/clone.js b/src/packet/clone.js index c7479790..eb9ba4a5 100644 --- a/src/packet/clone.js +++ b/src/packet/clone.js @@ -151,7 +151,7 @@ function packetlistCloneToSignatures(clone) { } function packetlistCloneToSignature(clone) { - if (util.isString(clone)) { + if (util.isString(clone) || util.isStream(clone)) { //signature is armored return clone; } diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index a96b3276..40eeeb5e 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -76,6 +76,8 @@ List.prototype.read = async function (bytes) { const { done, value } = await reader.read(); if (!done) { this.push(value); + } else { + this.stream = null; } if (done || value.fromStream) { break; diff --git a/src/packet/signature.js b/src/packet/signature.js index c447ba28..f29fc156 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -160,7 +160,7 @@ Signature.prototype.write = function () { arr.push(this.signatureData); arr.push(this.unhashedSubpackets ? this.unhashedSubpackets : util.writeNumber(0, 2)); arr.push(this.signedHashValue); - arr.push(this.signature); + arr.push(stream.clone(this.signature)); return util.concat(arr); }; diff --git a/src/util.js b/src/util.js index 33f0be0f..08171753 100644 --- a/src/util.js +++ b/src/util.js @@ -97,6 +97,9 @@ export default { } return; } + if (typeof MessagePort !== 'undefined' && MessagePort.prototype.isPrototypeOf(value)) { + throw new Error("Can't transfer the same stream twice."); + } util.collectTransferables(value, collection); }); } @@ -344,10 +347,10 @@ export default { if (list.some(util.isStream)) { return stream.concat(list); } - if (util.isUint8Array(list[0])) { - return util.concatUint8Array(list); + if (util.isString(list[0])) { + return list.join(''); } - return list.join(''); + return util.concatUint8Array(list); }, /** diff --git a/test/general/brainpool.js b/test/general/brainpool.js index d81aee24..9c6ad51b 100644 --- a/test/general/brainpool.js +++ b/test/general/brainpool.js @@ -213,14 +213,14 @@ describe('Brainpool Cryptography', function () { function omnibus() { it('Omnibus BrainpoolP256r1 Test', function () { const options = { userIds: {name: "Hi", email: "hi@hel.lo"}, curve: "brainpoolP256r1" }; - return openpgp.generateKey(options).then(function (firstKey) { - const hi = firstKey.key; - const pubHi = hi.toPublic(); + return openpgp.generateKey(options).then(async function (firstKey) { + const hi = (await openpgp.key.readArmored(firstKey.privateKeyArmored)).keys[0]; + const pubHi = (await openpgp.key.readArmored(firstKey.publicKeyArmored)).keys[0]; const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "brainpoolP256r1" }; - return openpgp.generateKey(options).then(function (secondKey) { - const bye = secondKey.key; - const pubBye = bye.toPublic(); + return openpgp.generateKey(options).then(async function (secondKey) { + const bye = (await openpgp.key.readArmored(secondKey.privateKeyArmored)).keys[0]; + const pubBye = (await openpgp.key.readArmored(secondKey.publicKeyArmored)).keys[0]; const testData = input.createSomeMessage(); const testData2 = input.createSomeMessage(); diff --git a/test/general/ecc_nist.js b/test/general/ecc_nist.js index 4e65ddc5..61cbaff1 100644 --- a/test/general/ecc_nist.js +++ b/test/general/ecc_nist.js @@ -241,14 +241,14 @@ describe('Elliptic Curve Cryptography', function () { const options = { userIds: {name: "Hi", email: "hi@hel.lo"}, curve: "p256" }; const testData = input.createSomeMessage(); const testData2 = input.createSomeMessage(); - return openpgp.generateKey(options).then(function (firstKey) { - const hi = firstKey.key; - const pubHi = hi.toPublic(); + return openpgp.generateKey(options).then(async function (firstKey) { + const hi = (await openpgp.key.readArmored(firstKey.privateKeyArmored)).keys[0]; + const pubHi = (await openpgp.key.readArmored(firstKey.publicKeyArmored)).keys[0]; - const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "p256" }; - return openpgp.generateKey(options).then(function (secondKey) { - const bye = secondKey.key; - const pubBye = bye.toPublic(); + const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "brainpoolP256r1" }; + return openpgp.generateKey(options).then(async function (secondKey) { + const bye = (await openpgp.key.readArmored(secondKey.privateKeyArmored)).keys[0]; + const pubBye = (await openpgp.key.readArmored(secondKey.publicKeyArmored)).keys[0]; return Promise.all([ // Signing message diff --git a/test/general/openpgp.js b/test/general/openpgp.js index 15611d03..6fb19a3c 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -1704,16 +1704,15 @@ describe('OpenPGP.js public api tests', function() { data: plaintext, privateKeys: privateKey_1337.keys, detached: true, - date: past, - armor: false + date: past }; const verifyOpt = { publicKeys: publicKey_1337.keys, date: past }; - return openpgp.sign(signOpt).then(function (signed) { + return openpgp.sign(signOpt).then(async function (signed) { verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext); - verifyOpt.signature = signed.signature; + verifyOpt.signature = await openpgp.signature.readArmored(signed.signature); return openpgp.verify(verifyOpt).then(function (verified) { expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past); expect(verified.data).to.equal(plaintext); @@ -1828,7 +1827,8 @@ describe('OpenPGP.js public api tests', function() { const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); expect(literals.length).to.equal(1); expect(+literals[0].date).to.equal(+past); - const signatures = await packets.verify(encryptOpt.publicKeys, past); + let signatures = await packets.verify(encryptOpt.publicKeys, past); + signatures = await openpgp.stream.readToEnd(signatures, arr => arr); expect(+signatures[0].signature.packets[0].created).to.equal(+past); expect(signatures[0].valid).to.be.true; expect(encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, past)) @@ -1856,7 +1856,8 @@ describe('OpenPGP.js public api tests', function() { expect(literals.length).to.equal(1); expect(literals[0].format).to.equal('binary'); expect(+literals[0].date).to.equal(+future); - const signatures = await packets.verify(encryptOpt.publicKeys, future); + let signatures = await packets.verify(encryptOpt.publicKeys, future); + signatures = await openpgp.stream.readToEnd(signatures, arr => arr); expect(+signatures[0].signature.packets[0].created).to.equal(+future); expect(signatures[0].valid).to.be.true; expect(encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) @@ -1885,7 +1886,8 @@ describe('OpenPGP.js public api tests', function() { expect(literals.length).to.equal(1); expect(literals[0].format).to.equal('mime'); expect(+literals[0].date).to.equal(+future); - const signatures = await packets.verify(encryptOpt.publicKeys, future); + let signatures = await packets.verify(encryptOpt.publicKeys, future); + signatures = await openpgp.stream.readToEnd(signatures, arr => arr); expect(+signatures[0].signature.packets[0].created).to.equal(+future); expect(signatures[0].valid).to.be.true; expect(encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) diff --git a/test/general/packet.js b/test/general/packet.js index a2983219..dbf01d7e 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -727,7 +727,7 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu =wEIR -----END PGP SIGNATURE-----`; - const signature = openpgp.signature.readArmored(armored_sig); + const signature = await openpgp.signature.readArmored(armored_sig); expect(signature.packets[0].signersUserId).to.equal('test-wkd@metacode.biz'); }); @@ -829,6 +829,7 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu const signed2 = new openpgp.packet.List(); await signed2.read(raw); + signed2.concat(await openpgp.stream.readToEnd(signed2.stream, arr => arr)); await expect(signed2[1].verify(key, signed2[0])).to.eventually.be.true; }); diff --git a/test/general/signature.js b/test/general/signature.js index 55fc4eac..bf30ca37 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -342,7 +342,8 @@ describe("Signature", function() { await priv_key_gnupg_ext.subKeys[0].keyPacket.decrypt("abcd"); return msg.decrypt([priv_key_gnupg_ext]).then(function(msg) { - return msg.verify([pub_key]).then(verified => { + return msg.verify([pub_key]).then(async verified => { + verified = await openpgp.stream.readToEnd(verified, arr => arr); expect(verified).to.exist; expect(verified).to.have.length(1); expect(verified[0].valid).to.be.true; @@ -366,7 +367,8 @@ describe("Signature", function() { const sMsg = await openpgp.message.readArmored(signedArmor); const pub_key = (await openpgp.key.readArmored(pub_key_arm2)).keys[0]; - return sMsg.verify([pub_key]).then(verified => { + return sMsg.verify([pub_key]).then(async verified => { + verified = await openpgp.stream.readToEnd(verified, arr => arr); expect(verified).to.exist; expect(verified).to.have.length(1); expect(verified[0].valid).to.be.true; @@ -437,6 +439,7 @@ describe("Signature", function() { expect(pubKey3.getKeys(keyids[0])).to.not.be.empty; return sMsg.verify([pubKey2, pubKey3]).then(async verifiedSig => { + verifiedSig = await openpgp.stream.readToEnd(verifiedSig, arr => arr); expect(verifiedSig).to.exist; expect(verifiedSig).to.have.length(2); expect(verifiedSig[0].valid).to.be.true; @@ -719,11 +722,11 @@ yYDnCgA= it('Should verify cleartext message correctly when using a detached binary signature and text literal data', async function () { const plaintext = 'short message\nnext line\n한국어/조선말'; const plaintextArray = openpgp.util.str_to_Uint8Array(plaintext); - const pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; - const privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; + const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0]; + const privKey = (await openpgp.key.readArmored(priv_key_arm2)).keys[0]; await privKey.decrypt('hello world'); - return openpgp.sign({ privateKeys:[privKey], data:plaintextArray, detached: true}).then(function(signed) { - const signature = openpgp.signature.readArmored(signed.signature); + return openpgp.sign({ privateKeys:[privKey], data:plaintextArray, detached: true}).then(async function(signed) { + const signature = await openpgp.signature.readArmored(signed.signature); return openpgp.verify({ publicKeys:[pubKey], message: openpgp.message.fromText(plaintext), signature: signature }); }).then(function(cleartextSig) { expect(cleartextSig).to.exist; @@ -880,7 +883,8 @@ yYDnCgA= // Text const msg = openpgp.message.fromText(content); await msg.appendSignature(detachedSig); - return msg.verify(publicKeys).then(result => { + return msg.verify(publicKeys).then(async result => { + result = await openpgp.stream.readToEnd(result, arr => arr); expect(result[0].valid).to.be.true; }); }); diff --git a/test/general/x25519.js b/test/general/x25519.js index 93bea465..a83bdbba 100644 --- a/test/general/x25519.js +++ b/test/general/x25519.js @@ -212,7 +212,6 @@ describe('X25519 Cryptography', function () { expect(result.signatures[0].valid).to.be.true; }); - // TODO export, then reimport key and validate function omnibus() { it('Omnibus Ed25519/Curve25519 Test', function () { const options = { @@ -223,12 +222,14 @@ describe('X25519 Cryptography', function () { expect(firstKey).to.exist; expect(firstKey.privateKeyArmored).to.exist; expect(firstKey.publicKeyArmored).to.exist; - expect(firstKey.key).to.exist; - expect(firstKey.key.primaryKey).to.exist; - expect(firstKey.key.subKeys).to.have.length(1); - expect(firstKey.key.subKeys[0].keyPacket).to.exist; - const hi = firstKey.key; + const hi = (await openpgp.key.readArmored(firstKey.privateKeyArmored)).keys[0]; + const pubHi = (await openpgp.key.readArmored(firstKey.publicKeyArmored)).keys[0]; + expect(hi).to.exist; + expect(hi.primaryKey).to.exist; + expect(hi.subKeys).to.have.length(1); + expect(hi.subKeys[0].subKey).to.exist; + const primaryKey = hi.primaryKey; const subKey = hi.subKeys[0]; expect(hi.getAlgorithmInfo().curve).to.equal('ed25519'); @@ -242,7 +243,7 @@ describe('X25519 Cryptography', function () { primaryKey, { userId: user.userId, key: primaryKey } )).to.eventually.be.true; await expect(user.verifyCertificate( - primaryKey, user.selfCertifications[0], [hi.toPublic()] + primaryKey, user.selfCertifications[0], [pubHi] )).to.eventually.equal(openpgp.enums.keyStatus.valid); const options = { @@ -250,7 +251,8 @@ describe('X25519 Cryptography', function () { curve: "curve25519" }; return openpgp.generateKey(options).then(async function (secondKey) { - const bye = secondKey.key; + const bye = (await openpgp.key.readArmored(secondKey.privateKeyArmored)).keys[0]; + const pubBye = (await openpgp.key.readArmored(secondKey.publicKeyArmored)).keys[0]; expect(bye.getAlgorithmInfo().curve).to.equal('ed25519'); expect(bye.getAlgorithmInfo().algorithm).to.equal('eddsa'); expect(bye.subKeys[0].getAlgorithmInfo().curve).to.equal('curve25519'); @@ -262,14 +264,14 @@ describe('X25519 Cryptography', function () { bye.primaryKey, { userId: user.userId, key: bye.primaryKey } )).to.eventually.be.true; await expect(user.verifyCertificate( - bye.primaryKey, user.selfCertifications[0], [bye.toPublic()] + bye.primaryKey, user.selfCertifications[0], [pubBye] )).to.eventually.equal(openpgp.enums.keyStatus.valid); return Promise.all([ // Hi trusts Bye! - bye.toPublic().signPrimaryUser([hi]).then(trustedBye => { + pubBye.signPrimaryUser([hi]).then(trustedBye => { expect(trustedBye.users[0].otherCertifications[0].verify( - primaryKey, { userId: user.userId, key: bye.toPublic().primaryKey } + primaryKey, { userId: user.userId, key: pubBye.primaryKey } )).to.eventually.be.true; }), // Signing message @@ -280,12 +282,12 @@ describe('X25519 Cryptography', function () { // Verifying signed message return Promise.all([ openpgp.verify( - { message: msg, publicKeys: hi.toPublic() } + { message: msg, publicKeys: pubHi } ).then(output => expect(output.signatures[0].valid).to.be.true), // Verifying detached signature openpgp.verify( { message: openpgp.message.fromText('Hi, this is me, Hi!'), - publicKeys: hi.toPublic(), + publicKeys: pubHi, signature: await openpgp.signature.readArmored(signed.data) } ).then(output => expect(output.signatures[0].valid).to.be.true) ]); @@ -293,7 +295,7 @@ describe('X25519 Cryptography', function () { // Encrypting and signing openpgp.encrypt( { data: 'Hi, Hi wrote this but only Bye can read it!', - publicKeys: [bye.toPublic()], + publicKeys: [pubBye], privateKeys: [hi] } ).then(async encrypted => { const msg = await openpgp.message.readArmored(encrypted.data); @@ -301,7 +303,7 @@ describe('X25519 Cryptography', function () { return openpgp.decrypt( { message: msg, privateKeys: bye, - publicKeys: [hi.toPublic()] } + publicKeys: [pubHi] } ).then(output => { expect(output.data).to.equal('Hi, Hi wrote this but only Bye can read it!'); expect(output.signatures[0].valid).to.be.true;