Move methods of Key and Message class to prototype. Clean up openpgp.js file.

This commit is contained in:
Thomas Oberndörfer 2013-12-02 14:54:05 +01:00
parent 89eb5dff2a
commit be96de5188
5 changed files with 1858 additions and 2419 deletions

File diff suppressed because one or more lines are too long

View File

@ -22,21 +22,23 @@ var config = require('./config');
/** /**
* @class * @class
* @classdesc Class that represents an OpenPGP key. Must contain a master key. * @classdesc Class that represents an OpenPGP key. Must contain a primary key.
* @param {packetlist} packetlist [description] * Can contain additional subkeys, signatures, user ids, user attributes.
* Can contain additional subkeys, signatures, * @param {packetlist} packetlist The packets that form this key
* user ids, user attributes.
*/ */
function key(packetlist) { function Key(packetlist) {
if (!(this instanceof Key)) {
return new Key(packetlist);
}
this.packets = packetlist || new packet.list(); this.packets = packetlist || new packet.list();
}
/** /**
* Returns the primary key packet (secret or public) * Returns the primary key packet (secret or public)
* @returns {packet_secret_key|packet_public_key|null} * @returns {packet_secret_key|packet_public_key|null}
*/ */
this.getKeyPacket = function() { Key.prototype.getKeyPacket = function() {
for (var i = 0; i < this.packets.length; i++) { for (var i = 0; i < this.packets.length; i++) {
if (this.packets[i].tag == enums.packet.public_key || if (this.packets[i].tag == enums.packet.public_key ||
this.packets[i].tag == enums.packet.secret_key) { this.packets[i].tag == enums.packet.secret_key) {
@ -44,13 +46,13 @@ var config = require('./config');
} }
} }
return null; return null;
} };
/** /**
* Returns all the private and public subkey packets * Returns all the private and public subkey packets
* @returns {[public_subkey|secret_subkey]} * @returns {[public_subkey|secret_subkey]}
*/ */
this.getSubkeyPackets = function() { Key.prototype.getSubkeyPackets = function() {
var subkeys = []; var subkeys = [];
@ -62,30 +64,30 @@ var config = require('./config');
} }
return subkeys; return subkeys;
} };
/** /**
* Returns all the private and public key and subkey packets * Returns all the private and public key and subkey packets
* @returns {[public_subkey|secret_subkey|packet_secret_key|packet_public_key]} * @returns {[public_subkey|secret_subkey|packet_secret_key|packet_public_key]}
*/ */
this.getAllKeyPackets = function() { Key.prototype.getAllKeyPackets = function() {
return [this.getKeyPacket()].concat(this.getSubkeyPackets()); return [this.getKeyPacket()].concat(this.getSubkeyPackets());
} };
/** /**
* Returns key IDs of all key packets * Returns key IDs of all key packets
* @returns {[keyid]} * @returns {[keyid]}
*/ */
this.getKeyIds = function() { Key.prototype.getKeyIds = function() {
var keyIds = []; var keyIds = [];
var keys = this.getAllKeyPackets(); var keys = this.getAllKeyPackets();
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
keyIds.push(keys[i].getKeyId()); keyIds.push(keys[i].getKeyId());
} }
return keyIds; return keyIds;
} };
function findKey(keys, keyIds) { function findKey(keys, keyIds) {
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
var keyId = keys[i].getKeyId(); var keyId = keys[i].getKeyId();
for (var j = 0; j < keyIds.length; j++) { for (var j = 0; j < keyIds.length; j++) {
@ -95,51 +97,51 @@ var config = require('./config');
} }
} }
return null; return null;
} }
/** /**
* Returns first public key packet for given array of key IDs * Returns first public key packet for given array of key IDs
* @param {[keyid]} keyIds * @param {[keyid]} keyIds
* @return {public_subkey|packet_public_key|null} * @return {public_subkey|packet_public_key|null}
*/ */
this.getPublicKeyPacket = function(keyIds) { Key.prototype.getPublicKeyPacket = function(keyIds) {
var keys = this.packets.filterByTag(enums.packet.public_key, enums.packet.public_subkey); var keys = this.packets.filterByTag(enums.packet.public_key, enums.packet.public_subkey);
return findKey(keys, keyIds); return findKey(keys, keyIds);
} };
/** /**
* Returns first private key packet for given array of key IDs * Returns first private key packet for given array of key IDs
* @param {[keyid]} keyIds * @param {[keyid]} keyIds
* @return {secret_subkey|packet_secret_key|null} * @return {secret_subkey|packet_secret_key|null}
*/ */
this.getPrivateKeyPacket = function(keyIds) { Key.prototype.getPrivateKeyPacket = function(keyIds) {
var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey); var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey);
return findKey(keys, keyIds); return findKey(keys, keyIds);
} };
/** /**
* Returns true if this is a public key * Returns true if this is a public key
* @return {Boolean} * @return {Boolean}
*/ */
this.isPublic = function() { Key.prototype.isPublic = function() {
var publicKeyPackets = this.packets.filterByTag(enums.packet.public_key); var publicKeyPackets = this.packets.filterByTag(enums.packet.public_key);
return publicKeyPackets.length ? true : false; return publicKeyPackets.length ? true : false;
} };
/** /**
* Returns true if this is a private key * Returns true if this is a private key
* @return {Boolean} * @return {Boolean}
*/ */
this.isPrivate = function() { Key.prototype.isPrivate = function() {
var privateKeyPackets = this.packets.filterByTag(enums.packet.private_key); var privateKeyPackets = this.packets.filterByTag(enums.packet.private_key);
return privateKeyPackets.length ? true : false; return privateKeyPackets.length ? true : false;
} };
/** /**
* Returns key as public key * Returns key as public key
* @return {key} public key * @return {key} public key
*/ */
this.toPublic = function() { Key.prototype.toPublic = function() {
for (var i = 0; i < this.packets.length; i++) { for (var i = 0; i < this.packets.length; i++) {
if (this.packets[i].tag == enums.packet.secret_key) { if (this.packets[i].tag == enums.packet.secret_key) {
var bytes = this.packets[i].writePublicKey(); var bytes = this.packets[i].writePublicKey();
@ -155,22 +157,22 @@ var config = require('./config');
} }
} }
return this; return this;
} };
/** /**
* Returns ASCII armored text of key * Returns ASCII armored text of key
* @return {String} ASCII armor * @return {String} ASCII armor
*/ */
this.armor = function() { Key.prototype.armor = function() {
var type = this.isPublic() ? enums.armor.public_key : enums.armor.private_key; var type = this.isPublic() ? enums.armor.public_key : enums.armor.private_key;
return armor.encode(type, this.packets.write()); return armor.encode(type, this.packets.write());
} };
/** /**
* Returns first key packet that is available for signing * Returns first key packet that is available for signing
* @return {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null} * @return {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null}
*/ */
this.getSigningKeyPacket = function() { Key.prototype.getSigningKeyPacket = function() {
var signing = [ enums.publicKey.rsa_encrypt_sign, enums.publicKey.rsa_sign, enums.publicKey.dsa]; var signing = [ enums.publicKey.rsa_encrypt_sign, enums.publicKey.rsa_sign, enums.publicKey.dsa];
@ -187,23 +189,23 @@ var config = require('./config');
} }
return null; return null;
} };
/** /**
* Returns preferred signature hash algorithm of this key * Returns preferred signature hash algorithm of this key
* @return {String} * @return {String}
*/ */
function getPreferredSignatureHashAlgorithm() { Key.prototype.getPreferredSignatureHashAlgorithm = function() {
//TODO implement: https://tools.ietf.org/html/rfc4880#section-5.2.3.8 //TODO implement: https://tools.ietf.org/html/rfc4880#section-5.2.3.8
//separate private key preference from digest preferences //separate private key preference from digest preferences
return config.prefer_hash_algorithm; return config.prefer_hash_algorithm;
} };
/** /**
* Returns the first valid encryption key packet for this key * Returns the first valid encryption key packet for this key
* @returns {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null} key packet or null if no encryption key has been found * @returns {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null} key packet or null if no encryption key has been found
*/ */
this.getEncryptionKeyPacket = function() { Key.prototype.getEncryptionKeyPacket = function() {
// V4: by convention subkeys are prefered for encryption service // V4: by convention subkeys are prefered for encryption service
// V3: keys MUST NOT have subkeys // V3: keys MUST NOT have subkeys
var isValidEncryptionKey = function(key) { var isValidEncryptionKey = function(key) {
@ -227,29 +229,29 @@ var config = require('./config');
return primaryKey; return primaryKey;
} }
return null; return null;
} };
/** /**
* Decrypts all secret key and subkey packets * Decrypts all secret key and subkey packets
* @param {String} passphrase * @param {String} passphrase
* @return {Boolean} true if all key and subkey packets decrypted successfully * @return {Boolean} true if all key and subkey packets decrypted successfully
*/ */
this.decrypt = function(passphrase) { Key.prototype.decrypt = function(passphrase) {
var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey); var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey);
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
var success = keys[i].decrypt(passphrase); var success = keys[i].decrypt(passphrase);
if (!success) return false; if (!success) return false;
} }
return true; return true;
} };
/** /**
* Decrypts specific key packets by key ID * Decrypts specific key packets by key ID
* @param {[keyid]} keyIds * @param {[keyid]} keyIds
* @param {String} passphrase * @param {String} passphrase
* @return {Boolean} true if all key packets decrypted successfully * @return {Boolean} true if all key packets decrypted successfully
*/ */
this.decryptKeyPacket = function(keyIds, passphrase) { Key.prototype.decryptKeyPacket = function(keyIds, passphrase) {
//TODO return value //TODO return value
var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey); var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey);
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
@ -262,32 +264,32 @@ var config = require('./config');
} }
} }
return true; return true;
} };
// TODO // TODO
this.verify = function() { Key.prototype.verify = function() {
} };
// TODO // TODO
this.revoke = function() { Key.prototype.revoke = function() {
} };
}
/** /**
* reads an OpenPGP armored text and returns a key object * reads an OpenPGP armored text and returns a key object
* @param {String} armoredText text to be parsed * @param {String} armoredText text to be parsed
* @return {key} new key object * @return {key} new key object
*/ */
key.readArmored = function(armoredText) { function readArmored(armoredText) {
//TODO how do we want to handle bad text? Exception throwing //TODO how do we want to handle bad text? Exception throwing
//TODO don't accept non-key armored texts //TODO don't accept non-key armored texts
var input = armor.decode(armoredText).data; var input = armor.decode(armoredText).data;
var packetlist = new packet.list(); var packetlist = new packet.list();
packetlist.read(input); packetlist.read(input);
var newKey = new key(packetlist); var newKey = new Key(packetlist);
return newKey; return newKey;
} }
module.exports = key; exports.Key = Key;
exports.readArmored = readArmored;

View File

@ -24,31 +24,36 @@ var util = require('./util');
/** /**
* @class * @class
* @classdesc A generic message containing one or more literal packets. * @classdesc Class that represents an OpenPGP message.
* Can be an encrypted message, signed message, compressed message or literal message
* See http://tools.ietf.org/html/rfc4880#section-11.3
*/ */
function message(packetlist) { function Message(packetlist) {
if (!(this instanceof Message)) {
return new Message(packetlist);
}
this.packets = packetlist || new packet.list(); this.packets = packetlist || new packet.list();
}
/** /**
* Returns the key IDs of the keys to which the session key is encrypted * Returns the key IDs of the keys to which the session key is encrypted
* @return {[keyId]} array of keyid objects * @return {[keyId]} array of keyid objects
*/ */
this.getEncryptionKeyIds = function() { Message.prototype.getEncryptionKeyIds = function() {
var keyIds = []; var keyIds = [];
var pkESKeyPacketlist = this.packets.filterByTag(enums.packet.public_key_encrypted_session_key); var pkESKeyPacketlist = this.packets.filterByTag(enums.packet.public_key_encrypted_session_key);
pkESKeyPacketlist.forEach(function(packet) { pkESKeyPacketlist.forEach(function(packet) {
keyIds.push(packet.publicKeyId); keyIds.push(packet.publicKeyId);
}); });
return keyIds; return keyIds;
} };
/** /**
* Returns the key IDs of the keys that signed the message * Returns the key IDs of the keys that signed the message
* @return {[keyId]} array of keyid objects * @return {[keyId]} array of keyid objects
*/ */
this.getSigningKeyIds = function() { Message.prototype.getSigningKeyIds = function() {
var keyIds = []; var keyIds = [];
var msg = this.unwrapCompressed(); var msg = this.unwrapCompressed();
// search for one pass signatures // search for one pass signatures
@ -64,14 +69,14 @@ function message(packetlist) {
}); });
} }
return keyIds; return keyIds;
} };
/** /**
* Decrypt the message * Decrypt the message
* @param {key} privateKey private key with decrypted secret data * @param {key} privateKey private key with decrypted secret data
* @return {[message]} new message with decrypted content * @return {[message]} new message with decrypted content
*/ */
this.decrypt = function(privateKey) { Message.prototype.decrypt = function(privateKey) {
var encryptionKeyIds = this.getEncryptionKeyIds(); var encryptionKeyIds = this.getEncryptionKeyIds();
if (!encryptionKeyIds.length) { if (!encryptionKeyIds.length) {
// nothing to decrypt return unmodified message // nothing to decrypt return unmodified message
@ -93,25 +98,25 @@ function message(packetlist) {
if (symEncryptedPacketlist.length !== 0) { if (symEncryptedPacketlist.length !== 0) {
var symEncryptedPacket = symEncryptedPacketlist[0]; var symEncryptedPacket = symEncryptedPacketlist[0];
symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey); symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey);
return new message(symEncryptedPacket.packets); return new Message(symEncryptedPacket.packets);
}
} }
} }
};
/** /**
* Get literal data that is the body of the message * Get literal data that is the body of the message
* @return {String|null} literal body of the message as string * @return {String|null} literal body of the message as string
*/ */
this.getLiteralData = function() { Message.prototype.getLiteralData = function() {
var literal = this.packets.findPacket(enums.packet.literal); var literal = this.packets.findPacket(enums.packet.literal);
return literal && literal.data || null; return literal && literal.data || null;
} };
/** /**
* Get literal data as text * Get literal data as text
* @return {String|null} literal body of the message interpreted as text * @return {String|null} literal body of the message interpreted as text
*/ */
this.getText = function() { Message.prototype.getText = function() {
var literal = this.packets.findPacket(enums.packet.literal); var literal = this.packets.findPacket(enums.packet.literal);
if (literal) { if (literal) {
var data = literal.data; var data = literal.data;
@ -124,14 +129,14 @@ function message(packetlist) {
} else { } else {
return null; return null;
} }
} };
/** /**
* Encrypt the message * Encrypt the message
* @param {[key]} keys array of keys, used to encrypt the message * @param {[key]} keys array of keys, used to encrypt the message
* @return {[message]} new message with encrypted content * @return {[message]} new message with encrypted content
*/ */
this.encrypt = function(keys) { Message.prototype.encrypt = function(keys) {
var packetlist = new packet.list(); var packetlist = new packet.list();
//TODO get preferred algo from signature //TODO get preferred algo from signature
var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, config.encryption_cipher)); var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, config.encryption_cipher));
@ -158,15 +163,15 @@ function message(packetlist) {
//TODO get preferred algo from signature //TODO get preferred algo from signature
symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey); symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey);
packetlist.push(symEncryptedPacket); packetlist.push(symEncryptedPacket);
return new message(packetlist); return new Message(packetlist);
} };
/** /**
* Sign the message (the literal data packet of the message) * Sign the message (the literal data packet of the message)
* @param {[key]} privateKey private keys with decrypted secret key data for signing * @param {[key]} privateKey private keys with decrypted secret key data for signing
* @return {message} new message with signed content * @return {message} new message with signed content
*/ */
this.sign = function(privateKeys) { Message.prototype.sign = function(privateKeys) {
var packetlist = new packet.list(); var packetlist = new packet.list();
@ -200,15 +205,15 @@ function message(packetlist) {
packetlist.push(signaturePacket); packetlist.push(signaturePacket);
} }
return new message(packetlist); return new Message(packetlist);
} };
/** /**
* Verify message signatures * Verify message signatures
* @param {[key]} publicKeys public keys to verify signatures * @param {[key]} publicKeys public keys to verify signatures
* @return {[{'keyid': keyid, 'valid': Boolean}]} list of signer's keyid and validity of signature * @return {[{'keyid': keyid, 'valid': Boolean}]} list of signer's keyid and validity of signature
*/ */
this.verify = function(publicKeys) { Message.prototype.verify = function(publicKeys) {
var result = []; var result = [];
var msg = this.unwrapCompressed(); var msg = this.unwrapCompressed();
var literalDataList = msg.packets.filterByTag(enums.packet.literal); var literalDataList = msg.packets.filterByTag(enums.packet.literal);
@ -227,119 +232,41 @@ function message(packetlist) {
} }
}); });
return result; return result;
} };
/** /**
* Unwrap compressed message * Unwrap compressed message
* @return {message} message Content of compressed message * @return {message} message Content of compressed message
*/ */
this.unwrapCompressed = function() { Message.prototype.unwrapCompressed = function() {
var compressed = this.packets.filterByTag(enums.packet.compressed); var compressed = this.packets.filterByTag(enums.packet.compressed);
if (compressed.length) { if (compressed.length) {
return new message(compressed[0].packets); return new Message(compressed[0].packets);
} else { } else {
return this; return this;
} }
} };
/** /**
* Returns ASCII armored text of message * Returns ASCII armored text of message
* @return {String} ASCII armor * @return {String} ASCII armor
*/ */
this.armor = function() { Message.prototype.armor = function() {
return armor.encode(enums.armor.message, this.packets.write()); return armor.encode(enums.armor.message, this.packets.write());
} };
/**
* Decrypts a message and generates user interface message out of the found.
* MDC will be verified as well as message signatures
* @param {openpgp_msg_privatekey} private_key the private the message is encrypted with (corresponding to the session key)
* @param {openpgp_packet_encryptedsessionkey} sessionkey the session key to be used to decrypt the message
* @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
* @return {String} plaintext of the message or null on error
*/
function decryptAndVerifySignature(private_key, sessionkey, pubkey) {
if (private_key == null || sessionkey == null || sessionkey == "")
return null;
var decrypted = sessionkey.decrypt(this, private_key.keymaterial);
if (decrypted == null)
return null;
var packet;
var position = 0;
var len = decrypted.length;
var validSignatures = new Array();
util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n", decrypted);
var messages = openpgp.read_messages_dearmored({
text: decrypted,
openpgp: decrypted
});
for (var m in messages) {
if (messages[m].data) {
this.text = messages[m].data;
}
if (messages[m].signature) {
validSignatures.push(messages[m].verifySignature(pubkey));
}
}
return {
text: this.text,
validSignatures: validSignatures
};
}
/**
* Verifies a message signature. This function can be called after read_message if the message was signed only.
* @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
* @return {boolean} true if the signature was correct; otherwise false
*/
function verifySignature(pubkey) {
var result = false;
if (this.signature.tagType == 2) {
if (!pubkey || pubkey.length == 0) {
var pubkey;
if (this.signature.version == 4) {
pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);
} else if (this.signature.version == 3) {
pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);
} else {
util.print_error("unknown signature type on message!");
return false;
}
}
if (pubkey.length == 0)
util.print_warning("Unable to verify signature of issuer: " + util.hexstrdump(this.signature.issuerKeyId) +
". Public key not found in keyring.");
else {
for (var i = 0; i < pubkey.length; i++) {
var tohash = this.text.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n");
if (this.signature.verify(tohash, pubkey[i])) {
util.print_info("Found Good Signature from " + pubkey[i].obj.userIds[0].text + " (0x" + util.hexstrdump(
pubkey[i].obj.getKeyId()).substring(8) + ")");
result = true;
} else {
util.print_error("Signature verification failed: Bad Signature from " + pubkey[i].obj.userIds[0].text +
" (0x" + util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8) + ")");
}
}
}
}
return result;
}
}
/** /**
* reads an OpenPGP armored message and returns a message object * reads an OpenPGP armored message and returns a message object
* @param {String} armoredText text to be parsed * @param {String} armoredText text to be parsed
* @return {message} new message object * @return {message} new message object
*/ */
message.readArmored = function(armoredText) { function readArmored(armoredText) {
//TODO how do we want to handle bad text? Exception throwing //TODO how do we want to handle bad text? Exception throwing
//TODO don't accept non-message armored texts //TODO don't accept non-message armored texts
var input = armor.decode(armoredText).data; var input = armor.decode(armoredText).data;
var packetlist = new packet.list(); var packetlist = new packet.list();
packetlist.read(input); packetlist.read(input);
var newMessage = new message(packetlist); var newMessage = new Message(packetlist);
return newMessage; return newMessage;
} }
@ -348,14 +275,16 @@ message.readArmored = function(armoredText) {
* @param {String} text * @param {String} text
* @return {message} new message object * @return {message} new message object
*/ */
message.fromText = function(text) { function fromText(text) {
var literalDataPacket = new packet.literal(); var literalDataPacket = new packet.literal();
// text will be converted to UTF8 // text will be converted to UTF8
literalDataPacket.set(text); literalDataPacket.set(text);
var literalDataPacketlist = new packet.list(); var literalDataPacketlist = new packet.list();
literalDataPacketlist.push(literalDataPacket); literalDataPacketlist.push(literalDataPacket);
var newMessage = new message(literalDataPacketlist); var newMessage = new Message(literalDataPacketlist);
return newMessage; return newMessage;
} }
module.exports = message; exports.Message = Message;
exports.readArmored = readArmored;
exports.fromText = fromText;

View File

@ -16,68 +16,59 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/** /**
* @fileoverview The openpgp base class should provide all of the functionality * @fileoverview The openpgp base module should provide all of the functionality
* to consume the openpgp.js library. All additional classes are documented * to consume the openpgp.js library. All additional classes are documented
* for extending and developing on top of the base library. * for extending and developing on top of the base library.
*/ */
var armor = require('./encoding/armor.js'); var armor = require('./encoding/armor.js');
var packet = require('./packet'); var packet = require('./packet');
var util = require('./util');
var enums = require('./enums.js'); var enums = require('./enums.js');
var config = require('./config'); var config = require('./config');
var message = require('./message.js'); var message = require('./message.js');
/**
* GPG4Browsers Core interface. A single instance is hold
* from the beginning. To use this library call "openpgp.init()"
* @alias openpgp
* @class
* @classdesc Main Openpgp.js class. Use this to initiate and make all calls to this library.
*/
function _openpgp() {
/** /**
* Encrypts message text with keys * Encrypts message text with keys
* @param {[key]} keys array of keys, used to encrypt the message * @param {[key]} keys array of keys, used to encrypt the message
* @param {String} text message as native JavaScript string * @param {String} text message as native JavaScript string
* @return {String} encrypted ASCII armored message * @return {String} encrypted ASCII armored message
*/ */
function encryptMessage(keys, text) { function encryptMessage(keys, text) {
var msg = message.fromText(text); var msg = message.fromText(text);
msg = msg.encrypt(keys); msg = msg.encrypt(keys);
var armored = armor.encode(enums.armor.message, msg.packets.write()); var armored = armor.encode(enums.armor.message, msg.packets.write());
return armored; return armored;
} }
/** /**
* Signs message text and encrypts it * Signs message text and encrypts it
* @param {[key]} publicKeys array of keys, used to encrypt the message * @param {[key]} publicKeys array of keys, used to encrypt the message
* @param {key} privateKey private key with decrypted secret key data for signing * @param {key} privateKey private key with decrypted secret key data for signing
* @param {String} text message as native JavaScript string * @param {String} text message as native JavaScript string
* @return {String} encrypted ASCII armored message * @return {String} encrypted ASCII armored message
*/ */
function signAndEncryptMessage(publicKeys, privateKey, text) { function signAndEncryptMessage(publicKeys, privateKey, text) {
var msg = message.fromText(text); var msg = message.fromText(text);
msg = msg.sign([privateKey]); msg = msg.sign([privateKey]);
msg = msg.encrypt(publicKeys); msg = msg.encrypt(publicKeys);
var armored = armor.encode(enums.armor.message, msg.packets.write()); var armored = armor.encode(enums.armor.message, msg.packets.write());
return armored; return armored;
} }
/** /**
* Decrypts message * Decrypts message
* @param {key} privateKey private key with decrypted secret key data * @param {key} privateKey private key with decrypted secret key data
* @param {message} message the message object with the encrypted data * @param {message} message the message object with the encrypted data
* @return {String|null} decrypted message as as native JavaScript string * @return {String|null} decrypted message as as native JavaScript string
* or null if no literal data found * or null if no literal data found
*/ */
function decryptMessage(privateKey, message) { function decryptMessage(privateKey, message) {
message = message.decrypt(privateKey); message = message.decrypt(privateKey);
return message.getText(); return message.getText();
} }
/** /**
* Decrypts message and verifies signatures * Decrypts message and verifies signatures
* @param {key} privateKey private key with decrypted secret key data * @param {key} privateKey private key with decrypted secret key data
* @param {[key]} publicKeys public keys to verify signatures * @param {[key]} publicKeys public keys to verify signatures
@ -86,7 +77,7 @@ function _openpgp() {
* decrypted message as as native JavaScript string * decrypted message as as native JavaScript string
* with verified signatures or null if no literal data found * with verified signatures or null if no literal data found
*/ */
function decryptAndVerifyMessage(privateKey, publicKeys, message) { function decryptAndVerifyMessage(privateKey, publicKeys, message) {
var result = {}; var result = {};
message = message.decrypt(privateKey); message = message.decrypt(privateKey);
result.text = message.getText(); result.text = message.getText();
@ -95,17 +86,19 @@ function _openpgp() {
return result; return result;
} }
return null; return null;
} }
function verifyMessage(publicKeys, messagePacketlist) { function signClearMessage(privateKeys, text) {
} }
function signMessage(privateKey, messagePacketlist) { function verifyClearSignedMessage(publicKeys, message) {
} }
/**
/**
* TODO: update this doc * TODO: update this doc
* generates a new key pair for openpgp. Beta stage. Currently only * generates a new key pair for openpgp. Beta stage. Currently only
* supports RSA keys, and no subkeys. * supports RSA keys, and no subkeys.
@ -119,7 +112,7 @@ function _openpgp() {
* @return {Object} {privateKey: [openpgp_msg_privatekey], * @return {Object} {privateKey: [openpgp_msg_privatekey],
* privateKeyArmored: [string], publicKeyArmored: [string]} * privateKeyArmored: [string], publicKeyArmored: [string]}
*/ */
function generateKeyPair(keyType, numBits, userId, passphrase) { function generateKeyPair(keyType, numBits, userId, passphrase) {
var packetlist = new packet.list(); var packetlist = new packet.list();
var secretKeyPacket = new packet.secret_key(); var secretKeyPacket = new packet.secret_key();
@ -165,119 +158,9 @@ function _openpgp() {
var armored = armor.encode(enums.armor.private_key, packetlist.write()); var armored = armor.encode(enums.armor.private_key, packetlist.write());
return armored; return armored;
} }
/** /**
* creates a binary string representation of an encrypted and signed message.
* The message will be encrypted with the public keys specified and signed
* with the specified private key.
* @param {Object} privatekey {obj: [openpgp_msg_privatekey]} Private key
* to be used to sign the message
* @param {Object[]} publickeys An arraf of {obj: [openpgp_msg_publickey]}
* - public keys to be used to encrypt the message
* @param {String} messagetext message text to encrypt and sign
* @return {String} a binary string representation of the message which
* can be OpenPGP armored
*/
function write_signed_and_encrypted_message(privatekey, publickeys, messagetext) {
var result = "";
var i;
var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g, "\n").replace(/\n/g,
"\r\n"));
util.print_debug_hexstr_dump("literal_packet: |" + literal + "|\n", literal);
for (i = 0; i < publickeys.length; i++) {
var onepasssignature = new openpgp_packet_onepasssignature();
var onepasssigstr = "";
if (i === 0)
onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm, privatekey, false);
else
onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm, privatekey, false);
util.print_debug_hexstr_dump("onepasssigstr: |" + onepasssigstr + "|\n", onepasssigstr);
var datasignature = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g, "\n").replace(
/\n/g, "\r\n"), privatekey);
util.print_debug_hexstr_dump("datasignature: |" + datasignature.openpgp + "|\n", datasignature.openpgp);
if (i === 0) {
result = onepasssigstr + literal + datasignature.openpgp;
} else {
result = onepasssigstr + result + datasignature.openpgp;
}
}
util.print_debug_hexstr_dump("signed packet: |" + result + "|\n", result);
// signatures done.. now encryption
var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
var result2 = "";
// creating session keys for each recipient
for (i = 0; i < publickeys.length; i++) {
var pkey = publickeys[i].getEncryptionKey();
if (pkey === null) {
util.print_error("no encryption key found! Key is for signing only.");
return null;
}
result2 += new openpgp_packet_encryptedsessionkey().
write_pub_key_packet(
pkey.getKeyId(),
pkey.MPIs,
pkey.publicKeyAlgorithm,
openpgp.config.config.encryption_cipher,
sessionkey);
}
if (openpgp.config.config.integrity_protect) {
result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher,
sessionkey, result);
} else {
result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey,
result);
}
return armor.encode(3, result2, null, null);
}
/**
* creates a binary string representation of an encrypted message.
* The message will be encrypted with the public keys specified
* @param {Object[]} publickeys An array of {obj: [openpgp_msg_publickey]}
* -public keys to be used to encrypt the message
* @param {String} messagetext message text to encrypt
* @return {String} a binary string representation of the message
* which can be OpenPGP armored
*/
function write_encrypted_message(publickeys, messagetext) {
var result = "";
var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g, "\n").replace(/\n/g,
"\r\n"));
util.print_debug_hexstr_dump("literal_packet: |" + literal + "|\n", literal);
result = literal;
// signatures done.. now encryption
var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
var result2 = "";
// creating session keys for each recipient
for (var i = 0; i < publickeys.length; i++) {
var pkey = publickeys[i].getEncryptionKey();
if (pkey === null) {
util.print_error("no encryption key found! Key is for signing only.");
return null;
}
result2 += new openpgp_packet_encryptedsessionkey().
write_pub_key_packet(
pkey.getKeyId(),
pkey.MPIs,
pkey.publicKeyAlgorithm,
openpgp.config.config.encryption_cipher,
sessionkey);
}
if (openpgp.config.config.integrity_protect) {
result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher,
sessionkey, result);
} else {
result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey,
result);
}
return armor.encode(3, result2, null, null);
}
/**
* creates a binary string representation a signed message. * creates a binary string representation a signed message.
* The message will be signed with the specified private key. * The message will be signed with the specified private key.
* @param {Object} privatekey {obj: [openpgp_msg_privatekey]} * @param {Object} privatekey {obj: [openpgp_msg_privatekey]}
@ -288,7 +171,8 @@ function _openpgp() {
* armored(openpgp) and a text representation of the message (text). * armored(openpgp) and a text representation of the message (text).
* This can be directly used to OpenPGP armor the message * This can be directly used to OpenPGP armor the message
*/ */
function write_signed_message(privatekey, messagetext) { /*
function write_signed_message(privatekey, messagetext) {
var sig = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g, "\n").replace(/\n/, var sig = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g, "\n").replace(/\n/,
"\r\n"), privatekey); "\r\n"), privatekey);
var result = { var result = {
@ -297,15 +181,13 @@ function _openpgp() {
hash: sig.hash hash: sig.hash
}; };
return armor.encode(2, result, null, null); return armor.encode(2, result, null, null);
}
this.generateKeyPair = generateKeyPair;
this.write_signed_message = write_signed_message;
this.signAndEncryptMessage = signAndEncryptMessage;
this.decryptAndVerifyMessage = decryptAndVerifyMessage
this.encryptMessage = encryptMessage;
this.decryptMessage = decryptMessage;
} }
*/
module.exports = new _openpgp(); exports.encryptMessage = encryptMessage;
exports.signAndEncryptMessage = signAndEncryptMessage;
exports.decryptMessage = decryptMessage;
exports.decryptAndVerifyMessage = decryptAndVerifyMessage
exports.signClearMessage = signClearMessage;
exports.verifyClearSignedMessage = verifyClearSignedMessage;
exports.generateKeyPair = generateKeyPair;

File diff suppressed because one or more lines are too long