Cleanup packet list clonong --> src/packet/clone.js
This commit is contained in:
parent
450a7321d1
commit
4f6e036a07
117
src/packet/clone.js
Normal file
117
src/packet/clone.js
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// OpenPGP.js - An OpenPGP implementation in javascript
|
||||||
|
// Copyright (C) 2015 Tankred Hase
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 3.0 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview This module implements packet list cloning required to
|
||||||
|
* pass certain object types beteen the web worker and main thread using
|
||||||
|
* the structured cloning algorithm.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as key from '../key.js';
|
||||||
|
import * as message from '../message.js';
|
||||||
|
import * as cleartext from '../cleartext.js';
|
||||||
|
import Packetlist from './packetlist.js';
|
||||||
|
import type_keyid from '../type/keyid.js';
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// //
|
||||||
|
// Packetlist --> Clone //
|
||||||
|
// //
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a packetlist from the correspoding object types.
|
||||||
|
* @param {Object} options the object passed to and from the web worker
|
||||||
|
* @return {Object} a mutated version of the options optject
|
||||||
|
*/
|
||||||
|
export function clonePackets(options) {
|
||||||
|
if(options.publicKeys) {
|
||||||
|
options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
|
||||||
|
}
|
||||||
|
if(options.privateKeys) {
|
||||||
|
options.privateKeys = options.privateKeys.map(key => key.toPacketlist());
|
||||||
|
}
|
||||||
|
if(options.privateKey) {
|
||||||
|
options.privateKey = options.privateKey.toPacketlist();
|
||||||
|
}
|
||||||
|
if (options.key) {
|
||||||
|
options.key = options.key.toPacketlist();
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// //
|
||||||
|
// Clone --> Packetlist //
|
||||||
|
// //
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an object with the correct prototype from a corresponding packetlist.
|
||||||
|
* @param {Object} options the object passed to and from the web worker
|
||||||
|
* @param {String} method the public api function name to be delegated to the worker
|
||||||
|
* @return {Object} a mutated version of the options optject
|
||||||
|
*/
|
||||||
|
export function parseClonedPackets(options, method) {
|
||||||
|
if(options.publicKeys) {
|
||||||
|
options.publicKeys = options.publicKeys.map(packetlistCloneToKey);
|
||||||
|
}
|
||||||
|
if(options.privateKeys) {
|
||||||
|
options.privateKeys = options.privateKeys.map(packetlistCloneToKey);
|
||||||
|
}
|
||||||
|
if(options.privateKey) {
|
||||||
|
options.privateKey = packetlistCloneToKey(options.privateKey);
|
||||||
|
}
|
||||||
|
if (options.key) {
|
||||||
|
options.key = packetlistCloneToKey(options.key);
|
||||||
|
}
|
||||||
|
if (options.message && (method === 'sign' || method === 'verify')) { // sign and verify support only CleartextMessage
|
||||||
|
options.message = packetlistCloneToCleartextMessage(options.message);
|
||||||
|
} else if (options.message) {
|
||||||
|
options.message = packetlistCloneToMessage(options.message);
|
||||||
|
}
|
||||||
|
if (options.signatures) {
|
||||||
|
options.signatures = options.signatures.map(packetlistCloneToSignature);
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
function packetlistCloneToKey(clone) {
|
||||||
|
const packetlist = Packetlist.fromStructuredClone(clone);
|
||||||
|
return new key.Key(packetlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function packetlistCloneToMessage(clone) {
|
||||||
|
const packetlist = Packetlist.fromStructuredClone(clone.packets);
|
||||||
|
return new message.Message(packetlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function packetlistCloneToCleartextMessage(clone) {
|
||||||
|
var packetlist = Packetlist.fromStructuredClone(clone.packets);
|
||||||
|
return new cleartext.CleartextMessage(clone.text, packetlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function packetlistCloneToSignature(clone) {
|
||||||
|
clone.keyid = type_keyid.fromClone(clone.keyid);
|
||||||
|
return clone;
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as packets from './all_packets.js';
|
import * as packets from './all_packets.js';
|
||||||
|
import * as clone from './clone.js';
|
||||||
import List from './packetlist.js';
|
import List from './packetlist.js';
|
||||||
|
|
||||||
const mod = {
|
const mod = {
|
||||||
/**
|
/** @see module:packet/packetlist */
|
||||||
* @name module:packet.List
|
List: List,
|
||||||
* @see module:packet/packetlist
|
/** @see module:packet/clone */
|
||||||
*/
|
clone: clone
|
||||||
List: List
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i in packets) {
|
for (let i in packets) {
|
||||||
|
|
|
@ -15,24 +15,11 @@
|
||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires crypto
|
|
||||||
* @requires enums
|
|
||||||
* @requires packet
|
|
||||||
* @requires type_keyid
|
|
||||||
* @requires key
|
|
||||||
* @module async_proxy
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import util from '../util.js';
|
import util from '../util.js';
|
||||||
import crypto from '../crypto';
|
import crypto from '../crypto';
|
||||||
import packet from '../packet';
|
import packet from '../packet';
|
||||||
import * as key from '../key.js';
|
|
||||||
import * as message from '../message.js';
|
|
||||||
import * as cleartext from '../cleartext.js';
|
|
||||||
import type_keyid from '../type/keyid.js';
|
|
||||||
|
|
||||||
const INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
|
const INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
|
||||||
RANDOM_SEED_REQUEST = 20000; // random bytes seeded after worker request
|
RANDOM_SEED_REQUEST = 20000; // random bytes seeded after worker request
|
||||||
|
@ -59,19 +46,6 @@ export default function AsyncProxy({ path='openpgp.worker.js', worker, config }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Command pattern that wraps synchronous code into a promise
|
|
||||||
* @param {function} cmd The synchronous function with a return value
|
|
||||||
* to be wrapped in a promise
|
|
||||||
* @return {Promise} The promise wrapped around cmd
|
|
||||||
*/
|
|
||||||
AsyncProxy.prototype.execute = function(cmd) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
cmd();
|
|
||||||
this.tasks.push({ resolve, reject });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message handling
|
* Message handling
|
||||||
*/
|
*/
|
||||||
|
@ -125,111 +99,18 @@ AsyncProxy.prototype.terminate = function() {
|
||||||
this.worker.terminate();
|
this.worker.terminate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
* Generic proxy function that handles all commands from the public api.
|
||||||
// //
|
* @param {String} method the public api function to be delegated to the worker thread
|
||||||
// Proxy functions. See the corresponding code in the openpgp module for the documentation. //
|
* @param {Object} options the api function's options
|
||||||
// //
|
* @return {Promise} see the corresponding public api functions for their return types
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
*/
|
||||||
|
|
||||||
|
|
||||||
AsyncProxy.prototype.delegate = function(method, options) {
|
AsyncProxy.prototype.delegate = function(method, options) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// clone packets (for web worker structured cloning algorithm)
|
// clone packets (for web worker structured cloning algorithm)
|
||||||
this.worker.postMessage({ event:method, options:clonePackets(options) }, util.getTransferables.call(util, options));
|
this.worker.postMessage({ event:method, options:packet.clone.clonePackets(options) }, util.getTransferables.call(util, options));
|
||||||
|
|
||||||
// remember to handle parsing cloned packets from worker
|
// remember to handle parsing cloned packets from worker
|
||||||
this.tasks.push({ resolve: data => resolve(parseClonedPackets(data, method)), reject });
|
this.tasks.push({ resolve: data => resolve(packet.clone.parseClonedPackets(data, method)), reject });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function clonePackets(options) {
|
|
||||||
if(options.publicKeys) {
|
|
||||||
options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
|
|
||||||
}
|
|
||||||
if(options.privateKeys) {
|
|
||||||
options.privateKeys = options.privateKeys.map(key => key.toPacketlist());
|
|
||||||
}
|
|
||||||
if(options.privateKey) {
|
|
||||||
options.privateKey = options.privateKey.toPacketlist();
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseClonedPackets(data, method) {
|
|
||||||
if (data.key) {
|
|
||||||
data.key = packetlistCloneToKey(data.key);
|
|
||||||
}
|
|
||||||
if (data.message && method === 'sign') { // sign supports only CleartextMessage
|
|
||||||
data.message = packetlistCloneToCleartextMessage(data.message);
|
|
||||||
} else if (data.message) {
|
|
||||||
data.message = packetlistCloneToMessage(data.message);
|
|
||||||
}
|
|
||||||
if (data.signatures) {
|
|
||||||
data.signatures = data.signatures.map(packetlistCloneToSignature);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToKey(clone) {
|
|
||||||
const packetlist = packet.List.fromStructuredClone(clone);
|
|
||||||
return new key.Key(packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToMessage(clone) {
|
|
||||||
const packetlist = packet.List.fromStructuredClone(clone.packets);
|
|
||||||
return new message.Message(packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToCleartextMessage(clone) {
|
|
||||||
var packetlist = packet.List.fromStructuredClone(clone.packets);
|
|
||||||
return new cleartext.CleartextMessage(clone.text, packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToSignature(clone) {
|
|
||||||
clone.keyid = type_keyid.fromClone(clone.keyid);
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncProxy.prototype.decryptKey = function(privateKey, password) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var promise = new Promise(function(resolve, reject) {
|
|
||||||
privateKey = privateKey.toPacketlist();
|
|
||||||
self.worker.postMessage({
|
|
||||||
event: 'decrypt-key',
|
|
||||||
privateKey: privateKey,
|
|
||||||
password: password
|
|
||||||
});
|
|
||||||
|
|
||||||
self.tasks.push({ resolve:function(data) {
|
|
||||||
var packetlist = packet.List.fromStructuredClone(data);
|
|
||||||
data = new key.Key(packetlist);
|
|
||||||
resolve(data);
|
|
||||||
}, reject:reject });
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncProxy.prototype.decryptKeyPacket = function(privateKey, keyIds, password) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var promise = new Promise(function(resolve, reject) {
|
|
||||||
privateKey = privateKey.toPacketlist();
|
|
||||||
self.worker.postMessage({
|
|
||||||
event: 'decrypt-key-packet',
|
|
||||||
privateKey: privateKey,
|
|
||||||
keyIds: keyIds,
|
|
||||||
password: password
|
|
||||||
});
|
|
||||||
|
|
||||||
self.tasks.push({ resolve:function(data) {
|
|
||||||
var packetlist = packet.List.fromStructuredClone(data);
|
|
||||||
data = new key.Key(packetlist);
|
|
||||||
resolve(data);
|
|
||||||
}, reject:reject });
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
|
|
|
@ -42,23 +42,21 @@ if (!Function.prototype.bind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
importScripts('openpgp.js');
|
importScripts('openpgp.js');
|
||||||
|
var openpgp = window.openpgp;
|
||||||
|
|
||||||
var MIN_SIZE_RANDOM_BUFFER = 40000;
|
var MIN_SIZE_RANDOM_BUFFER = 40000;
|
||||||
var MAX_SIZE_RANDOM_BUFFER = 60000;
|
var MAX_SIZE_RANDOM_BUFFER = 60000;
|
||||||
|
|
||||||
window.openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
|
openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
|
||||||
|
|
||||||
self.onmessage = function (event) {
|
self.onmessage = function (event) {
|
||||||
var data = null,
|
var msg = event.data,
|
||||||
err = null,
|
options = msg.options || {};
|
||||||
msg = event.data,
|
|
||||||
opt = msg.options || {},
|
|
||||||
correct = false;
|
|
||||||
|
|
||||||
switch (msg.event) {
|
switch (msg.event) {
|
||||||
case 'configure':
|
case 'configure':
|
||||||
for (var i in msg.config) {
|
for (var i in msg.config) {
|
||||||
window.openpgp.config[i] = msg.config[i];
|
openpgp.config[i] = msg.config[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -66,41 +64,11 @@ self.onmessage = function (event) {
|
||||||
if (!(msg.buf instanceof Uint8Array)) {
|
if (!(msg.buf instanceof Uint8Array)) {
|
||||||
msg.buf = new Uint8Array(msg.buf);
|
msg.buf = new Uint8Array(msg.buf);
|
||||||
}
|
}
|
||||||
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
|
openpgp.crypto.random.randomBuffer.set(msg.buf);
|
||||||
break;
|
|
||||||
|
|
||||||
case 'decrypt-key':
|
|
||||||
try {
|
|
||||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
|
||||||
correct = msg.privateKey.decrypt(msg.password);
|
|
||||||
if (correct) {
|
|
||||||
data = msg.privateKey.toPacketlist();
|
|
||||||
} else {
|
|
||||||
err = 'Wrong password';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
err = e.message;
|
|
||||||
}
|
|
||||||
response({event: 'method-return', data: data, err: err});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'decrypt-key-packet':
|
|
||||||
try {
|
|
||||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
|
||||||
msg.keyIds = msg.keyIds.map(window.openpgp.Keyid.fromClone);
|
|
||||||
correct = msg.privateKey.decryptKeyPacket(msg.keyIds, msg.password);
|
|
||||||
if (correct) {
|
|
||||||
data = msg.privateKey.toPacketlist();
|
|
||||||
} else {
|
|
||||||
err = 'Wrong password';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
err = e.message;
|
|
||||||
}
|
|
||||||
response({event: 'method-return', data: data, err: err});
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'generateKey':
|
case 'generateKey':
|
||||||
|
case 'decryptKey':
|
||||||
case 'encrypt':
|
case 'encrypt':
|
||||||
case 'decrypt':
|
case 'decrypt':
|
||||||
case 'sign':
|
case 'sign':
|
||||||
|
@ -108,9 +76,9 @@ self.onmessage = function (event) {
|
||||||
case 'encryptSessionKey':
|
case 'encryptSessionKey':
|
||||||
case 'decryptSessionKey':
|
case 'decryptSessionKey':
|
||||||
// parse cloned packets
|
// parse cloned packets
|
||||||
window.openpgp[msg.event](parseClonedPackets(opt, msg.event)).then(function(data) {
|
openpgp[msg.event](openpgp.packet.clone.parseClonedPackets(options, msg.event)).then(function(data) {
|
||||||
// clone packets (for web worker structured cloning algorithm)
|
// clone packets (for web worker structured cloning algorithm)
|
||||||
response({ event:'method-return', data:clonePackets(data) });
|
response({ event:'method-return', data:openpgp.packet.clone.clonePackets(data) });
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
response({ event:'method-return', err:e.message });
|
response({ event:'method-return', err:e.message });
|
||||||
});
|
});
|
||||||
|
@ -121,49 +89,9 @@ self.onmessage = function (event) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseClonedPackets(options, method) {
|
|
||||||
if(options.publicKeys) {
|
|
||||||
options.publicKeys = options.publicKeys.map(packetlistCloneToKey);
|
|
||||||
}
|
|
||||||
if(options.privateKeys) {
|
|
||||||
options.privateKeys = options.privateKeys.map(packetlistCloneToKey);
|
|
||||||
}
|
|
||||||
if(options.privateKey) {
|
|
||||||
options.privateKey = packetlistCloneToKey(options.privateKey);
|
|
||||||
}
|
|
||||||
if (options.message && method === 'verify') { // verify supports only CleartextMessage
|
|
||||||
options.message = packetlistCloneToCleartextMessage(options.message);
|
|
||||||
} else if (options.message) {
|
|
||||||
options.message = packetlistCloneToMessage(options.message);
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToKey(clone) {
|
|
||||||
var packetlist = window.openpgp.packet.List.fromStructuredClone(clone);
|
|
||||||
return new window.openpgp.key.Key(packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToMessage(clone) {
|
|
||||||
var packetlist = window.openpgp.packet.List.fromStructuredClone(clone.packets);
|
|
||||||
return new window.openpgp.message.Message(packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function packetlistCloneToCleartextMessage(clone) {
|
|
||||||
var packetlist = window.openpgp.packet.List.fromStructuredClone(clone.packets);
|
|
||||||
return new window.openpgp.cleartext.CleartextMessage(clone.text, packetlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clonePackets(data) {
|
|
||||||
if (data.key) {
|
|
||||||
data.key = data.key.toPacketlist();
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function response(event) {
|
function response(event) {
|
||||||
if (window.openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
|
if (openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
|
||||||
self.postMessage({event: 'request-seed'});
|
self.postMessage({event: 'request-seed'});
|
||||||
}
|
}
|
||||||
self.postMessage(event, window.openpgp.util.getTransferables.call(window.openpgp.util, event.data));
|
self.postMessage(event, openpgp.util.getTransferables.call(openpgp.util, event.data));
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user