Refactoring message and key class. Implement decryptMessage.

This commit is contained in:
Thomas Oberndörfer 2013-10-21 20:51:46 +02:00
parent 91070f9750
commit b1c9eb71d2
10 changed files with 1275 additions and 782 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
var crypto = require('./crypto');
module.exports = require('./openpgp.js');
module.exports.key = require('./key.js');
module.exports.message = require('./message.js');
module.exports.util = require('./util');
module.exports.packet = require('./packet');
module.exports.mpi = require('./type/mpi.js');
@ -9,6 +10,4 @@ module.exports.keyid = require('./type/keyid.js');
module.exports.armor = require('./encoding/armor.js');
module.exports.enums = require('./enums.js');
module.exports.config = require('./config');
for (var i in crypto)
module.exports[i] = crypto[i];
module.exports.crypto = require('./crypto');

View File

@ -17,40 +17,45 @@
var packet = require('./packet');
var enums = require('./enums.js');
var armor = require('./encoding/armor.js');
/**
* @class
* @classdesc Class that represents an OpenPGP key. Must contain a master key.
* @param {packetlist} packetlist [description]
* Can contain additional subkeys, signatures,
* user ids, user attributes.
*/
module.exports = function key() {
function key(packetlist) {
this.packets = packetlist || new packet.list();
this.packets = new packet.list();
/** Returns the primary key (secret or public)
* @returns {openpgp_packet_secret_key|openpgp_packet_public_key|null} */
* @returns {packet_secret_key|packet_public_key|null} */
this.getKey = 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 ||
this.packets[i].tag == enums.packet.secret_key)
this.packets[i].tag == enums.packet.secret_key) {
return this.packets[i];
}
}
return null;
};
/** Returns all the private and public subkeys
* @returns {openpgp_packet_subkey[]} */
* @returns {[public_subkey|secret_subkey]} */
this.getSubkeys = function() {
var subkeys = [];
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_subkey ||
this.packets[i].tag == enums.packet.secret_subkey)
this.packets[i].tag == enums.packet.secret_subkey) {
subkeys.push(this.packets[i]);
}
}
return subkeys;
};
@ -59,18 +64,39 @@ module.exports = function key() {
return [this.getKey()].concat(this.getSubkeys());
};
this.getKeyids = function() {
var keyids = [];
var keys = this.getAllKeys();
for (var i = 0; i < keys.length; i++) {
keyids.push(keys[i].getKeyId());
}
return keyids;
};
this.getKeyById = function(keyid) {
var keys = this.getAllKeys();
for (var i = 0; i < keys.length; i++) {
if (keys[i].getKeyId().equals(keyid)) {
return keys[i];
}
}
}
this.getSigningKey = function() {
var signing = ['rsa_encrypt_sign', 'rsa_sign', 'dsa'];
var signing = [ enums.publicKey.rsa_encrypt_sign, enums.publicKey.rsa_sign, enums.publicKey.dsa];
signing = signing.map(function(s) {
return openpgp.publickey[s];
return enums.read(enums.publicKey, s);
});
var keys = this.getAllKeys();
for (var i in keys)
if (signing.indexOf(keys[i].public_algorithm) != -1)
for (var i = 0; i < keys.length; i++) {
if (signing.indexOf(keys[i].algorithm) !== -1) {
return keys[i];
}
}
return null;
};
@ -97,22 +123,23 @@ module.exports = function key() {
this.getEncryptionKey = function() {
// V4: by convention subkeys are prefered for encryption service
// V3: keys MUST NOT have subkeys
var isValidSignKey = function(key) {
var isValidEncryptionKey = function(key) {
return key.algorithm != enums.read(enums.publicKey, enums.publicKey.dsa) && key.algorithm != enums.read(enums.publicKey,
enums.publicKey.rsa_sign);
//TODO verify key
//&& keys.verifyKey()
};
var subKeys = this.getSubkeys();
for (var j = 0; j < subKeys.length; j++) {
if (isValidSignKey(subKeys[j])) {
return subKeys[j];
var subkeys = this.getSubkeys();
for (var j = 0; j < subkeys.length; j++) {
if (isValidEncryptionKey(subkeys[j])) {
return subkeys[j];
}
}
// if no valid subkey for encryption, use primary key
var primaryKey = this.getKey();
if (isValidSignKey(primaryKey)) {
if (isValidEncryptionKey(primaryKey)) {
return primaryKey;
}
return null;
@ -135,5 +162,20 @@ module.exports = function key() {
}
};
/**
* reads an OpenPGP armored text and returns a key object
* @param {String} armoredText text to be parsed
* @return {key} new key object
*/
key.readArmored = function(armoredText) {
//TODO how do we want to handle bad text? Exception throwing
var input = armor.decode(armoredText).openpgp;
var packetlist = new packet.list();
packetlist.read(input);
var newKey = new key(packetlist);
return newKey;
}
module.exports = key;

View File

@ -15,14 +15,31 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var packet = require('./packet');
var enums = require('./enums.js');
var armor = require('./encoding/armor.js');
/**
* @class
* @classdesc A generic message containing one or more literal packets.
*/
function openpgp_message() {
this.packets = new openpgp_packetlist();
function message(packetlist) {
this.packets = packetlist || new packet.list();
/**
* Returns the key IDs of the public keys to which the session key is encrypted
* @return {[keyId]} keyId provided as string of hex number (lowercase)
*/
this.getKeyIds = function() {
var keyIds = [];
var pkESKeyPacketlist = this.packets.filterByType(enums.packet.public_key_encrypted_session_key);
pkESKeyPacketlist.forEach(function(packet) {
keyIds.push(packet.publicKeyId.toHex());
});
return keyIds;
}
function generic_decrypt(packets, passphrase) {
var sessionkey;
@ -44,7 +61,39 @@ function openpgp_message() {
* @return {} plaintext of the message or null on error
*/
this.decrypt = function(key) {
return this.decryptAndVerifySignature(private_key, sessionkey)
var decryptedMessages = [];
var keyids = key.getKeyids();
var pkESKeyPacketlist = this.packets.filterByType(enums.packet.public_key_encrypted_session_key);
outer: for (var i = 0; i < pkESKeyPacketlist.length; i++) {
var pkESKeyPacket = pkESKeyPacketlist[i];
for (var j = 0; j < keyids.length; j++) {
if (pkESKeyPacket.publicKeyId.equals(keyids[j])) {
pkESKeyPacket.decrypt(key.getKeyById(pkESKeyPacket.publicKeyId));
var symEncryptedPacketlist = this.packets.filter(function(packet) {
return packet.tag == enums.packet.symmetrically_encrypted || packet.tag == enums.packet.sym_encrypted_integrity_protected;
});
for (var k = 0; k < symEncryptedPacketlist.length; k++) {
var symEncryptedPacket = symEncryptedPacketlist[k];
symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey);
for (var l = 0; l < symEncryptedPacket.packets.length; l++) {
var dataPacket = symEncryptedPacket.packets[l];
switch (dataPacket.tag) {
case enums.packet.literal:
decryptedMessages.push(dataPacket.getBytes());
break;
case enums.packet.compressed:
//TODO
break;
default:
//TODO
}
}
}
break outer;
}
}
}
return decryptedMessages;
}
/**
@ -124,3 +173,19 @@ function openpgp_message() {
return result;
}
}
/**
* reads an OpenPGP armored message and returns a message object
* @param {String} armoredText text to be parsed
* @return {key} new message object
*/
message.readArmored = function(armoredText) {
//TODO how do we want to handle bad text? Exception throwing
var input = armor.decode(armoredText).openpgp;
var packetlist = new packet.list();
packetlist.read(input);
var newMessage = new message(packetlist);
return newMessage;
}
module.exports = message;

View File

@ -26,7 +26,6 @@ var packet = require('./packet');
var util = require('./util');
var enums = require('./enums.js');
var crypto = require('./crypto');
var key = require('./key.js');
var config = require('./config');
/**
@ -40,56 +39,20 @@ function _openpgp() {
this.tostring = "";
/**
* reads message packets out of an OpenPGP armored text and
* returns an array of message objects
* @param {String} armoredText text to be parsed
* @return {openpgp_msg_message[]} on error the function
* returns null
* encrypts message with keys
* @param {[key]} keys array of keys, used to encrypt the message
* @param {String} message text message as native JavaScript string
* @return {String} encrypted ASCII armored message
*/
function readArmoredPackets(armoredText) {
//TODO how do we want to handle bad text? Exception throwing
var input = armor.decode(armoredText.replace(/\r/g, '')).openpgp;
return readDearmoredPackets(input);
}
function encryptMessage(keys, message) {
/**
* reads message packets out of an OpenPGP armored text and
* returns an array of message objects. Can be called externally or internally.
* External call will parse a de-armored messaged and return messages found.
* Internal will be called to read packets wrapped in other packets (i.e. compressed)
* @param {String} input dearmored text of OpenPGP packets, to be parsed
* @return {openpgp_msg_message[]} on error the function
* returns null
*/
function readDearmoredPackets(input) {
var packetList = new packet.list();
packetList.read(input);
return packetList;
}
//TODO I think longterm we might actually want to just make key a subclass of packetlist
//passphrase is optional, this should work for both public and private
function getKeyFromPacketlist(keyPacketlist, passphrase){
var parsedKey = new key();
parsedKey.packets = keyPacketlist;
parsedKey.decrypt(passphrase);
return parsedKey;
}
function encryptMessage(publicKeys, message) {
var packetList = new packet.list();
var literalDataPacket = new packet.literal();
literalDataPacket.set(message, 'utf8');
var messagePacketlist = new packet.list();
//TODO get preferred algo from signature
var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, config.encryption_cipher));
publicKeys.forEach(function(publicKeyPacketlist) {
var pubKey = new key();
pubKey.packets = publicKeyPacketlist;
var encryptionKey = pubKey.getEncryptionKey();
keys.forEach(function(key) {
var encryptionKey = key.getEncryptionKey();
if (encryptionKey) {
var pkESKeyPacket = new packet.public_key_encrypted_session_key();
pkESKeyPacket.publicKeyId = encryptionKey.getKeyId();
@ -98,32 +61,42 @@ function _openpgp() {
//TODO get preferred algo from signature
pkESKeyPacket.sessionKeyAlgorithm = enums.read(enums.symmetric, config.encryption_cipher);
pkESKeyPacket.encrypt(encryptionKey);
packetList.push(pkESKeyPacket);
messagePacketlist.push(pkESKeyPacket);
}
});
var literalDataPacket = new packet.literal();
literalDataPacket.set(message, 'utf8');
var literalDataPacketlist = new packet.list();
literalDataPacketlist.push(literalDataPacket);
var symEncryptedPacket;
if (config.integrity_protect) {
symEncryptedPacket = new packet.sym_encrypted_integrity_protected();
} else {
symEncryptedPacket = new packet.symmetrically_encrypted();
}
symEncryptedPacket.packets = literalDataPacket;
symEncryptedPacket.packets = literalDataPacketlist;
//TODO get preferred algo from signature
symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey);
packetList.push(symEncryptedPacket);
messagePacketlist.push(symEncryptedPacket);
var armored = armor.encode(enums.armor.message, packetList.write(), config);
var armored = armor.encode(enums.armor.message, messagePacketlist.write(), config);
return armored;
}
function encryptAndSignMessage(publicKeys, privateKey, message) {
}
function decryptMessage(privateKey, messagePacketlist) {
/**
* decrypts message
* @param {[key]} decrypted privateKey
* @param {message} message the message object with the encrypted data
* @return {String} decrypted message as as native JavaScript string
*/
function decryptMessage(privateKey, message) {
return message.decrypt(privateKey);
}
function decryptAndVerifyMessage(privateKey, publicKeys, messagePacketlist) {
@ -336,9 +309,8 @@ function _openpgp() {
this.write_signed_message = write_signed_message;
this.write_signed_and_encrypted_message = write_signed_and_encrypted_message;
this.encryptMessage = encryptMessage;
this.readArmoredPackets = readArmoredPackets;
this.readDearmoredPackets = readDearmoredPackets;
this.getKeyFromPacketlist = getKeyFromPacketlist;
this.decryptMessage = decryptMessage;
}
module.exports = new _openpgp();

View File

@ -62,4 +62,38 @@ module.exports = function packetlist() {
this.length++;
}
/**
* Creates a new packetList with all packets that pass the test implemented by the provided function.
*/
this.filter = function(callback) {
var filtered = new packetlist();
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
filtered.push(this[i]);
}
}
return filtered;
}
/**
* Creates a new packetList with all packets from the given type
*/
this.filterByType = function(packetType) {
return this.filter(function(packet) {
return packet.tag == packetType;
});
}
/**
* Executes the provided callback once for each element
*/
this.forEach = function(callback) {
for (var i = 0; i < this.length; i++) {
callback(this[i]);
}
}
}

View File

@ -15,6 +15,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util');
/**
* @class
* @classdesc Implementation of type key id (RFC4880 3.3)
@ -24,10 +26,12 @@
formed.
*/
module.exports = function keyid() {
var bytes = '';
for (var i = 0; i < 8; i++)
bytes += String.fromCharCode(0);
this.bytes = '';
for (var i = 0; i < 8; i++) {
this.bytes += String.fromCharCode(0);
}
/**
* Parsing method for a key id
* @param {String} input Input to read the key id from
@ -42,4 +46,12 @@ module.exports = function keyid() {
this.write = function() {
return this.bytes;
}
this.toHex = function() {
return util.hexstrdump(this.bytes);
}
this.equals = function(keyid) {
return this.bytes == keyid.bytes;
}
};

View File

@ -2,7 +2,7 @@ var unit = require('../../unit.js');
unit.register("SHA* test with test vectors from NIST FIPS 180-2", function() {
var openpgp = require('../../../'),
var openpgp = require('../../../src'),
util = openpgp.util,
hash = openpgp.hash;

View File

@ -1,6 +1,6 @@
var unit = require('../unit.js');
unit.register("Encryption/decryption", function() {
unit.register("Key generation/encryption/decryption", function() {
var openpgp = require('../../');
var keyring = require('../../src/openpgp.keyring.js');
var result = [];
@ -60,3 +60,105 @@ unit.register("Encryption/decryption", function() {
return result;
});
unit.register("Encryption/decryption", function() {
var openpgp = require('../../src');
var pub_key =
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'Type: RSA/RSA',
'',
'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+',
'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5',
'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0',
'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS',
'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6',
'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki',
'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf',
'9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa',
'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag',
'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr',
'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb',
'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA',
'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP',
'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2',
'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X',
'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD',
'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY',
'hz3tYjKhoFTKEIq3y3Pp',
'=h/aX',
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
var priv_key =
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'Type: RSA/RSA',
'Pwd: hello world',
'',
'lQH+BFJhL04BBADclrUEDDsm0PSZbQ6pml9FpzTyXiyCyDN+rMOsy9J300Oc10kt',
'/nyBej9vZSRcaW5VpNNj0iA+c1/w2FPf84zNsTzvDmuMaNHFUzky4/vkYuZra//3',
'+Ri7CF8RawSYQ/4IRbC9zqdBlzniyfQOW7Dp/LYe8eibnDSrmkQem0G0jwARAQAB',
'/gMDAu7L//czBpE40p1ZqO8K3k7UejemjsQqc7kOqnlDYd1Z6/3NEA/UM30Siipr',
'KjdIFY5+hp0hcs6EiiNq0PDfm/W2j+7HfrZ5kpeQVxDek4irezYZrl7JS2xezaLv',
'k0Fv/6fxasnFtjOM6Qbstu67s5Gpl9y06ZxbP3VpT62+Xeibn/swWrfiJjuGEEhM',
'bgnsMpHtzAz/L8y6KSzViG/05hBaqrvk3/GeEA6nE+o0+0a6r0LYLTemmq6FbaA1',
'PHo+x7k7oFcBFUUeSzgx78GckuPwqr2mNfeF+IuSRnrlpZl3kcbHASPAOfEkyMXS',
'sWGE7grCAjbyQyM3OEXTSyqnehvGS/1RdB6kDDxGwgE/QFbwNyEh6K4eaaAThW2j',
'IEEI0WEnRkPi9fXyxhFsCLSI1XhqTaq7iDNqJTxE+AX2b9ZuZXAxI3Tc/7++vEyL',
'3p18N/MB2kt1Wb1azmXWL2EKlT1BZ5yDaJuBQ8BhphM3tCRUZXN0IE1jVGVzdGlu',
'Z3RvbiA8dGVzdEBleGFtcGxlLmNvbT6IuQQTAQIAIwUCUmEvTgIbLwcLCQgHAwIB',
'BhUIAgkKCwQWAgMBAh4BAheAAAoJEEpjYTpNbkCUMAwD+gIK08qpEZSVas9qW+Ok',
'32wzNkwxe6PQgZwcyBqMQYZUcKagC8+89pMQQ5sKUGvpIgat42Tf1KLGPcvG4cDA',
'JZ6w2PYz9YHQqPh9LA+PAnV8m25TcGmKcKgvFUqQ3U53X/Y9sBP8HooRqfwwHcv9',
'pMgQmojmNbI4VHydRqIBePawnQH+BFJhL04BBADpH8+0EVolpPiOrXTKoBKTiyrB',
'UyxzodyJ8zmVJ3HMTEU/vidpQwzISwoc/ndDFMXQauq6xqBCD9m2BPQI3UdQzXnb',
'LsAI52nWCIqOkzM5NAKWoKhyXK9Y4UH4v9LAYQgl/stIISvCgG4mJ8lzzEBWvRdf',
'Qm2Ghb64/3V5NDdemwARAQAB/gMDAu7L//czBpE40iPcpLzL7GwBbWFhSWgSLy53',
'Md99Kxw3cApWCok2E8R9/4VS0490xKZIa5y2I/K8thVhqk96Z8Kbt7MRMC1WLHgC',
'qJvkeQCI6PrFM0PUIPLHAQtDJYKtaLXxYuexcAdKzZj3FHdtLNWCooK6n3vJlL1c',
'WjZcHJ1PH7USlj1jup4XfxsbziuysRUSyXkjn92GZLm+64vCIiwhqAYoizF2NHHG',
'hRTN4gQzxrxgkeVchl+ag7DkQUDANIIVI+A63JeLJgWJiH1fbYlwESByHW+zBFNt',
'qStjfIOhjrfNIc3RvsggbDdWQLcbxmLZj4sB0ydPSgRKoaUdRHJY0S4vp9ouKOtl',
'2au/P1BP3bhD0fDXl91oeheYth+MSmsJFDg/vZJzCJhFaQ9dp+2EnjN5auNCNbaI',
'beFJRHFf9cha8p3hh+AK54NRCT++B2MXYf+TPwqX88jYMBv8kk8vYUgo8128r1zQ',
'EzjviQE9BBgBAgAJBQJSYS9OAhsuAKgJEEpjYTpNbkCUnSAEGQECAAYFAlJhL04A',
'CgkQ4IT3RGwgLJe6ogQA2aaJEIBIXtgrs+8WSJ4k3DN4rRXcXaUZf667pjdD9nF2',
'3BzjFH6Z78JIGaxRHJdM7b05aE8YuzM8f3NIlT0F0OLq/TI2muYU9f/U2DQBuf+w',
'KTB62+PELVgi9MsXC1Qv/u/o1LZtmmxTFFOD35xKsxZZI2OJj2pQpqObW27M8Nlc',
'BQQAw2YA3fFc38qPK+PY4rZyTRdbvjyyX+1zeqIo8wn7QCQwXs+OGaH2fGoT35AI',
'SXuqKcWqoEuO7OBSEFThCXBfUYMC01OrqKEswPm/V3zZkLu01q12UMwZach28QwK',
'/YZly4ioND2tdazj17u2rU2dwtiHPe1iMqGgVMoQirfLc+k=',
'=lw5e',
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
var armored =
['-----BEGIN PGP MESSAGE-----',
'Version: OpenPGP.js VERSION',
'Comment: http://openpgpjs.org',
'',
'wYwD4IT3RGwgLJcBA/wN8H9qUvsJwsarDOcsczk1L9Iif47jy+3vF6LcpSgA',
'DfKSARWvatyakvEJmuCNfcpzS8NUPnFA51p0VWmI7FnYG5LkPVUIHb4sN07G',
'9PeqhaayZIeNVvS6DoYuxiTG2sbDmyrv6MMSLivs7VcTAN6L7XXJRI2IumOS',
'x2WFgYNKANJFAQmen4R4IGf9nZDI7NJ4QHUlK1GENgLix9RzMK+Cri6p9Gx5',
'4MDV23jgCBWrUHfFYximgcXiUk0NfpVD3x6chcnKUKJv',
'=Eaix',
'-----END PGP MESSAGE-----'].join('\n');
var plaintext = 'short message';
var key = openpgp.key.readArmored(pub_key);
var encrypted = openpgp.encryptMessage([key], plaintext);
var message = openpgp.message.readArmored(encrypted);
var privKey = openpgp.key.readArmored(priv_key);
privKey.decrypt('hello world');
var decrypted = openpgp.decryptMessage(privKey, message);
return new test_result('Encrypt plain text and afterwards decrypt leads to same result', plaintext == decrypted);
});

File diff suppressed because one or more lines are too long