From b20c6977caf0bb8b7f71cf4422e25effa9291e3f Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 1 Jul 2014 20:58:34 +0200 Subject: [PATCH 1/2] [WO-437] Allow users to import only the private PGP key block --- src/js/controller/login-new-device.js | 23 +++++++++++++---------- src/js/crypto/pgp.js | 11 +++++++++++ test/unit/login-new-device-ctrl-test.js | 3 ++- test/unit/pgp-test.js | 8 ++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/js/controller/login-new-device.js b/src/js/controller/login-new-device.js index bac997a..fcc6c94 100644 --- a/src/js/controller/login-new-device.js +++ b/src/js/controller/login-new-device.js @@ -26,6 +26,17 @@ define(function(require) { keypair = keypair || {}; + // extract public key from private key block if missing in key file + if (!$scope.key.publicKeyArmored || $scope.key.publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) { + try { + $scope.key.publicKeyArmored = pgp.extractPublicKey($scope.key.privateKeyArmored); + } catch (e) { + $scope.onError(new Error('Error parsing public key from private key!')); + return; + } + } + + // parse keypair params var privKeyParams, pubKeyParams; try { privKeyParams = pgp.getKeyParams($scope.key.privateKeyArmored); @@ -93,14 +104,11 @@ define(function(require) { reader.onload = function(e) { var rawKeys = e.target.result, - privKeyPrexix = '-----BEGIN PGP PRIVATE KEY BLOCK-----', - pubKeyPrefix = '-----BEGIN PGP PUBLIC KEY BLOCK-----', - index = rawKeys.indexOf(privKeyPrexix), - errMsg = 'Keyfile must be formatted like so:\n' + pubKeyPrefix + '\n ... \n' + privKeyPrexix, + index = rawKeys.indexOf('-----BEGIN PGP PRIVATE KEY BLOCK-----'), keyParts; if (index === -1) { - scope.onError(new Error(errMsg)); + scope.onError(new Error('Error parsing private PGP key block!')); return; } @@ -109,11 +117,6 @@ define(function(require) { privateKeyArmored: rawKeys.substring(index, rawKeys.length).trim() }; - if (keyParts.publicKeyArmored.indexOf(pubKeyPrefix) < 0 || keyParts.privateKeyArmored.indexOf(privKeyPrexix) < 0) { - scope.onError(new Error(errMsg)); - return; - } - scope.$apply(function() { scope.key = keyParts; }); diff --git a/src/js/crypto/pgp.js b/src/js/crypto/pgp.js index c006e06..f3c2218 100644 --- a/src/js/crypto/pgp.js +++ b/src/js/crypto/pgp.js @@ -133,6 +133,17 @@ define(function(require) { }; }; + /** + * Extract a public key from a private key + * @param {String} privateKeyArmored The private PGP key block + * @return {String} The publick PGP key block + */ + PGP.prototype.extractPublicKey = function(privateKeyArmored) { + var privkey = openpgp.key.readArmored(privateKeyArmored).keys[0]; + var pubkey = privkey.toPublic(); + return pubkey.armor(); + }; + /** * Import the user's key pair */ diff --git a/test/unit/login-new-device-ctrl-test.js b/test/unit/login-new-device-ctrl-test.js index 83ad0a9..3d9b48e 100644 --- a/test/unit/login-new-device-ctrl-test.js +++ b/test/unit/login-new-device-ctrl-test.js @@ -26,7 +26,8 @@ define(function(require) { keyId = '9FEB47936E712926'; emailDaoMock._keychain = keychainMock = sinon.createStubInstance(KeychainDAO); - appController._crypto = pgpMock = sinon.createStubInstance(PGP); + appController._pgp = pgpMock = sinon.createStubInstance(PGP); + pgpMock.extractPublicKey.returns('publicKeyArmored'); emailDaoMock._account = { emailAddress: emailAddress, diff --git a/test/unit/pgp-test.js b/test/unit/pgp-test.js index 0c0a5f5..4aee180 100644 --- a/test/unit/pgp-test.js +++ b/test/unit/pgp-test.js @@ -262,6 +262,14 @@ define(function(require) { }); }); + describe('extractPublicKey', function() { + it('should work', function() { + var pk = pgp.extractPublicKey(privkey); + expect(pk).to.exist; + expect(pk).to.contain('-----BEGIN PGP PUBLIC KEY BLOCK-----'); + }); + }); + describe('Encrypt and sign', function() { it('should fail', function(done) { var input = null; From 5aec80da474d546e2ff7ea2d89c78eefea3e32e3 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 1 Jul 2014 20:59:10 +0200 Subject: [PATCH 2/2] Fix appController._pgp mocking in read controller test --- test/unit/read-ctrl-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/read-ctrl-test.js b/test/unit/read-ctrl-test.js index 9875371..893fbc1 100644 --- a/test/unit/read-ctrl-test.js +++ b/test/unit/read-ctrl-test.js @@ -26,8 +26,8 @@ define(function(require) { origInvitation = appController._invitationDao; appController._invitationDao = invitationMock = sinon.createStubInstance(InvitationDAO); - origCrypto = appController._crypto; - appController._crypto = cryptoMock = sinon.createStubInstance(PGP); + origCrypto = appController._pgp; + appController._pgp = cryptoMock = sinon.createStubInstance(PGP); origOutbox = appController._outboxBo; appController._outboxBo = outboxMock = sinon.createStubInstance(OutboxBO); @@ -51,7 +51,7 @@ define(function(require) { afterEach(function() { appController._keychain = origKeychain; appController._invitationDao = origInvitation; - appController._crypto = origCrypto; + appController._pgp = origCrypto; appController._outboxBo = origOutbox; appController._emailDao = origEmailDao; });