freedom-pgp-e2e
Advanced tools
Comparing version 0.6.1 to 0.6.2
150
dist/e2e.js
@@ -48,4 +48,3 @@ /*globals freedom, console, e2e, exports, ArrayBuffer, Uint8Array, Uint16Array, DataView*/ | ||
var mye2e = function(dispatchEvents) { | ||
this.pgpContext = new e2e.openpgp.ContextImpl(); | ||
this.pgpContext.armorOutput = false; | ||
this.pgpContext = null; | ||
this.pgpUser = null; | ||
@@ -64,3 +63,8 @@ }; | ||
return refreshBuffer(5000).then(store.prepareFreedom).then(function() { | ||
scope.pgpContext.setKeyRingPassphrase(passphrase); | ||
if (!scope.pgpContext) { | ||
scope.pgpContext = new e2e.openpgp.ContextImpl(); | ||
scope.pgpContext.armorOutput = false; | ||
} | ||
return scope.pgpContext.initializeKeyRing(passphrase); | ||
}).then(function() { | ||
if (e2e.async.Result.getValue( | ||
@@ -89,4 +93,8 @@ scope.pgpContext.searchPrivateKey(scope.pgpUser)).length === 0) { | ||
return this.clear().then(function() { | ||
if (!scope.pgpContext) { | ||
scope.pgpContext = new e2e.openpgp.ContextImpl(); | ||
scope.pgpContext.armorOutput = false; | ||
} | ||
scope.pgpContext.setKeyRingPassphrase(passphrase); | ||
return scope.importKey(privateKey, passphrase); | ||
return scope.importPrivKey(privateKey, passphrase); | ||
}).then(function() { | ||
@@ -122,11 +130,9 @@ if (e2e.async.Result.getValue( | ||
// http://tools.ietf.org/html/rfc4880#section-12.2 | ||
var importResult = e2e.async.Result.getValue( | ||
this.pgpContext.importKey(function(str, f) { | ||
f(''); | ||
}, publicKey)); | ||
var keyResult = e2e.async.Result.getValue( | ||
this.pgpContext.searchPublicKey(importResult[0])); | ||
return Promise.resolve({ | ||
'fingerprint': keyResult[0].key.fingerprintHex, | ||
'words': hex2words(keyResult[0].key.fingerprintHex) | ||
return this.pgpContext.getKeyDescription(publicKey).then( | ||
function(keyDescriptions) { | ||
var fingerprint = keyDescriptions[0].key.fingerprintHex; | ||
return { | ||
'fingerprint': fingerprint, | ||
'words': hex2words(fingerprint) | ||
}; | ||
}); | ||
@@ -136,2 +142,3 @@ }; | ||
mye2e.prototype.signEncrypt = function(data, encryptKey, sign) { | ||
var scope = this; | ||
var pgp = this.pgpContext; | ||
@@ -143,8 +150,10 @@ var user = this.pgpUser; | ||
} | ||
var importResult = e2e.async.Result.getValue( | ||
pgp.importKey(function(str, f) { | ||
f(''); | ||
}, encryptKey)); | ||
var keys = e2e.async.Result.getValue( | ||
pgp.searchPublicKey(importResult[0])); | ||
var keys = Promise.resolve([]); | ||
if (encryptKey) { | ||
keys = scope.importPubKey(encryptKey).then(function(key) { | ||
return [key]; | ||
}); | ||
} | ||
return keys; | ||
}).then(function(keys) { | ||
var signKey; | ||
@@ -157,36 +166,30 @@ if (sign) { | ||
} | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.encryptSign(buf2array(data), [], keys, [], signKey).addCallback( | ||
function (ciphertext) { | ||
resolve(array2buf(ciphertext)); | ||
}).addErrback(reject); | ||
}); | ||
}); | ||
return pgp.encryptSign(buf2array(data), [], keys, [], signKey); | ||
}).then(array2buf); | ||
}; | ||
mye2e.prototype.verifyDecrypt = function(data, verifyKey) { | ||
var importedKey; | ||
if (typeof verifyKey === 'undefined') { | ||
verifyKey = ''; | ||
importedKey = Promise.resolve(); | ||
} else { | ||
this.importKey(verifyKey); | ||
importedKey = this.importPubKey(verifyKey); | ||
} | ||
var byteView = new Uint8Array(data); | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.verifyDecrypt(function () { | ||
return ''; | ||
}, e2e.openpgp.asciiArmor.encode('MESSAGE', byteView)).addCallback( | ||
function (result) { | ||
var signed = null; | ||
if (verifyKey) { | ||
signed = result.verify.success[0].uids; | ||
} | ||
resolve({ | ||
data: array2buf(result.decrypt.data), | ||
signedBy: signed | ||
}); | ||
}).addErrback(reject); | ||
}); | ||
return importedKey.then(function() { | ||
return pgp.verifyDecrypt(function () { | ||
throw new Error('Passphrase decryption is not supported'); | ||
}, buf2array(data)); | ||
}).then(function (result) { | ||
var signed = null; | ||
if (verifyKey) { | ||
signed = result.verify.success[0].uids; | ||
} | ||
return { | ||
data: array2buf(result.decrypt.data), | ||
signedBy: signed | ||
}; | ||
}); | ||
}; | ||
@@ -211,14 +214,9 @@ | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
var expiration = Date.now() / 1000 + (3600 * 24 * 365); | ||
pgp.generateKey('ECDSA', 256, 'ECDH', 256, name, '', email, expiration). | ||
addCallback(function (keys) { | ||
if (keys.length == 2) { | ||
resolve(); | ||
} else { | ||
reject(new Error('Failed to generate key')); | ||
} | ||
}); | ||
}); | ||
var expiration = Date.now() / 1000 + (3600 * 24 * 365); | ||
return pgp.generateKey('ECDSA', 256, 'ECDH', 256, name, '', email, expiration) | ||
.then(function (keys) { | ||
if (keys.length !== 2) { | ||
throw new Error('Failed to generate key'); | ||
} | ||
}); | ||
}; | ||
@@ -231,3 +229,3 @@ | ||
mye2e.prototype.importKey = function(keyStr, passphrase) { | ||
mye2e.prototype.importPrivKey = function(keyStr, passphrase) { | ||
if (typeof passphrase === 'undefined') { | ||
@@ -237,9 +235,35 @@ passphrase = ''; | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.importKey( | ||
function(str, continuation) { | ||
continuation(passphrase); | ||
}, keyStr).addCallback(resolve).addErrback(reject); | ||
return pgp.importKey( | ||
function(str) { | ||
return e2e.async.Result.toResult(passphrase); | ||
}, keyStr); | ||
}; | ||
mye2e.prototype.importPubKey = function(keyStr) { | ||
// Algorithm: | ||
// 1. Compute the key description, which includes the fingerprint. | ||
// This action has no side effects (does not import the key). | ||
// 2. Import the key. This returns the "uid", i.e. e-mail address. | ||
// 3. Search for all known public keys with this uid. | ||
// 4. Find the key whose fingerprint matches the input. Return this one. | ||
var pgp = this.pgpContext; | ||
return pgp.getKeyDescription(keyStr).then(function(keyDescriptions) { | ||
var keyDescription = keyDescriptions[0]; | ||
return pgp.importKey(function(str) { | ||
throw new Error('No passphrase needed for a public key'); | ||
}, keyStr).then(function(uids) { | ||
if (uids.length !== 1) throw new Error('too many uids'); | ||
return pgp.searchPublicKey(uids[0]); | ||
}).then(function(candidateKeydescriptions) { | ||
var rightKey = null; | ||
candidateKeydescriptions.forEach(function(candidateKeyDescription) { | ||
if (candidateKeyDescription.key.fingerprintHex === | ||
keyDescription.key.fingerprintHex) { | ||
rightKey = candidateKeyDescription; | ||
} | ||
}); | ||
if (!rightKey) throw new Error('could not import key'); | ||
return rightKey; | ||
}); | ||
}); | ||
}; | ||
@@ -246,0 +270,0 @@ |
function store () { | ||
this.storage = {}; | ||
if (!store.isPrepared) { | ||
throw new Error('store not yet prepared'); | ||
} | ||
} | ||
@@ -53,4 +56,7 @@ | ||
store.isPrepared = false; | ||
store.prepareFreedom = function() { | ||
// mock doesn't actually use freedom localStorage | ||
store.isPrepared = true; | ||
return Promise.resolve(); | ||
@@ -57,0 +63,0 @@ }; |
@@ -70,2 +70,5 @@ | ||
store.prototype.initialize = function() { | ||
if (!store.isPrepared) { | ||
throw new Error('store is not yet prepared'); | ||
} | ||
this.memStorage = store.preparedMem; | ||
@@ -75,2 +78,3 @@ }; | ||
store.preparedMem = {}; | ||
store.isPrepared = false; | ||
@@ -84,2 +88,3 @@ // IMPORTANT - this function must be called and resolved before instantiating | ||
} | ||
store.isPrepared = true; | ||
}); | ||
@@ -86,0 +91,0 @@ }; |
@@ -12,2 +12,8 @@ /** | ||
module.exports = function(grunt) { | ||
require('time-grunt')(grunt); | ||
require('jit-grunt')(grunt, { | ||
jasmine_node: 'grunt-jasmine-node2', | ||
'npm-publish': 'grunt-npm' | ||
}); | ||
grunt.initConfig({ | ||
@@ -115,3 +121,4 @@ copy: { | ||
options: { | ||
jshintrc: true | ||
jshintrc: true, | ||
reporter: require('jshint-stylish') | ||
} | ||
@@ -172,15 +179,2 @@ }, | ||
grunt.loadNpmTasks('grunt-browserify'); | ||
grunt.loadNpmTasks('grunt-bump'); | ||
grunt.loadNpmTasks('grunt-contrib-clean'); | ||
grunt.loadNpmTasks('grunt-contrib-connect'); | ||
grunt.loadNpmTasks('grunt-contrib-copy'); | ||
grunt.loadNpmTasks('grunt-contrib-jshint'); | ||
grunt.loadNpmTasks('grunt-jasmine-chromeapp'); | ||
grunt.loadNpmTasks('grunt-jasmine-firefoxaddon'); | ||
grunt.loadNpmTasks('grunt-jasmine-node2'); | ||
grunt.loadNpmTasks('grunt-karma'); | ||
grunt.loadNpmTasks('grunt-npm'); | ||
grunt.loadNpmTasks('grunt-prompt'); | ||
grunt.registerTask('build', [ | ||
@@ -187,0 +181,0 @@ 'jshint', |
{ | ||
"name": "freedom-pgp-e2e", | ||
"description": "Library to provide freedom API wrapper of end-to-end library", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"contributors": [ | ||
@@ -16,4 +16,4 @@ "Aaron Gallant <ag@cs.washington.edu>" | ||
"es6-promise": "^3.0.2", | ||
"freedom": "^0.6.26", | ||
"freedom-for-chrome": "^0.4.20", | ||
"freedom": "^0.6.27", | ||
"freedom-for-chrome": "^0.4.22", | ||
"freedom-for-firefox": "^0.6.18", | ||
@@ -23,8 +23,8 @@ "freedom-for-node": "^0.2.18", | ||
"grunt-browserify": "^4.0.1", | ||
"grunt-bump": "^0.6.0", | ||
"grunt-contrib-clean": "^0.6.0", | ||
"grunt-bump": "^0.7.0", | ||
"grunt-contrib-clean": "^0.7.0", | ||
"grunt-contrib-connect": "^0.11.2", | ||
"grunt-contrib-copy": "^0.8.2", | ||
"grunt-contrib-jshint": "^0.11.3", | ||
"grunt-jasmine-chromeapp": "^1.8.0", | ||
"grunt-contrib-jshint": "^0.12.0", | ||
"grunt-jasmine-chromeapp": "^1.9.0", | ||
"grunt-jasmine-firefoxaddon": "^0.3.2", | ||
@@ -36,11 +36,14 @@ "grunt-jasmine-node2": "^0.4.0", | ||
"hex2words": "^1.1.3", | ||
"karma": "^0.13.15", | ||
"karma-chrome-launcher": "^0.2.1", | ||
"jit-grunt": "^0.9.1", | ||
"jshint-stylish": "^2.1.0", | ||
"karma": "^0.13.19", | ||
"karma-chrome-launcher": "^0.2.2", | ||
"karma-coverage": "^0.5.3", | ||
"karma-firefox-launcher": "^0.1.7", | ||
"karma-jasmine": "^0.3.6", | ||
"karma-phantomjs-launcher": "^0.2.1", | ||
"karma-phantomjs-launcher": "^0.2.3", | ||
"karma-story-reporter": "^0.3.1", | ||
"karma-unicorn-reporter": "^0.1.4", | ||
"phantomjs": "^1.9.18" | ||
"phantomjs": "^1.9.19", | ||
"time-grunt": "^1.3.0" | ||
}, | ||
@@ -47,0 +50,0 @@ "scripts": { |
@@ -82,4 +82,5 @@ /*globals describe, beforeEach, require, expect, it*/ | ||
function () { | ||
return e2eImp.importKey(publicKeyStr); | ||
}).then(function () { | ||
return e2eImp.importPubKey(publicKeyStr); | ||
}).then(function (keyObj) { | ||
expect(keyObj.key.fingerprintHex).toEqual(keyFingerprint); | ||
return e2eImp.searchPublicKey('<quantsword@gmail.com>'); | ||
@@ -117,3 +118,3 @@ }).then(function (keys) { | ||
function () { | ||
return e2eImp.importKey(privateKeyStr); | ||
return e2eImp.importPrivKey(privateKeyStr); | ||
}).then(function () { | ||
@@ -172,2 +173,18 @@ return e2eImp.searchPrivateKey('<quantsword@gmail.com>'); | ||
it('sign and verify', function(done) { | ||
e2eImp.setup('test passphrase', 'Test User <test@example.com>').then( | ||
function () { | ||
return Promise.all([e2eImp.exportKey(), e2eImp.signEncrypt(buffer)]); | ||
}).then(function (array) { | ||
var key = array[0].key; | ||
var signedData = array[1]; | ||
return e2eImp.verifyDecrypt(signedData, key); | ||
}).then(function (result) { | ||
expect(result.data).toEqual(buffer); | ||
}).catch(function (e) { | ||
console.log(e.toString()); | ||
expect(false).toBeTruthy(); | ||
}).then(done); | ||
}); | ||
it('encryptSign and verifyDecrypt', function(done) { | ||
@@ -234,2 +251,123 @@ e2eImp.setup('test passphrase', 'Test User <test@example.com>').then( | ||
}); | ||
it('sign and verify between two users', function(done) { | ||
e2eImp.setup('test passphrase', 'Test User <test@example.com>').then(function() { | ||
var otherUser = new mye2e(); | ||
return otherUser.setup('other user passphrase', | ||
'Other User <other@example.com>').then(function() { | ||
return otherUser; | ||
}); | ||
}).then( | ||
function(otherUser) { | ||
return Promise.all([otherUser.exportKey(), | ||
otherUser.signEncrypt(buffer)]); | ||
}).then(function (array) { | ||
var key = array[0].key; | ||
var signedData = array[1]; | ||
return e2eImp.verifyDecrypt(signedData, key); | ||
}).then(function (result) { | ||
expect(result.data).toEqual(buffer); | ||
}).catch(function (e) { | ||
console.log(e.toString()); | ||
expect(false).toBeTruthy(); | ||
}).then(done); | ||
}); | ||
it('getFingerprint of users with the same name', function(done) { | ||
var otherUser0 = new mye2e(); | ||
var otherUser1 = new mye2e(); | ||
e2eImp.setup('test passphrase', 'Test User <test@example.com>').then( | ||
function () { | ||
return Promise.all([ | ||
otherUser0.setup('test passphrase', 'Test User <test@example.com>'), | ||
otherUser1.setup('test passphrase', 'Test User <test@example.com>') | ||
]); | ||
}).then(function () { | ||
return Promise.all([otherUser0.exportKey(), otherUser1.exportKey()]); | ||
}).then(function (keys) { | ||
// Check that the test is functioning correctly, generating new keys. | ||
expect(keys[0].key).not.toEqual(keys[1].key); | ||
expect(keys[0].fingerprint).not.toEqual(keys[1].fingerprint); | ||
// Check that the fingerprints are computed correctly | ||
return Promise.all([ | ||
e2eImp.getFingerprint(keys[0].key).then(function(fp) { | ||
expect(fp.fingerprint).toEqual(keys[0].fingerprint); | ||
}), | ||
e2eImp.getFingerprint(keys[1].key).then(function(fp) { | ||
expect(fp.fingerprint).toEqual(keys[1].fingerprint); | ||
}) | ||
]); | ||
}).catch(function (e) { | ||
console.log(e.toString()); | ||
expect(false).toBeTruthy(); | ||
}).then(done); | ||
}); | ||
it('verify messages from users with the same name', function(done) { | ||
var otherUser0 = new mye2e(); | ||
var otherUser1 = new mye2e(); | ||
e2eImp.setup('test passphrase', 'Test User <test@example.com>').then(function() { | ||
return Promise.all([ | ||
otherUser0.setup('test passphrase', 'Test User <test@example.com>'), | ||
otherUser1.setup('test passphrase', 'Test User <test@example.com>') | ||
]); | ||
}).then(function () { | ||
// Sign a message from user0, and verify with e2eImp | ||
return Promise.all([otherUser0.exportKey(), | ||
otherUser0.signEncrypt(buffer)]); | ||
}).then(function (array) { | ||
var key = array[0].key; | ||
var signedData = array[1]; | ||
return e2eImp.verifyDecrypt(signedData, key); | ||
}).then(function (result) { | ||
expect(result.data).toEqual(buffer); | ||
// Sign a message from user1, and verify with e2eImp | ||
return Promise.all([otherUser1.exportKey(), | ||
otherUser1.signEncrypt(buffer)]); | ||
}).then(function (array) { | ||
var key = array[0].key; | ||
var signedData = array[1]; | ||
return e2eImp.verifyDecrypt(signedData, key); | ||
}).then(function (result) { | ||
expect(result.data).toEqual(buffer); | ||
}).catch(function (e) { | ||
console.log(e.toString()); | ||
expect(false).toBeTruthy(); | ||
}).then(done); | ||
}); | ||
it('encrypt messages to users with the same name', function(done) { | ||
var otherUser0 = new mye2e(); | ||
var otherUser1 = new mye2e(); | ||
e2eImp.setup('test passphrase', 'Test User <test@example.com>').then(function() { | ||
return Promise.all([ | ||
otherUser0.setup('test passphrase', 'Test User <test@example.com>'), | ||
otherUser1.setup('test passphrase', 'Test User <test@example.com>') | ||
]); | ||
}).then(function () { | ||
return Promise.all([otherUser0.exportKey(), otherUser1.exportKey()]); | ||
}).then(function (keys) { | ||
// Check that the test is functioning correctly, generating new keys. | ||
expect(keys[0].key).not.toEqual(keys[1].key); | ||
// Encrypt a message to both users | ||
return Promise.all([ | ||
e2eImp.signEncrypt(buffer, keys[0].key), | ||
e2eImp.signEncrypt(buffer, keys[1].key) | ||
]); | ||
}).then(function (cipherTexts) { | ||
return Promise.all([ | ||
otherUser0.verifyDecrypt(cipherTexts[0]), | ||
otherUser1.verifyDecrypt(cipherTexts[1]) | ||
]); | ||
}).then(function (results) { | ||
expect(results[0].data).toEqual(buffer); | ||
expect(results[1].data).toEqual(buffer); | ||
}).catch(function (e) { | ||
console.log(e.toString()); | ||
expect(false).toBeTruthy(); | ||
}).then(done); | ||
}); | ||
}); |
150
src/e2e.js
@@ -48,4 +48,3 @@ /*globals freedom, console, e2e, exports, ArrayBuffer, Uint8Array, Uint16Array, DataView*/ | ||
var mye2e = function(dispatchEvents) { | ||
this.pgpContext = new e2e.openpgp.ContextImpl(); | ||
this.pgpContext.armorOutput = false; | ||
this.pgpContext = null; | ||
this.pgpUser = null; | ||
@@ -64,3 +63,8 @@ }; | ||
return refreshBuffer(5000).then(store.prepareFreedom).then(function() { | ||
scope.pgpContext.setKeyRingPassphrase(passphrase); | ||
if (!scope.pgpContext) { | ||
scope.pgpContext = new e2e.openpgp.ContextImpl(); | ||
scope.pgpContext.armorOutput = false; | ||
} | ||
return scope.pgpContext.initializeKeyRing(passphrase); | ||
}).then(function() { | ||
if (e2e.async.Result.getValue( | ||
@@ -89,4 +93,8 @@ scope.pgpContext.searchPrivateKey(scope.pgpUser)).length === 0) { | ||
return this.clear().then(function() { | ||
if (!scope.pgpContext) { | ||
scope.pgpContext = new e2e.openpgp.ContextImpl(); | ||
scope.pgpContext.armorOutput = false; | ||
} | ||
scope.pgpContext.setKeyRingPassphrase(passphrase); | ||
return scope.importKey(privateKey, passphrase); | ||
return scope.importPrivKey(privateKey, passphrase); | ||
}).then(function() { | ||
@@ -122,11 +130,9 @@ if (e2e.async.Result.getValue( | ||
// http://tools.ietf.org/html/rfc4880#section-12.2 | ||
var importResult = e2e.async.Result.getValue( | ||
this.pgpContext.importKey(function(str, f) { | ||
f(''); | ||
}, publicKey)); | ||
var keyResult = e2e.async.Result.getValue( | ||
this.pgpContext.searchPublicKey(importResult[0])); | ||
return Promise.resolve({ | ||
'fingerprint': keyResult[0].key.fingerprintHex, | ||
'words': hex2words(keyResult[0].key.fingerprintHex) | ||
return this.pgpContext.getKeyDescription(publicKey).then( | ||
function(keyDescriptions) { | ||
var fingerprint = keyDescriptions[0].key.fingerprintHex; | ||
return { | ||
'fingerprint': fingerprint, | ||
'words': hex2words(fingerprint) | ||
}; | ||
}); | ||
@@ -136,2 +142,3 @@ }; | ||
mye2e.prototype.signEncrypt = function(data, encryptKey, sign) { | ||
var scope = this; | ||
var pgp = this.pgpContext; | ||
@@ -143,8 +150,10 @@ var user = this.pgpUser; | ||
} | ||
var importResult = e2e.async.Result.getValue( | ||
pgp.importKey(function(str, f) { | ||
f(''); | ||
}, encryptKey)); | ||
var keys = e2e.async.Result.getValue( | ||
pgp.searchPublicKey(importResult[0])); | ||
var keys = Promise.resolve([]); | ||
if (encryptKey) { | ||
keys = scope.importPubKey(encryptKey).then(function(key) { | ||
return [key]; | ||
}); | ||
} | ||
return keys; | ||
}).then(function(keys) { | ||
var signKey; | ||
@@ -157,36 +166,30 @@ if (sign) { | ||
} | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.encryptSign(buf2array(data), [], keys, [], signKey).addCallback( | ||
function (ciphertext) { | ||
resolve(array2buf(ciphertext)); | ||
}).addErrback(reject); | ||
}); | ||
}); | ||
return pgp.encryptSign(buf2array(data), [], keys, [], signKey); | ||
}).then(array2buf); | ||
}; | ||
mye2e.prototype.verifyDecrypt = function(data, verifyKey) { | ||
var importedKey; | ||
if (typeof verifyKey === 'undefined') { | ||
verifyKey = ''; | ||
importedKey = Promise.resolve(); | ||
} else { | ||
this.importKey(verifyKey); | ||
importedKey = this.importPubKey(verifyKey); | ||
} | ||
var byteView = new Uint8Array(data); | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.verifyDecrypt(function () { | ||
return ''; | ||
}, e2e.openpgp.asciiArmor.encode('MESSAGE', byteView)).addCallback( | ||
function (result) { | ||
var signed = null; | ||
if (verifyKey) { | ||
signed = result.verify.success[0].uids; | ||
} | ||
resolve({ | ||
data: array2buf(result.decrypt.data), | ||
signedBy: signed | ||
}); | ||
}).addErrback(reject); | ||
}); | ||
return importedKey.then(function() { | ||
return pgp.verifyDecrypt(function () { | ||
throw new Error('Passphrase decryption is not supported'); | ||
}, buf2array(data)); | ||
}).then(function (result) { | ||
var signed = null; | ||
if (verifyKey) { | ||
signed = result.verify.success[0].uids; | ||
} | ||
return { | ||
data: array2buf(result.decrypt.data), | ||
signedBy: signed | ||
}; | ||
}); | ||
}; | ||
@@ -211,14 +214,9 @@ | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
var expiration = Date.now() / 1000 + (3600 * 24 * 365); | ||
pgp.generateKey('ECDSA', 256, 'ECDH', 256, name, '', email, expiration). | ||
addCallback(function (keys) { | ||
if (keys.length == 2) { | ||
resolve(); | ||
} else { | ||
reject(new Error('Failed to generate key')); | ||
} | ||
}); | ||
}); | ||
var expiration = Date.now() / 1000 + (3600 * 24 * 365); | ||
return pgp.generateKey('ECDSA', 256, 'ECDH', 256, name, '', email, expiration) | ||
.then(function (keys) { | ||
if (keys.length !== 2) { | ||
throw new Error('Failed to generate key'); | ||
} | ||
}); | ||
}; | ||
@@ -231,3 +229,3 @@ | ||
mye2e.prototype.importKey = function(keyStr, passphrase) { | ||
mye2e.prototype.importPrivKey = function(keyStr, passphrase) { | ||
if (typeof passphrase === 'undefined') { | ||
@@ -237,9 +235,35 @@ passphrase = ''; | ||
var pgp = this.pgpContext; | ||
return new Promise( | ||
function(resolve, reject) { | ||
pgp.importKey( | ||
function(str, continuation) { | ||
continuation(passphrase); | ||
}, keyStr).addCallback(resolve).addErrback(reject); | ||
return pgp.importKey( | ||
function(str) { | ||
return e2e.async.Result.toResult(passphrase); | ||
}, keyStr); | ||
}; | ||
mye2e.prototype.importPubKey = function(keyStr) { | ||
// Algorithm: | ||
// 1. Compute the key description, which includes the fingerprint. | ||
// This action has no side effects (does not import the key). | ||
// 2. Import the key. This returns the "uid", i.e. e-mail address. | ||
// 3. Search for all known public keys with this uid. | ||
// 4. Find the key whose fingerprint matches the input. Return this one. | ||
var pgp = this.pgpContext; | ||
return pgp.getKeyDescription(keyStr).then(function(keyDescriptions) { | ||
var keyDescription = keyDescriptions[0]; | ||
return pgp.importKey(function(str) { | ||
throw new Error('No passphrase needed for a public key'); | ||
}, keyStr).then(function(uids) { | ||
if (uids.length !== 1) throw new Error('too many uids'); | ||
return pgp.searchPublicKey(uids[0]); | ||
}).then(function(candidateKeydescriptions) { | ||
var rightKey = null; | ||
candidateKeydescriptions.forEach(function(candidateKeyDescription) { | ||
if (candidateKeyDescription.key.fingerprintHex === | ||
keyDescription.key.fingerprintHex) { | ||
rightKey = candidateKeyDescription; | ||
} | ||
}); | ||
if (!rightKey) throw new Error('could not import key'); | ||
return rightKey; | ||
}); | ||
}); | ||
}; | ||
@@ -246,0 +270,0 @@ |
function store () { | ||
this.storage = {}; | ||
if (!store.isPrepared) { | ||
throw new Error('store not yet prepared'); | ||
} | ||
} | ||
@@ -53,4 +56,7 @@ | ||
store.isPrepared = false; | ||
store.prepareFreedom = function() { | ||
// mock doesn't actually use freedom localStorage | ||
store.isPrepared = true; | ||
return Promise.resolve(); | ||
@@ -57,0 +63,0 @@ }; |
@@ -70,2 +70,5 @@ | ||
store.prototype.initialize = function() { | ||
if (!store.isPrepared) { | ||
throw new Error('store is not yet prepared'); | ||
} | ||
this.memStorage = store.preparedMem; | ||
@@ -75,2 +78,3 @@ }; | ||
store.preparedMem = {}; | ||
store.isPrepared = false; | ||
@@ -84,2 +88,3 @@ // IMPORTANT - this function must be called and resolved before instantiating | ||
} | ||
store.isPrepared = true; | ||
}); | ||
@@ -86,0 +91,0 @@ }; |
Sorry, the diff of this file is too big to display
2284416
17278
32