From afc2c95238c7a3431a18292e926afbc50074adc5 Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Mon, 25 Apr 2016 00:54:16 +0200 Subject: [PATCH 1/6] Implement feature #443 --- src/key.js | 21 +++++++++++++++++++++ test/general/key.js | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/key.js b/src/key.js index dd261f8d..f2af4b44 100644 --- a/src/key.js +++ b/src/key.js @@ -365,6 +365,27 @@ Key.prototype.getEncryptionKeyPacket = function() { return null; }; +/** + * Encrypts all secret key and subkey packets + * @param {String} passphrase + * @return {Boolean} true if all key and subkey packets encrypted successfully + */ +Key.prototype.encrypt = function(passphrase) { + if (this.isPrivate()) { + var keys = this.getAllKeyPackets(); + for (var i = 0; i < keys.length; i++) { + try { + keys[i].encrypt(passphrase); + } catch (e) { + return false; + } + } + } else { + throw new Error("Nothing to encrypt in a public key"); + } + return true; +}; + /** * Decrypts all secret key and subkey packets * @param {String} passphrase diff --git a/test/general/key.js b/test/general/key.js index f5b342eb..22fc8b0a 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -706,5 +706,24 @@ var pgp_desktop_priv = }).catch(done); }); + it('Encrypt key with new passphrase', function(done) { + var userId = 'test '; + var opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + openpgp.generateKey(opt).then(function(key) { + key = key.key; + var armor1 = key.armor(); + var armor2 = key.armor(); + expect(armor1).to.equal(armor2); + expect(key.decrypt('passphrase')).to.be.true; + expect(key.encrypt('new_passphrase')).to.be.true; + expect(key.decrypt('passphrase')).to.be.false; + expect(key.decrypt('new_passphrase')).to.be.true; + var armor3 = key.armor(); + expect(armor3).to.not.equal(armor1); + done(); + }).catch(done); + }); + }); From 61470ad0682cdc7f5679f8f90fb1713ccc457710 Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Mon, 25 Apr 2016 18:35:50 +0200 Subject: [PATCH 2/6] Apply edits as suggested in review of pull #446 --- src/key.js | 7 +------ test/general/key.js | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/key.js b/src/key.js index f2af4b44..ecae8af0 100644 --- a/src/key.js +++ b/src/key.js @@ -374,16 +374,11 @@ Key.prototype.encrypt = function(passphrase) { if (this.isPrivate()) { var keys = this.getAllKeyPackets(); for (var i = 0; i < keys.length; i++) { - try { - keys[i].encrypt(passphrase); - } catch (e) { - return false; - } + keys[i].encrypt(passphrase); } } else { throw new Error("Nothing to encrypt in a public key"); } - return true; }; /** diff --git a/test/general/key.js b/test/general/key.js index 22fc8b0a..19c39e29 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -716,9 +716,13 @@ var pgp_desktop_priv = var armor2 = key.armor(); expect(armor1).to.equal(armor2); expect(key.decrypt('passphrase')).to.be.true; + expect(key.primaryKey.isDecrypted).to.be.true; expect(key.encrypt('new_passphrase')).to.be.true; + expect(key.primaryKey.isDecrypted).to.be.false; expect(key.decrypt('passphrase')).to.be.false; + expect(key.primaryKey.isDecrypted).to.be.false; expect(key.decrypt('new_passphrase')).to.be.true; + expect(key.primaryKey.isDecrypted).to.be.true; var armor3 = key.armor(); expect(armor3).to.not.equal(armor1); done(); From 1007637f3988b5ab2169e0a9aaa8f4d81daf372b Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Mon, 25 Apr 2016 18:35:57 +0200 Subject: [PATCH 3/6] Mark isDecrypted flag when the key is encrypted --- src/packet/secret_key.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index b7d5bdf3..5fb67b47 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -199,6 +199,7 @@ SecretKey.prototype.encrypt = function (passphrase) { arr.push(crypto.cfb.normalEncrypt(symmetric, key, cleartext, iv)); this.encrypted = util.concatUint8Array(arr); + this.isDecrypted = false; }; function produceEncryptionKey(s2k, passphrase, algorithm) { From a5fdc360624defb1b0b5b732f804ca21e080a73f Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Wed, 27 Apr 2016 16:06:52 +0200 Subject: [PATCH 4/6] Cleanup API for key.decrypt and align unit tests --- src/key.js | 3 --- test/general/key.js | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/key.js b/src/key.js index ecae8af0..641c8a17 100644 --- a/src/key.js +++ b/src/key.js @@ -368,7 +368,6 @@ Key.prototype.getEncryptionKeyPacket = function() { /** * Encrypts all secret key and subkey packets * @param {String} passphrase - * @return {Boolean} true if all key and subkey packets encrypted successfully */ Key.prototype.encrypt = function(passphrase) { if (this.isPrivate()) { @@ -376,8 +375,6 @@ Key.prototype.encrypt = function(passphrase) { for (var i = 0; i < keys.length; i++) { keys[i].encrypt(passphrase); } - } else { - throw new Error("Nothing to encrypt in a public key"); } }; diff --git a/test/general/key.js b/test/general/key.js index 19c39e29..34262885 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -717,7 +717,7 @@ var pgp_desktop_priv = expect(armor1).to.equal(armor2); expect(key.decrypt('passphrase')).to.be.true; expect(key.primaryKey.isDecrypted).to.be.true; - expect(key.encrypt('new_passphrase')).to.be.true; + key.encrypt('new_passphrase'); expect(key.primaryKey.isDecrypted).to.be.false; expect(key.decrypt('passphrase')).to.be.false; expect(key.primaryKey.isDecrypted).to.be.false; From 0d931271864670449865a0cb33153dd795d407ef Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Thu, 28 Apr 2016 15:59:55 +0200 Subject: [PATCH 5/6] Simplify code-flow of Key.encrypt --- src/key.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/key.js b/src/key.js index 641c8a17..a513856e 100644 --- a/src/key.js +++ b/src/key.js @@ -370,11 +370,13 @@ Key.prototype.getEncryptionKeyPacket = function() { * @param {String} passphrase */ Key.prototype.encrypt = function(passphrase) { - if (this.isPrivate()) { - var keys = this.getAllKeyPackets(); - for (var i = 0; i < keys.length; i++) { - keys[i].encrypt(passphrase); - } + if (!this.isPrivate()) { + throw new Error("Nothing to encrypt in a public key"); + } + + var keys = this.getAllKeyPackets(); + for (var i = 0; i < keys.length; i++) { + keys[i].encrypt(passphrase); } }; From 4e3937f1e25384ef293f8a4c754f45fa0e7408a5 Mon Sep 17 00:00:00 2001 From: evilaliv3 Date: Thu, 28 Apr 2016 17:40:14 +0200 Subject: [PATCH 6/6] Replace isDecrypted=false with keys[i].clearPrivateMPIs() --- src/key.js | 1 + src/packet/secret_key.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.js b/src/key.js index a513856e..2ba3b7bf 100644 --- a/src/key.js +++ b/src/key.js @@ -377,6 +377,7 @@ Key.prototype.encrypt = function(passphrase) { var keys = this.getAllKeyPackets(); for (var i = 0; i < keys.length; i++) { keys[i].encrypt(passphrase); + keys[i].clearPrivateMPIs(); } }; diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 5fb67b47..b7d5bdf3 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -199,7 +199,6 @@ SecretKey.prototype.encrypt = function (passphrase) { arr.push(crypto.cfb.normalEncrypt(symmetric, key, cleartext, iv)); this.encrypted = util.concatUint8Array(arr); - this.isDecrypted = false; }; function produceEncryptionKey(s2k, passphrase, algorithm) {