diff --git a/src/message.js b/src/message.js index f24a619b..76f58c4b 100644 --- a/src/message.js +++ b/src/message.js @@ -564,9 +564,15 @@ export async function createVerificationObjects(signatureList, literalDataList, } })); + // If this is a text signature, canonicalize line endings of the data + const literalDataPacket = literalDataList[0]; + if (signature.signatureType === enums.signature.text) { + literalDataPacket.setText(literalDataPacket.getText()); + } + const verifiedSig = { keyid: signature.issuerKeyId, - valid: keyPacket ? await signature.verify(keyPacket, literalDataList[0]) : null + valid: keyPacket ? await signature.verify(keyPacket, literalDataPacket) : null }; const packetlist = new packet.List(); diff --git a/src/openpgp.js b/src/openpgp.js index b1d77d0a..a1ef6550 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -335,9 +335,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe * @async * @static */ -export function sign({ - data, privateKeys, armor=true, detached=false, date=new Date() -}) { +export function sign({ data, privateKeys, armor=true, detached=false, date=new Date() }) { checkData(data); privateKeys = toArray(privateKeys); diff --git a/src/packet/literal.js b/src/packet/literal.js index 9ce967a9..453dddf2 100644 --- a/src/packet/literal.js +++ b/src/packet/literal.js @@ -49,8 +49,9 @@ function Literal(date=new Date()) { Literal.prototype.setText = function(text) { // normalize EOL to \r\n text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/\n/g, '\r\n'); + this.format = 'utf8'; // encode UTF8 - this.data = this.format === 'utf8' ? util.str_to_Uint8Array(util.encode_utf8(text)) : util.str_to_Uint8Array(text); + this.data = util.str_to_Uint8Array(util.encode_utf8(text)); }; /** diff --git a/test/general/signature.js b/test/general/signature.js index 5db953e0..89211fd7 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -640,6 +640,41 @@ describe("Signature", function() { }); }); + it('Should verify cleartext message correctly when using a detached cleartext signature and binary literal data', async function () { + const plaintext = 'short message\nnext line\n한국어/조선말'; + const pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; + const privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; + await privKey.primaryKey.decrypt('hello world'); + return openpgp.sign({ privateKeys:[privKey], data:plaintext, detached: true}).then(function(signed) { + const signature = openpgp.signature.readArmored(signed.signature); + return openpgp.verify({ publicKeys:[pubKey], message: openpgp.message.fromBinary(openpgp.util.str_to_Uint8Array(openpgp.util.encode_utf8(plaintext))), signature: signature }); + }).then(function(cleartextSig) { + expect(cleartextSig).to.exist; + expect(cleartextSig.signatures).to.have.length(1); + expect(cleartextSig.signatures[0].valid).to.be.true; + expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('Should verify encrypted cleartext message correctly when encrypting binary literal data with a canonical text signature', async function () { + const plaintext = 'short message\nnext line\n한국어/조선말'; + const pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; + const privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; + await Promise.all([privKey.primaryKey.decrypt('hello world'), privKey.subKeys[0].subKey.decrypt('hello world')]); + return openpgp.sign({ privateKeys:[privKey], data: plaintext, detached: true}).then(function(signed) { + const signature = openpgp.signature.readArmored(signed.signature); + return openpgp.encrypt({ data: openpgp.util.str_to_Uint8Array(openpgp.util.encode_utf8(plaintext)), publicKeys: [pubKey], signature }) + }).then(({ data }) => { + const csMsg = openpgp.message.readArmored(data); + return openpgp.decrypt({ message: csMsg, privateKeys: [ privKey ], publicKeys: [ pubKey ] }); + }).then(function(cleartextSig) { + expect(cleartextSig).to.exist; + expect(cleartextSig.signatures).to.have.length(1); + expect(cleartextSig.signatures[0].valid).to.be.true; + expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1); + }); + }); + it('Verify test with expired verification public key', function() { const pubKey = openpgp.key.readArmored(pub_expired).keys[0]; const message = openpgp.message.readArmored(msg_sig_expired);