diff --git a/package.json b/package.json index 17683417..059f0e72 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openpgp", "description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.", - "version": "0.7.0", + "version": "0.7.1-dev", "homepage": "http://openpgpjs.org/", "engines": { "node": ">=0.8" diff --git a/src/encoding/armor.js b/src/encoding/armor.js index 13ea2d0a..57708bf0 100644 --- a/src/encoding/armor.js +++ b/src/encoding/armor.js @@ -38,7 +38,7 @@ var base64 = require('./base64.js'), * 5 = PRIVATE KEY BLOCK */ function getType(text) { - var reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK)-----$\n/m; + var reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$\n/m; var header = text.match(reHeader); diff --git a/src/message.js b/src/message.js index 8e758bdf..374f727f 100644 --- a/src/message.js +++ b/src/message.js @@ -290,6 +290,22 @@ function readArmored(armoredText) { return newMessage; } +/** + * Create a message object from signed content and a detached armored signature. + * @param {String} content An 8 bit ascii string containing e.g. a MIME subtree with text nodes or attachments + * @param {String} detachedSignature The detached ascii armored PGP signarure + */ +function readSignedContent(content, detachedSignature) { + var literalDataPacket = new packet.Literal(); + literalDataPacket.setBytes(content, enums.read(enums.literal, enums.literal.binary)); + var packetlist = new packet.List(); + packetlist.push(literalDataPacket); + var input = armor.decode(detachedSignature).data; + packetlist.read(input); + var newMessage = new Message(packetlist); + return newMessage; +} + /** * creates new message object from text * @param {String} text @@ -323,5 +339,6 @@ function fromBinary(bytes) { exports.Message = Message; exports.readArmored = readArmored; +exports.readSignedContent = readSignedContent; exports.fromText = fromText; exports.fromBinary = fromBinary; diff --git a/test/general/armor.js b/test/general/armor.js index 205766eb..a0a654e3 100644 --- a/test/general/armor.js +++ b/test/general/armor.js @@ -117,7 +117,7 @@ describe("ASCII armor", function() { ['-----BEGIN PGP SIGNED MESSAGE\u2010\u2010\u2010\u2010\u2010\nHash:SHA1\n\nIs this properly-----', '', 'sign this', - '-----BEGIN PGP SIGNATURE-----', + '-----BEGIN PGP SIGNNATURE-----', 'Version: GnuPG v2.0.22 (GNU/Linux)', '', 'iJwEAQECAAYFAlMrPj0ACgkQ4IT3RGwgLJfYkQQAgHMQieazCVdfGAfzQM69Egm5', @@ -125,7 +125,7 @@ describe("ASCII armor", function() { 'LQ9DiQUwJMBE8nOwVR7Mpc4kLNngMTNaHAjZaVaDpTCrklPY+TPHIZnu0B6Ur+6t', 'skTzzVXIxMYw8ihbHfk=', '=e/eA', - '-----END PGP SIGNATURE-----'].join('\n'); + '-----END PGP SIGNNATURE-----'].join('\n'); msg = openpgp.cleartext.readArmored.bind(null, msg); expect(msg).to.throw(Error, /Unknow ASCII armor type/); diff --git a/test/general/signature.js b/test/general/signature.js index 65a2c509..1da22c0e 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -590,4 +590,50 @@ describe("Signature", function() { expect(pubKey.users[0].selfCertifications).to.eql(pubKey2.users[0].selfCertifications); }); + it('Verify a detached signature', function() { + var detachedSig = ['-----BEGIN PGP SIGNATURE-----', + 'Version: GnuPG v1.4.13 (Darwin)', + 'Comment: GPGTools - https://gpgtools.org', + 'Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/', + '', + 'iQEcBAEBCgAGBQJTqH5OAAoJENf7k/zfv8I8oFoH/R6EFTw2CYUQoOKSAQstWIHp', + 'fVVseLOkFbByUV5eLuGVBNI3DM4GQ6C7dGntKAn34a1iTGcAIZH+fIhaZ2WtNdtA', + 'R+Ijn8xDjbF/BWvcTBOaRvgw9b8viPxhkVYa3PioHYz6krt/LmFqFdp/phWZcqR4', + 'jzWMX55h4FOw3YBNGiz2NuIg+iGrFRWPYgd8NVUmJKReZHs8C/6HGz7F4/A24k6Y', + '7xms9D6Er+MhspSl+1dlRdHjtXiRqC5Ld1hi2KBKc6YzgOLpVw5l9sffbnH+aRG4', + 'dH+2J5U3elqBDK1i3GyG8ixLSB0FGW9+lhYNosZne2xy8SbQKdgsnTBnWSGevP0=', + '=xiih', + '-----END PGP SIGNATURE-----' + ].join('\r\n'); + + var content = ['Content-Type: multipart/mixed;', + ' boundary="------------070307080002050009010403"', + '', + 'This is a multi-part message in MIME format.', + '--------------070307080002050009010403', + 'Content-Type: text/plain; charset=ISO-8859-1', + 'Content-Transfer-Encoding: quoted-printable', + '', + 'test11', + '', + '--------------070307080002050009010403', + 'Content-Type: application/macbinary;', + ' name="test.bin"', + 'Content-Transfer-Encoding: base64', + 'Content-Disposition: attachment;', + ' filename="test.bin"', + '', + 'dGVzdGF0dGFjaG1lbnQ=', + '--------------070307080002050009010403--', + '' + ].join('\r\n'); + + var publicKeyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v.1.20131116\r\nComment: Whiteout Mail - http://whiteout.io\r\n\r\nxsBNBFKODs4BB/9iOF4THsjQMY+WEpT7ShgKxj4bHzRRaQkqczS4nZvP0U3g\r\nqeqCnbpagyeKXA+bhWFQW4GmXtgAoeD5PXs6AZYrw3tWNxLKu2Oe6Tp9K/XI\r\nxTMQ2wl4qZKDXHvuPsJ7cmgaWqpPyXtxA4zHHS3WrkI/6VzHAcI/y6x4szSB\r\nKgSuhI3hjh3s7TybUC1U6AfoQGx/S7e3WwlCOrK8GTClirN/2mCPRC5wuIft\r\nnkoMfA6jK8d2OPrJ63shy5cgwHOjQg/xuk46dNS7tkvGmbaa+X0PgqSKB+Hf\r\nYPPNS/ylg911DH9qa8BqYU2QpNh9jUKXSF+HbaOM+plWkCSAL7czV+R3ABEB\r\nAAHNLVdoaXRlb3V0IFVzZXIgPHNhZmV3aXRobWUudGVzdHVzZXJAZ21haWwu\r\nY29tPsLAXAQQAQgAEAUCUo4O2gkQ1/uT/N+/wjwAAN2cB/9gFRmAfvEQ2qz+\r\nWubmT2EsSSnjPMxzG4uyykFoa+TaZCWo2Xa2tQghmU103kEkQb1OEjRjpgwJ\r\nYX9Kghnl8DByM686L5AXnRyHP78qRJCLXSXl0AGicboUDp5sovaa4rswQceH\r\nvcdWgZ/mgHTRoiQeJddy9k+H6MPFiyFaVcFwegVsmpc+dCcC8yT+qh8ZIbyG\r\nRJU60PmKKN7LUusP+8DbSv39zCGJCBlVVKyA4MzdF5uM+sqTdXbKzOrT5DGd\r\nCZaox4s+w16Sq1rHzZKFWfQPfKLDB9pyA0ufCVRA3AF6BUi7G3ZqhZiHNhMP\r\nNvE45V/hS1PbZcfPVoUjE2qc1Ix1\r\n=7Wpe\r\n-----END PGP PUBLIC KEY BLOCK-----'; + var publicKeys = openpgp.key.readArmored(publicKeyArmored).keys; + + var msg = openpgp.message.readSignedContent(content, detachedSig); + var result = msg.verify(publicKeys); + expect(result[0].valid).to.be.true; + }); + });