From 28e5f5d3f408e1943924f1abfb6d12ad262d8314 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Tue, 4 Jul 2017 14:15:39 -0700 Subject: [PATCH 1/7] allow cleartext msg data to be string or byte array --- src/cleartext.js | 54 +++++++++++++++++++++++++++++++++-------- src/openpgp.js | 11 ++++++--- src/packet/signature.js | 2 +- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/cleartext.js b/src/cleartext.js index e9ab668e..9e6f1be9 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -28,7 +28,9 @@ import config from './config'; import packet from './packet'; import enums from './enums.js'; +import util from './util'; import armor from './encoding/armor.js'; +import base64 from './encoding/base64.js'; import * as sigModule from './signature.js'; /** @@ -39,12 +41,16 @@ import * as sigModule from './signature.js'; * @param {module:signature} signature The detached signature or an empty signature if message not yet signed */ -export function CleartextMessage(text, signature) { +export function CleartextMessage(data, signature) { if (!(this instanceof CleartextMessage)) { - return new CleartextMessage(text, signature); + return new CleartextMessage(data, signature); + } + if (util.isString(data)) { + // normalize EOL to canonical form + this.text = data.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); + } else { + this.bytes = data; } - // normalize EOL to canonical form - this.text = text.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); if (signature && !(signature instanceof sigModule.Signature)) { throw new Error('Invalid signature input'); } @@ -80,7 +86,11 @@ CleartextMessage.prototype.sign = function(privateKeys) { CleartextMessage.prototype.signDetached = function(privateKeys) { var packetlist = new packet.List(); var literalDataPacket = new packet.Literal(); - literalDataPacket.setText(this.text); + if (this.text) { + literalDataPacket.setText(this.text); + } else { + literalDataPacket.setBytes(this.bytes, enums.read(enums.literal, enums.literal.binary)); + } for (var i = 0; i < privateKeys.length; i++) { if (privateKeys[i].isPublic()) { throw new Error('Need private key for signing'); @@ -118,7 +128,11 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) { var signatureList = signature.packets; var literalDataPacket = new packet.Literal(); // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); + if (this.text) { + literalDataPacket.setText(this.text); + } else { + literalDataPacket.setBytes(this.bytes, enums.read(enums.literal, enums.literal.binary)); + } for (var i = 0; i < signatureList.length; i++) { var keyPacket = null; for (var j = 0; j < keys.length; j++) { @@ -144,7 +158,7 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) { }; /** - * Get cleartext + * Get cleartext as native JavaScript string * @return {String} cleartext of message */ CleartextMessage.prototype.getText = function() { @@ -152,6 +166,14 @@ CleartextMessage.prototype.getText = function() { return this.text.replace(/\r\n/g,"\n"); }; +/** + * Get cleartext as byte array + * @returns {Uint8Array} A sequence of bytes + */ +CleartextMessage.prototype.getBytes = function() { + return this.bytes; +}; + /** * Returns ASCII armored text of cleartext signed message * @return {String} ASCII armor @@ -159,9 +181,14 @@ CleartextMessage.prototype.getText = function() { CleartextMessage.prototype.armor = function() { var body = { hash: enums.read(enums.hash, config.prefer_hash_algorithm).toUpperCase(), - text: this.text, data: this.signature.packets.write() }; + + if (this.text) { + body.text = this.text; + } else { + body.bytes = this.bytes; + } return armor.encode(enums.armor.signed, body); }; @@ -169,10 +196,11 @@ CleartextMessage.prototype.armor = function() { /** * reads an OpenPGP cleartext signed message and returns a CleartextMessage object * @param {String} armoredText text to be parsed + * @param {bool} whether the decoded cleartext message should be returned as a string (alternative is a byte array) * @return {module:cleartext~CleartextMessage} new cleartext message object * @static */ -export function readArmored(armoredText) { +export function readArmored(armoredText, isText=true) { var input = armor.decode(armoredText); if (input.type !== enums.armor.signed) { throw new Error('No cleartext signed message.'); @@ -181,7 +209,13 @@ export function readArmored(armoredText) { packetlist.read(input.data); verifyHeaders(input.headers, packetlist); var signature = new sigModule.Signature(packetlist); - var newMessage = new CleartextMessage(input.text, signature); + var cleartext; + if (isText) { + cleartext = input.cleartext.replace(/\n$/, '').replace(/\n/g, "\r\n"); + } else { + cleartext = base64.decode(input.cleartext); + } + var newMessage = new CleartextMessage(cleartext, signature); return newMessage; } diff --git a/src/openpgp.js b/src/openpgp.js index d523d5d4..57fea8f1 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -273,7 +273,7 @@ export function decrypt({ message, privateKey, publicKeys, sessionKey, password, /** * Signs a cleartext message. - * @param {String} data cleartext input to be signed + * @param {String | Uint8Array} data cleartext input to be signed * @param {Key|Array} 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 * @param {Boolean} detached (optional) if the return value should contain a detached signature @@ -283,7 +283,7 @@ export function decrypt({ message, privateKey, publicKeys, sessionKey, password, * @static */ export function sign({ data, privateKeys, armor=true, detached=false}) { - checkString(data); + checkData(data); privateKeys = toArray(privateKeys); if (asyncProxy) { // use web worker if available @@ -294,7 +294,6 @@ export function sign({ data, privateKeys, armor=true, detached=false}) { return execute(() => { const cleartextMessage = new cleartext.CleartextMessage(data); - if (detached) { var signature = cleartextMessage.signDetached(privateKeys); if (armor) { @@ -335,7 +334,11 @@ export function verify({ message, publicKeys, signature=null }) { var result = {}; return execute(() => { - result.data = message.getText(); + if (message.text) { + result.data = message.getText(); + } else { + result.data = message.getBytes(); + } if (signature) { //detached signature diff --git a/src/packet/signature.js b/src/packet/signature.js index f8639894..25e545c9 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -226,7 +226,7 @@ Signature.prototype.sign = function (key, data) { var trailer = this.calculateTrailer(); - var toHash = null + var toHash = null; switch (this.version) { case 3: From a9bb3f1839bf17095ae03fc61ee30c0f3d8a61a5 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Tue, 4 Jul 2017 16:47:23 -0700 Subject: [PATCH 2/7] armor based on text vs. bytes --- src/cleartext.js | 23 ++++++++++++++++------- src/encoding/armor.js | 8 ++++++-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/cleartext.js b/src/cleartext.js index 9e6f1be9..b4b9c3ee 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -37,7 +37,7 @@ import * as sigModule from './signature.js'; * @class * @classdesc Class that represents an OpenPGP cleartext signed message. * See {@link http://tools.ietf.org/html/rfc4880#section-7} - * @param {String} text The cleartext of the signed message + * @param {String | Uint8Array} data The cleartext of the signed message * @param {module:signature} signature The detached signature or an empty signature if message not yet signed */ @@ -162,8 +162,12 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) { * @return {String} cleartext of message */ CleartextMessage.prototype.getText = function() { - // normalize end of line to \n - return this.text.replace(/\r\n/g,"\n"); + if (this.text) { + // normalize end of line to \n + return this.text.replace(/\r\n/g,"\n"); + } else { + return util.Uint8Array2str(this.bytes); + } }; /** @@ -171,6 +175,11 @@ CleartextMessage.prototype.getText = function() { * @returns {Uint8Array} A sequence of bytes */ CleartextMessage.prototype.getBytes = function() { + if (this.bytes) { + return this.bytes; + } else { + return util.str2Uint8Array(this.text.replace(/\r\n/g,"\n")); + } return this.bytes; }; @@ -200,7 +209,7 @@ CleartextMessage.prototype.armor = function() { * @return {module:cleartext~CleartextMessage} new cleartext message object * @static */ -export function readArmored(armoredText, isText=true) { +export function readArmored(armoredText, bytes=false) { var input = armor.decode(armoredText); if (input.type !== enums.armor.signed) { throw new Error('No cleartext signed message.'); @@ -210,10 +219,10 @@ export function readArmored(armoredText, isText=true) { verifyHeaders(input.headers, packetlist); var signature = new sigModule.Signature(packetlist); var cleartext; - if (isText) { - cleartext = input.cleartext.replace(/\n$/, '').replace(/\n/g, "\r\n"); - } else { + if (bytes) { cleartext = base64.decode(input.cleartext); + } else { + cleartext = input.cleartext.replace(/\n$/, '').replace(/\n/g, "\r\n"); } var newMessage = new CleartextMessage(cleartext, signature); return newMessage; diff --git a/src/encoding/armor.js b/src/encoding/armor.js index 9dcbe891..4db897d0 100644 --- a/src/encoding/armor.js +++ b/src/encoding/armor.js @@ -300,7 +300,7 @@ function dearmor(text) { var sig_sum = splitChecksum(sig.body); result = { - text: msg.body.replace(/\n$/, '').replace(/\n/g, "\r\n"), + cleartext: msg.body, data: base64.decode(sig_sum.body), headers: msg.headers, type: type @@ -353,7 +353,11 @@ function armor(messagetype, body, partindex, parttotal) { case enums.armor.signed: result.push("\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"); result.push("Hash: " + body.hash + "\r\n\r\n"); - result.push(body.text.replace(/\n-/g, "\n- -")); + if (body.text) { + result.push(body.text.replace(/\n-/g, "\n- -")); + } else { + result.push(base64.encode(body.bytes)); + } result.push("\r\n-----BEGIN PGP SIGNATURE-----\r\n"); result.push(addheader()); result.push(base64.encode(body.data)); From 697eab19cd8ba01a710912740024b1c4b2fcce2d Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Tue, 4 Jul 2017 17:03:56 -0700 Subject: [PATCH 3/7] add tests --- test/general/signature.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/general/signature.js b/test/general/signature.js index dacc59da..ff0bd761 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -527,7 +527,7 @@ describe("Signature", function() { }); }); - it('Sign text with openpgp.sign and verify with openpgp.verify leads to same cleartext and valid signatures', function(done) { + it('Sign text with openpgp.sign and verify with openpgp.verify leads to same string cleartext and valid signatures - armored', function(done) { var plaintext = 'short message\nnext line\n한국어/조선말'; var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; @@ -549,6 +549,28 @@ describe("Signature", function() { }); + it('Sign text with openpgp.sign and verify with openpgp.verify leads to same bytes cleartext and valid signatures - not armored', function(done) { + var plaintext = openpgp.util.str2Uint8Array('short message\nnext line\n한국어/조선말'); + var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; + var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; + privKey.getSigningKeyPacket().decrypt('hello world'); + + openpgp.sign({ privateKeys:[privKey], data:plaintext, armor:false }).then(function(signed) { + + var csMsg = signed.message; + return openpgp.verify({ publicKeys:[pubKey], message:csMsg }); + + }).then(function(cleartextSig) { + expect(cleartextSig).to.exist; + expect(cleartextSig.data).to.deep.equal(plaintext); + 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); + done(); + }); + + }); + it('Verify primary key revocation signature', function(done) { var pubKey = openpgp.key.readArmored(pub_revoked).keys[0]; From cc831cde4a81a17ceaed1e0a1da594afdfea6b4e Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Tue, 4 Jul 2017 21:08:48 -0700 Subject: [PATCH 4/7] more tests --- test/general/signature.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/general/signature.js b/test/general/signature.js index ff0bd761..3252d7c7 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -527,7 +527,7 @@ describe("Signature", function() { }); }); - it('Sign text with openpgp.sign and verify with openpgp.verify leads to same string cleartext and valid signatures - armored', function(done) { + it('Sign text with openpgp.sign and verify with openpgp.verify leads to same string cleartext and valid signatures', function(done) { var plaintext = 'short message\nnext line\n한국어/조선말'; var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; @@ -549,6 +549,28 @@ describe("Signature", function() { }); + it('Sign text with openpgp.sign and verify with openpgp.verify leads to same bytes cleartext and valid signatures - armored', function(done) { + var plaintext = openpgp.util.str2Uint8Array('short message\nnext line\n한국어/조선말'); + var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; + var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; + privKey.getSigningKeyPacket().decrypt('hello world'); + + openpgp.sign({ privateKeys:[privKey], data:plaintext }).then(function(signed) { + + var csMsg = openpgp.cleartext.readArmored(signed.data, true); + return openpgp.verify({ publicKeys:[pubKey], message:csMsg }); + + }).then(function(cleartextSig) { + expect(cleartextSig).to.exist; + expect(cleartextSig.data).to.deep.equal(plaintext); + 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); + done(); + }); + + }); + it('Sign text with openpgp.sign and verify with openpgp.verify leads to same bytes cleartext and valid signatures - not armored', function(done) { var plaintext = openpgp.util.str2Uint8Array('short message\nnext line\n한국어/조선말'); var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; From d061af1fc32e66230d09040e98f275de8909c0d6 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Thu, 6 Jul 2017 16:29:25 +0200 Subject: [PATCH 5/7] style fixes --- src/cleartext.js | 23 +++++++++++------------ src/encoding/armor.js | 2 +- src/openpgp.js | 1 + 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cleartext.js b/src/cleartext.js index b4b9c3ee..79e67001 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -37,19 +37,19 @@ import * as sigModule from './signature.js'; * @class * @classdesc Class that represents an OpenPGP cleartext signed message. * See {@link http://tools.ietf.org/html/rfc4880#section-7} - * @param {String | Uint8Array} data The cleartext of the signed message + * @param {String | Uint8Array} content The cleartext of the signed message * @param {module:signature} signature The detached signature or an empty signature if message not yet signed */ -export function CleartextMessage(data, signature) { +export function CleartextMessage(content, signature) { if (!(this instanceof CleartextMessage)) { - return new CleartextMessage(data, signature); + return new CleartextMessage(content, signature); } - if (util.isString(data)) { + if (util.isString(content)) { // normalize EOL to canonical form - this.text = data.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); + this.text = content.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); } else { - this.bytes = data; + this.bytes = content; } if (signature && !(signature instanceof sigModule.Signature)) { throw new Error('Invalid signature input'); @@ -180,7 +180,6 @@ CleartextMessage.prototype.getBytes = function() { } else { return util.str2Uint8Array(this.text.replace(/\r\n/g,"\n")); } - return this.bytes; }; /** @@ -205,7 +204,7 @@ CleartextMessage.prototype.armor = function() { /** * reads an OpenPGP cleartext signed message and returns a CleartextMessage object * @param {String} armoredText text to be parsed - * @param {bool} whether the decoded cleartext message should be returned as a string (alternative is a byte array) + * @param {bool} whether the decoded cleartext message should be returned as a byte array (default is string) * @return {module:cleartext~CleartextMessage} new cleartext message object * @static */ @@ -218,13 +217,13 @@ export function readArmored(armoredText, bytes=false) { packetlist.read(input.data); verifyHeaders(input.headers, packetlist); var signature = new sigModule.Signature(packetlist); - var cleartext; + var content; if (bytes) { - cleartext = base64.decode(input.cleartext); + content = base64.decode(input.content); } else { - cleartext = input.cleartext.replace(/\n$/, '').replace(/\n/g, "\r\n"); + content = input.content.replace(/\n$/, '').replace(/\n/g, "\r\n"); } - var newMessage = new CleartextMessage(cleartext, signature); + var newMessage = new CleartextMessage(content, signature); return newMessage; } diff --git a/src/encoding/armor.js b/src/encoding/armor.js index 4db897d0..1700cd2c 100644 --- a/src/encoding/armor.js +++ b/src/encoding/armor.js @@ -300,7 +300,7 @@ function dearmor(text) { var sig_sum = splitChecksum(sig.body); result = { - cleartext: msg.body, + content: msg.body, data: base64.decode(sig_sum.body), headers: msg.headers, type: type diff --git a/src/openpgp.js b/src/openpgp.js index 57fea8f1..19d907a1 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -294,6 +294,7 @@ export function sign({ data, privateKeys, armor=true, detached=false}) { return execute(() => { const cleartextMessage = new cleartext.CleartextMessage(data); + if (detached) { var signature = cleartextMessage.signDetached(privateKeys); if (armor) { From 95c5e3af0176c6ef67f6b5c7f401273e8b87ac77 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Sat, 8 Jul 2017 13:25:24 +0200 Subject: [PATCH 6/7] use message obj when signing uint8 array --- src/cleartext.js | 71 +++++++++------------------------------ src/encoding/armor.js | 8 ++--- src/openpgp.js | 32 ++++++++++-------- test/general/signature.js | 6 ++-- 4 files changed, 39 insertions(+), 78 deletions(-) diff --git a/src/cleartext.js b/src/cleartext.js index 79e67001..c6e74a33 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -28,29 +28,24 @@ import config from './config'; import packet from './packet'; import enums from './enums.js'; -import util from './util'; import armor from './encoding/armor.js'; -import base64 from './encoding/base64.js'; import * as sigModule from './signature.js'; /** * @class * @classdesc Class that represents an OpenPGP cleartext signed message. * See {@link http://tools.ietf.org/html/rfc4880#section-7} - * @param {String | Uint8Array} content The cleartext of the signed message + * @param {String} text The cleartext of the signed message * @param {module:signature} signature The detached signature or an empty signature if message not yet signed */ -export function CleartextMessage(content, signature) { +export function CleartextMessage(text, signature) { if (!(this instanceof CleartextMessage)) { - return new CleartextMessage(content, signature); - } - if (util.isString(content)) { - // normalize EOL to canonical form - this.text = content.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); - } else { - this.bytes = content; + return new CleartextMessage(text, signature); } + // normalize EOL to canonical form + this.text = text.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); + if (signature && !(signature instanceof sigModule.Signature)) { throw new Error('Invalid signature input'); } @@ -73,9 +68,10 @@ CleartextMessage.prototype.getSigningKeyIds = function() { /** * Sign the cleartext message * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @return {module:message~CleartextMessage} new cleartext message with signed content */ CleartextMessage.prototype.sign = function(privateKeys) { - this.signature = this.signDetached(privateKeys); + return new CleartextMessage(this.text, this.signDetached(privateKeys)); }; /** @@ -86,11 +82,7 @@ CleartextMessage.prototype.sign = function(privateKeys) { CleartextMessage.prototype.signDetached = function(privateKeys) { var packetlist = new packet.List(); var literalDataPacket = new packet.Literal(); - if (this.text) { - literalDataPacket.setText(this.text); - } else { - literalDataPacket.setBytes(this.bytes, enums.read(enums.literal, enums.literal.binary)); - } + literalDataPacket.setText(this.text); for (var i = 0; i < privateKeys.length; i++) { if (privateKeys[i].isPublic()) { throw new Error('Need private key for signing'); @@ -128,11 +120,7 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) { var signatureList = signature.packets; var literalDataPacket = new packet.Literal(); // we assume that cleartext signature is generated based on UTF8 cleartext - if (this.text) { - literalDataPacket.setText(this.text); - } else { - literalDataPacket.setBytes(this.bytes, enums.read(enums.literal, enums.literal.binary)); - } + literalDataPacket.setText(this.text); for (var i = 0; i < signatureList.length; i++) { var keyPacket = null; for (var j = 0; j < keys.length; j++) { @@ -158,28 +146,12 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) { }; /** - * Get cleartext as native JavaScript string + * Get cleartext * @return {String} cleartext of message */ CleartextMessage.prototype.getText = function() { - if (this.text) { - // normalize end of line to \n - return this.text.replace(/\r\n/g,"\n"); - } else { - return util.Uint8Array2str(this.bytes); - } -}; - -/** - * Get cleartext as byte array - * @returns {Uint8Array} A sequence of bytes - */ -CleartextMessage.prototype.getBytes = function() { - if (this.bytes) { - return this.bytes; - } else { - return util.str2Uint8Array(this.text.replace(/\r\n/g,"\n")); - } + // normalize end of line to \n + return this.text.replace(/\r\n/g,"\n"); }; /** @@ -189,14 +161,10 @@ CleartextMessage.prototype.getBytes = function() { CleartextMessage.prototype.armor = function() { var body = { hash: enums.read(enums.hash, config.prefer_hash_algorithm).toUpperCase(), + text: this.text, data: this.signature.packets.write() }; - if (this.text) { - body.text = this.text; - } else { - body.bytes = this.bytes; - } return armor.encode(enums.armor.signed, body); }; @@ -204,11 +172,10 @@ CleartextMessage.prototype.armor = function() { /** * reads an OpenPGP cleartext signed message and returns a CleartextMessage object * @param {String} armoredText text to be parsed - * @param {bool} whether the decoded cleartext message should be returned as a byte array (default is string) * @return {module:cleartext~CleartextMessage} new cleartext message object * @static */ -export function readArmored(armoredText, bytes=false) { +export function readArmored(armoredText) { var input = armor.decode(armoredText); if (input.type !== enums.armor.signed) { throw new Error('No cleartext signed message.'); @@ -217,13 +184,7 @@ export function readArmored(armoredText, bytes=false) { packetlist.read(input.data); verifyHeaders(input.headers, packetlist); var signature = new sigModule.Signature(packetlist); - var content; - if (bytes) { - content = base64.decode(input.content); - } else { - content = input.content.replace(/\n$/, '').replace(/\n/g, "\r\n"); - } - var newMessage = new CleartextMessage(content, signature); + var newMessage = new CleartextMessage(input.text, signature); return newMessage; } diff --git a/src/encoding/armor.js b/src/encoding/armor.js index 1700cd2c..9dcbe891 100644 --- a/src/encoding/armor.js +++ b/src/encoding/armor.js @@ -300,7 +300,7 @@ function dearmor(text) { var sig_sum = splitChecksum(sig.body); result = { - content: msg.body, + text: msg.body.replace(/\n$/, '').replace(/\n/g, "\r\n"), data: base64.decode(sig_sum.body), headers: msg.headers, type: type @@ -353,11 +353,7 @@ function armor(messagetype, body, partindex, parttotal) { case enums.armor.signed: result.push("\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"); result.push("Hash: " + body.hash + "\r\n\r\n"); - if (body.text) { - result.push(body.text.replace(/\n-/g, "\n- -")); - } else { - result.push(base64.encode(body.bytes)); - } + result.push(body.text.replace(/\n-/g, "\n- -")); result.push("\r\n-----BEGIN PGP SIGNATURE-----\r\n"); result.push(addheader()); result.push(base64.encode(body.data)); diff --git a/src/openpgp.js b/src/openpgp.js index 19d907a1..5a2a5e5a 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -292,24 +292,29 @@ export function sign({ data, privateKeys, armor=true, detached=false}) { var result = {}; return execute(() => { + var message; - const cleartextMessage = new cleartext.CleartextMessage(data); + if (util.isString(data)) { + message = new cleartext.CleartextMessage(data); + } else { + message = messageLib.fromBinary(data); + } if (detached) { - var signature = cleartextMessage.signDetached(privateKeys); + var signature = message.signDetached(privateKeys); if (armor) { result.signature = signature.armor(); } else { result.signature = signature; } } else { - cleartextMessage.sign(privateKeys); + message = message.sign(privateKeys); } if (armor) { - result.data = cleartextMessage.armor(); + result.data = message.armor(); } else { - result.message = cleartextMessage; + result.message = message; } return result; @@ -326,7 +331,7 @@ export function sign({ data, privateKeys, armor=true, detached=false}) { * @static */ export function verify({ message, publicKeys, signature=null }) { - checkCleartextMessage(message); + checkCleartextOrMessage(message); publicKeys = toArray(publicKeys); if (asyncProxy) { // use web worker if available @@ -335,12 +340,11 @@ export function verify({ message, publicKeys, signature=null }) { var result = {}; return execute(() => { - if (message.text) { + if (cleartext.CleartextMessage.prototype.isPrototypeOf(message)) { result.data = message.getText(); } else { - result.data = message.getBytes(); + result.data = message.getLiteralData(); } - if (signature) { //detached signature result.signatures = message.verifyDetached(signature, publicKeys); @@ -371,7 +375,7 @@ export function verify({ message, publicKeys, signature=null }) { * @static */ export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) { - checkbinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); + checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); if (asyncProxy) { // use web worker if available return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords }); @@ -421,7 +425,7 @@ function checkString(data, name) { throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); } } -function checkbinary(data, name) { +function checkBinary(data, name) { if (!util.isUint8Array(data)) { throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); } @@ -436,9 +440,9 @@ function checkMessage(message) { throw new Error('Parameter [message] needs to be of type Message'); } } -function checkCleartextMessage(message) { - if (!cleartext.CleartextMessage.prototype.isPrototypeOf(message)) { - throw new Error('Parameter [message] needs to be of type CleartextMessage'); +function checkCleartextOrMessage(message) { + if (!cleartext.CleartextMessage.prototype.isPrototypeOf(message) && !messageLib.Message.prototype.isPrototypeOf(message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); } } diff --git a/test/general/signature.js b/test/general/signature.js index 3252d7c7..254ce574 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -554,10 +554,11 @@ describe("Signature", function() { var pubKey = openpgp.key.readArmored(pub_key_arm2).keys[0]; var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0]; privKey.getSigningKeyPacket().decrypt('hello world'); + console.log(pubKey.armor()); openpgp.sign({ privateKeys:[privKey], data:plaintext }).then(function(signed) { - - var csMsg = openpgp.cleartext.readArmored(signed.data, true); + console.log(signed.data); + var csMsg = openpgp.message.readArmored(signed.data); return openpgp.verify({ publicKeys:[pubKey], message:csMsg }); }).then(function(cleartextSig) { @@ -578,7 +579,6 @@ describe("Signature", function() { privKey.getSigningKeyPacket().decrypt('hello world'); openpgp.sign({ privateKeys:[privKey], data:plaintext, armor:false }).then(function(signed) { - var csMsg = signed.message; return openpgp.verify({ publicKeys:[pubKey], message:csMsg }); From e53cbe8417e5fb28d948378c78c87655c98bce67 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Sat, 8 Jul 2017 13:26:20 +0200 Subject: [PATCH 7/7] remove extra spaces --- src/cleartext.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cleartext.js b/src/cleartext.js index c6e74a33..78a8de43 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -45,7 +45,6 @@ export function CleartextMessage(text, signature) { } // normalize EOL to canonical form this.text = text.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n"); - if (signature && !(signature instanceof sigModule.Signature)) { throw new Error('Invalid signature input'); } @@ -164,7 +163,6 @@ CleartextMessage.prototype.armor = function() { text: this.text, data: this.signature.packets.write() }; - return armor.encode(enums.armor.signed, body); };