Added test and working code to the sym encrypted integrity protected packet.
This commit is contained in:
parent
3f04470e1f
commit
3a3764a436
|
@ -8362,6 +8362,17 @@ function _openpgp () {
|
|||
|
||||
var openpgp = new _openpgp();
|
||||
|
||||
/** RFC4880, section 9.1
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.publickey = {
|
||||
rsa_encrypt_sign: 1,
|
||||
rsa_encrypt: 2,
|
||||
rsa_sign: 3,
|
||||
elgamal: 16,
|
||||
dsa: 17
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.2
|
||||
* @enum {Integer}
|
||||
*/
|
||||
|
@ -8378,7 +8389,30 @@ openpgp.symmetric = {
|
|||
twofish: 10
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.3
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.compression = {
|
||||
uncompressed: 0,
|
||||
/** RFC1951 */
|
||||
zip: 1,
|
||||
/** RFC1950 */
|
||||
zlib: 2,
|
||||
bzip2: 3
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.4
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.hash = {
|
||||
md5: 1,
|
||||
sha1: 2,
|
||||
ripemd: 3,
|
||||
sha256: 8,
|
||||
sha384: 9,
|
||||
sha512: 10,
|
||||
sha224: 11
|
||||
};
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
|
@ -9257,6 +9291,173 @@ function openpgp_msg_publickey() {
|
|||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Compressed Data Packet (Tag 8)
|
||||
*
|
||||
* RFC4880 5.6:
|
||||
* The Compressed Data packet contains compressed data. Typically, this
|
||||
* packet is found as the contents of an encrypted packet, or following
|
||||
* a Signature or One-Pass Signature packet, and contains a literal data
|
||||
* packet.
|
||||
*/
|
||||
function openpgp_packet_compressed() {
|
||||
this.tag = 8;
|
||||
this.packets = new openpgp_packetlist();
|
||||
this.algorithm = openpgp.compression.uncompressed;
|
||||
this.compressed = null;
|
||||
|
||||
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
* @param {String} input Payload of a tag 8 packet
|
||||
* @param {Integer} position Position to start reading from the input string
|
||||
* @param {Integer} len Length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_compressed} Object representation
|
||||
*/
|
||||
this.read = function(bytes) {
|
||||
// One octet that gives the algorithm used to compress the packet.
|
||||
this.algorithm = input.charCodeAt(0);
|
||||
// Compressed data, which makes up the remainder of the packet.
|
||||
this.compressed = input.substr(1);
|
||||
|
||||
this.decompress();
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.write = function() {
|
||||
if(this.compressed == null)
|
||||
this.compress();
|
||||
|
||||
return String.fromCharCode(this.type) + this.compressed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decompression method for decompressing the compressed data
|
||||
* read by read_packet
|
||||
* @return {String} The decompressed data
|
||||
*/
|
||||
this.decompress = function() {
|
||||
var bytes;
|
||||
|
||||
switch (this.algorithm) {
|
||||
case openpgp.compression.uncompressed:
|
||||
decompressed = this.compressed;
|
||||
break;
|
||||
|
||||
case openpgp.compression.zip:
|
||||
util.print_info('Decompressed packet [Type 1-ZIP]: ' + this.toString());
|
||||
var compData = this.compressed;
|
||||
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
// no header in this case, directly call deflate
|
||||
var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
|
||||
|
||||
decompressed = unescape(jxg_obj.deflate()[0][0]);
|
||||
break;
|
||||
|
||||
case openpgp.compression.zlib:
|
||||
util.print_info('Decompressed packet [Type 2-ZLIB]: ' + this.toString());
|
||||
//RFC 1950. Bits 0-3 Compression Method
|
||||
var compressionMethod = this.compressed.charCodeAt(0) % 0x10;
|
||||
|
||||
//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
|
||||
// 2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary
|
||||
// (how is this defined). Basic checksum, and compression level.
|
||||
|
||||
if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
|
||||
// remove 4 bytes ADLER32 checksum from the end
|
||||
var compData = this.compressed.substring(0, this.compressed.length - 4);
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
//TODO check ADLER32 checksum
|
||||
decompressed = JXG.decompress(radix);
|
||||
break;
|
||||
|
||||
} else {
|
||||
util.print_error("Compression algorithm ZLIB only supports " +
|
||||
"DEFLATE compression method.");
|
||||
}
|
||||
break;
|
||||
|
||||
case openpgp.compression.bzip2:
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
|
||||
util.print_debug("decompressed:"+util.hexstrdump(decompressed));
|
||||
|
||||
this.packets.read(decompressed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the packet data (member decompressedData)
|
||||
* @param {Integer} type Algorithm to be used // See RFC 4880 9.3
|
||||
* @param {String} data Data to be compressed
|
||||
* @return {String} The compressed data stored in attribute compressedData
|
||||
*/
|
||||
this.compress = function() {
|
||||
switch (this.type) {
|
||||
|
||||
case openpgp.compression.uncompressed: // - Uncompressed
|
||||
this.compressed = this.packets.write();
|
||||
break;
|
||||
|
||||
case openpgp.compression.zip: // - ZIP [RFC1951]
|
||||
util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
|
||||
break;
|
||||
|
||||
case openpgp.compression.zlib: // - ZLIB [RFC1950]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
|
||||
break;
|
||||
|
||||
case openpgp.compression.bzip2: // - BZip2 [BZ2]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pretty printing the packet (useful for debug purposes)
|
||||
* @return {String}
|
||||
*/
|
||||
this.toString = function() {
|
||||
return '5.6. Compressed Data Packet (Tag 8)\n'+
|
||||
' Compression Algorithm = '+this.algorithm+'\n'+
|
||||
' Compressed Data: Byte ['+util.hexstrdump(this.compressed)+']\n';
|
||||
}
|
||||
};
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Literal Data Packet (Tag 11)
|
||||
|
@ -9410,343 +9611,6 @@ openpgp_packet_literal.format = {
|
|||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Compressed Data Packet (Tag 8)
|
||||
*
|
||||
* RFC4880 5.6:
|
||||
* The Compressed Data packet contains compressed data. Typically, this
|
||||
* packet is found as the contents of an encrypted packet, or following
|
||||
* a Signature or One-Pass Signature packet, and contains a literal data
|
||||
* packet.
|
||||
*/
|
||||
function openpgp_packet_compressed(bytes) {
|
||||
this.tagType = 8;
|
||||
this.decompressedData = null;
|
||||
this.compressedData = null;
|
||||
this.type = 0;
|
||||
|
||||
if(bytes != undefined)
|
||||
this.read(bytes);
|
||||
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
* @param {String} input Payload of a tag 8 packet
|
||||
* @param {Integer} position Position to start reading from the input string
|
||||
* @param {Integer} len Length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_compressed} Object representation
|
||||
*/
|
||||
function read_packet (input, position, len) {
|
||||
this.packetLength = len;
|
||||
var mypos = position;
|
||||
// One octet that gives the algorithm used to compress the packet.
|
||||
this.type = input.charCodeAt(mypos++);
|
||||
// Compressed data, which makes up the remainder of the packet.
|
||||
this.compressedData = input.substring(position+1, position+len);
|
||||
return this;
|
||||
}
|
||||
|
||||
this.read = function(bytes) {
|
||||
this.type = input.charCodeAt(mypos++);
|
||||
this.compressedData = input.substring(position+1, position+len);
|
||||
this.decompressedData = null;
|
||||
}
|
||||
|
||||
this.write = function() {
|
||||
if(this.compressedData == null)
|
||||
this.compress();
|
||||
|
||||
return String.fromCharCode(this.type) + this.compress();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decompression method for decompressing the compressed data
|
||||
* read by read_packet
|
||||
* @return {String} The decompressed data
|
||||
*/
|
||||
function decompress() {
|
||||
if (this.decompressedData != null)
|
||||
return this.decompressedData;
|
||||
|
||||
if (this.type == null)
|
||||
return null;
|
||||
|
||||
switch (this.type) {
|
||||
case 0: // - Uncompressed
|
||||
this.decompressedData = this.compressedData;
|
||||
break;
|
||||
case 1: // - ZIP [RFC1951]
|
||||
util.print_info('Decompressed packet [Type 1-ZIP]: ' + this.toString());
|
||||
var compData = this.compressedData;
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
// no header in this case, directly call deflate
|
||||
var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
|
||||
this.decompressedData = unescape(jxg_obj.deflate()[0][0]);
|
||||
break;
|
||||
case 2: // - ZLIB [RFC1950]
|
||||
util.print_info('Decompressed packet [Type 2-ZLIB]: ' + this.toString());
|
||||
var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method
|
||||
//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
|
||||
//2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary (how is this defined). Basic checksum, and compression level.
|
||||
if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
|
||||
// remove 4 bytes ADLER32 checksum from the end
|
||||
var compData = this.compressedData.substring(0, this.compressedData.length - 4);
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
//TODO check ADLER32 checksum
|
||||
this.decompressedData = JXG.decompress(radix);
|
||||
break;
|
||||
} else {
|
||||
util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
|
||||
}
|
||||
break;
|
||||
case 3: // - BZip2 [BZ2]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));
|
||||
return this.decompressedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the packet data (member decompressedData)
|
||||
* @param {Integer} type Algorithm to be used // See RFC 4880 9.3
|
||||
* @param {String} data Data to be compressed
|
||||
* @return {String} The compressed data stored in attribute compressedData
|
||||
*/
|
||||
function compress() {
|
||||
switch (this.type) {
|
||||
case 0: // - Uncompressed
|
||||
this.compressedData = this.decompressedData;
|
||||
break;
|
||||
case 1: // - ZIP [RFC1951]
|
||||
util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
|
||||
break;
|
||||
case 2: // - ZLIB [RFC1950]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
|
||||
break;
|
||||
case 3: // - BZip2 [BZ2]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
this.packetLength = this.compressedData.length +1;
|
||||
return this.compressedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of the packet
|
||||
* @param {Integer} algorithm Algorithm to be used // See RFC 4880 9.3
|
||||
* @param {String} data Data to be compressed
|
||||
* @return {String} String-representation of the packet
|
||||
*/
|
||||
function write_packet(algorithm, data) {
|
||||
this.decompressedData = data;
|
||||
if (algorithm == null) {
|
||||
this.type = 1;
|
||||
}
|
||||
var result = String.fromCharCode(this.type)+this.compress(this.type);
|
||||
return openpgp_packet.write_packet_header(8, result.length)+result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty printing the packet (useful for debug purposes)
|
||||
* @return {String}
|
||||
*/
|
||||
function toString() {
|
||||
return '5.6. Compressed Data Packet (Tag 8)\n'+
|
||||
' length: '+this.packetLength+'\n'+
|
||||
' Compression Algorithm = '+this.type+'\n'+
|
||||
' Compressed Data: Byte ['+util.hexstrdump(this.compressedData)+']\n';
|
||||
}
|
||||
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
this.compress = compress;
|
||||
this.decompress = decompress;
|
||||
this.write_packet = write_packet;
|
||||
};
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Sym. Encrypted Integrity Protected Data
|
||||
* Packet (Tag 18)
|
||||
*
|
||||
* RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is
|
||||
* a variant of the Symmetrically Encrypted Data packet. It is a new feature
|
||||
* created for OpenPGP that addresses the problem of detecting a modification to
|
||||
* encrypted data. It is used in combination with a Modification Detection Code
|
||||
* packet.
|
||||
*/
|
||||
|
||||
function openpgp_packet_encryptedintegrityprotecteddata() {
|
||||
this.tagType = 18;
|
||||
this.version = null; // integer == 1
|
||||
this.packetLength = null; // integer
|
||||
this.encryptedData = null; // string
|
||||
this.decrytpedData = null; // string
|
||||
this.hash = null; // string
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
*
|
||||
* @param {String} input Payload of a tag 18 packet
|
||||
* @param {Integer} position
|
||||
* position to start reading from the input string
|
||||
* @param {Integer} len Length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_encryptedintegrityprotecteddata} object
|
||||
* representation
|
||||
*/
|
||||
function read_packet(input, position, len) {
|
||||
this.packetLength = len;
|
||||
// - A one-octet version number. The only currently defined value is
|
||||
// 1.
|
||||
this.version = input[position].charCodeAt();
|
||||
if (this.version != 1) {
|
||||
util
|
||||
.print_error('openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: '
|
||||
+ this.version
|
||||
+ " , @ "
|
||||
+ position
|
||||
+ "hex:"
|
||||
+ util.hexstrdump(input));
|
||||
return null;
|
||||
}
|
||||
// - Encrypted data, the output of the selected symmetric-key cipher
|
||||
// operating in Cipher Feedback mode with shift amount equal to the
|
||||
// block size of the cipher (CFB-n where n is the block size).
|
||||
this.encryptedData = input.substring(position + 1, position + 1 + len);
|
||||
util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"
|
||||
+ this.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of a Sym. Encrypted Integrity Protected
|
||||
* Data Packet (tag 18) (see RFC4880 5.13)
|
||||
*
|
||||
* @param {Integer} symmetric_algorithm
|
||||
* The selected symmetric encryption algorithm to be used
|
||||
* @param {String} key The key of cipher blocksize length to be used
|
||||
* @param {String} data
|
||||
* Plaintext data to be encrypted within the packet
|
||||
* @return {String} A string representation of the packet
|
||||
*/
|
||||
function write_packet(symmetric_algorithm, key, data) {
|
||||
|
||||
var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm);
|
||||
var prefix = prefixrandom
|
||||
+ prefixrandom.charAt(prefixrandom.length - 2)
|
||||
+ prefixrandom.charAt(prefixrandom.length - 1);
|
||||
var tohash = data;
|
||||
tohash += String.fromCharCode(0xD3);
|
||||
tohash += String.fromCharCode(0x14);
|
||||
util.print_debug_hexstr_dump("data to be hashed:"
|
||||
, prefix + tohash);
|
||||
tohash += str_sha1(prefix + tohash);
|
||||
util.print_debug_hexstr_dump("hash:"
|
||||
, tohash.substring(tohash.length - 20,
|
||||
tohash.length));
|
||||
var result = openpgp_crypto_symmetricEncrypt(prefixrandom,
|
||||
symmetric_algorithm, key, tohash, false).substring(0,
|
||||
prefix.length + tohash.length);
|
||||
var header = openpgp_packet.write_packet_header(18, result.length + 1)
|
||||
+ String.fromCharCode(1);
|
||||
this.encryptedData = result;
|
||||
return header + result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the encrypted data contained in this object read_packet must
|
||||
* have been called before
|
||||
*
|
||||
* @param {Integer} symmetric_algorithm_type
|
||||
* The selected symmetric encryption algorithm to be used
|
||||
* @param {String} key The key of cipher blocksize length to be used
|
||||
* @return {String} The decrypted data of this packet
|
||||
*/
|
||||
function decrypt(symmetric_algorithm_type, key) {
|
||||
this.decryptedData = openpgp_crypto_symmetricDecrypt(
|
||||
symmetric_algorithm_type, key, this.encryptedData, false);
|
||||
// there must be a modification detection code packet as the
|
||||
// last packet and everything gets hashed except the hash itself
|
||||
this.hash = str_sha1(openpgp_crypto_MDCSystemBytes(
|
||||
symmetric_algorithm_type, key, this.encryptedData)
|
||||
+ this.decryptedData.substring(0,
|
||||
this.decryptedData.length - 20));
|
||||
util.print_debug_hexstr_dump("calc hash = ", this.hash);
|
||||
if (this.hash == this.decryptedData.substring(
|
||||
this.decryptedData.length - 20, this.decryptedData.length))
|
||||
return this.decryptedData;
|
||||
else
|
||||
util
|
||||
.print_error("Decryption stopped: discovered a modification of encrypted data.");
|
||||
return null;
|
||||
}
|
||||
|
||||
function toString() {
|
||||
var data = '';
|
||||
if(openpgp.config.debug)
|
||||
data = ' data: Bytes ['
|
||||
+ util.hexstrdump(this.encryptedData) + ']';
|
||||
|
||||
return '5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n'
|
||||
+ ' length: '
|
||||
+ this.packetLength
|
||||
+ '\n'
|
||||
+ ' version: '
|
||||
+ this.version
|
||||
+ '\n'
|
||||
+ data;
|
||||
}
|
||||
|
||||
this.write_packet = write_packet;
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
this.decrypt = decrypt;
|
||||
};
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Public-Key Encrypted Session Key Packets (Tag 1)
|
||||
|
@ -10857,85 +10721,6 @@ function openpgp_packet_marker() {
|
|||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Modification Detection Code Packet (Tag 19)
|
||||
*
|
||||
* RFC4880 5.14: The Modification Detection Code packet contains a SHA-1 hash of
|
||||
* plaintext data, which is used to detect message modification. It is only used
|
||||
* with a Symmetrically Encrypted Integrity Protected Data packet. The
|
||||
* Modification Detection Code packet MUST be the last packet in the plaintext
|
||||
* data that is encrypted in the Symmetrically Encrypted Integrity Protected
|
||||
* Data packet, and MUST appear in no other place.
|
||||
*/
|
||||
|
||||
function openpgp_packet_modificationdetectioncode() {
|
||||
this.tagType = 19;
|
||||
this.hash = null;
|
||||
/**
|
||||
* parsing function for a modification detection code packet (tag 19).
|
||||
*
|
||||
* @param {String} input payload of a tag 19 packet
|
||||
* @param {Integer} position
|
||||
* position to start reading from the input string
|
||||
* @param {Integer} len
|
||||
* length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_encrypteddata} object representation
|
||||
*/
|
||||
function read_packet(input, position, len) {
|
||||
this.packetLength = len;
|
||||
|
||||
if (len != 20) {
|
||||
util
|
||||
.print_error("openpgp.packet.modificationdetectioncode.js\n"
|
||||
+ 'invalid length for a modification detection code packet!'
|
||||
+ len);
|
||||
return null;
|
||||
}
|
||||
// - A 20-octet SHA-1 hash of the preceding plaintext data of the
|
||||
// Symmetrically Encrypted Integrity Protected Data packet,
|
||||
// including prefix data, the tag octet, and length octet of the
|
||||
// Modification Detection Code packet.
|
||||
this.hash = input.substring(position, position + 20);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* this packet is created within the encryptedintegrityprotected packet
|
||||
* function write_packet(data) { }
|
||||
*/
|
||||
|
||||
/**
|
||||
* generates debug output (pretty print)
|
||||
*
|
||||
* @return {String} String which gives some information about the
|
||||
* modification detection code
|
||||
*/
|
||||
function toString() {
|
||||
return '5.14 Modification detection code packet\n' + ' bytes ('
|
||||
+ this.hash.length + '): [' + util.hexstrdump(this.hash) + ']';
|
||||
}
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
};
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the One-Pass Signature Packets (Tag 4)
|
||||
|
@ -12582,7 +12367,7 @@ function _openpgp_packet() {
|
|||
userid: 13,
|
||||
public_subkey: 14,
|
||||
user_attribute: 17,
|
||||
sym_encrypted_and_integrity_protected: 18,
|
||||
sym_encrypted_integrity_protected: 18,
|
||||
modification_detection_code: 19
|
||||
};
|
||||
}
|
||||
|
@ -12656,6 +12441,171 @@ function openpgp_packetlist() {
|
|||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Sym. Encrypted Integrity Protected Data
|
||||
* Packet (Tag 18)
|
||||
*
|
||||
* RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is
|
||||
* a variant of the Symmetrically Encrypted Data packet. It is a new feature
|
||||
* created for OpenPGP that addresses the problem of detecting a modification to
|
||||
* encrypted data. It is used in combination with a Modification Detection Code
|
||||
* packet.
|
||||
*/
|
||||
|
||||
function openpgp_packet_sym_encrypted_integrity_protected() {
|
||||
this.tag = 18;
|
||||
this.version = 1;
|
||||
this.encrypted = null; // string
|
||||
this.hash = null; // string
|
||||
this.data = new openpgp_packetlist();
|
||||
this.algorithm = openpgp.symmetric.plaintext;
|
||||
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
*
|
||||
* @param {String} input Payload of a tag 18 packet
|
||||
* @param {Integer} position
|
||||
* position to start reading from the input string
|
||||
* @param {Integer} len Length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_encryptedintegrityprotecteddata} object
|
||||
* representation
|
||||
*/
|
||||
this.read = function(bytes) {
|
||||
// - A one-octet version number. The only currently defined value is
|
||||
// 1.
|
||||
this.version = bytes[0].charCodeAt();
|
||||
if (this.version != 1) {
|
||||
util.print_error('openpgp.packet.encryptedintegrityprotecteddata.js' +
|
||||
'\nunknown encrypted integrity protected data packet version: '
|
||||
+ this.version
|
||||
+ "hex:"
|
||||
+ util.hexstrdump(bytes));
|
||||
return null;
|
||||
}
|
||||
|
||||
// - Encrypted data, the output of the selected symmetric-key cipher
|
||||
// operating in Cipher Feedback mode with shift amount equal to the
|
||||
// block size of the cipher (CFB-n where n is the block size).
|
||||
this.encrypted = bytes.substr(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of a Sym. Encrypted Integrity Protected
|
||||
* Data Packet (tag 18) (see RFC4880 5.13)
|
||||
*
|
||||
* @param {Integer} symmetric_algorithm
|
||||
* The selected symmetric encryption algorithm to be used
|
||||
* @param {String} key The key of cipher blocksize length to be used
|
||||
* @param {String} data
|
||||
* Plaintext data to be encrypted within the packet
|
||||
* @return {String} A string representation of the packet
|
||||
*/
|
||||
this.write = function(symmetric_algorithm, key, data) {
|
||||
return String.fromCharCode(this.version) + this.encrypted;
|
||||
}
|
||||
|
||||
this.encrypt = function(symmetric_algorithm, key) {
|
||||
var bytes = this.data.write()
|
||||
|
||||
var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm);
|
||||
var prefix = prefixrandom
|
||||
+ prefixrandom.charAt(prefixrandom.length - 2)
|
||||
+ prefixrandom.charAt(prefixrandom.length - 1)
|
||||
|
||||
var tohash = bytes;
|
||||
tohash += String.fromCharCode(0xD3);
|
||||
tohash += String.fromCharCode(0x14);
|
||||
|
||||
util.print_debug_hexstr_dump("data to be hashed:"
|
||||
, prefix + tohash);
|
||||
|
||||
tohash += str_sha1(prefix + tohash);
|
||||
|
||||
util.print_debug_hexstr_dump("hash:"
|
||||
, tohash.substring(tohash.length - 20,
|
||||
tohash.length));
|
||||
|
||||
this.encrypted = openpgp_crypto_symmetricEncrypt(prefixrandom,
|
||||
symmetric_algorithm, key, tohash, false).substring(0,
|
||||
prefix.length + tohash.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the encrypted data contained in this object read_packet must
|
||||
* have been called before
|
||||
*
|
||||
* @param {Integer} symmetric_algorithm_type
|
||||
* The selected symmetric encryption algorithm to be used
|
||||
* @param {String} key The key of cipher blocksize length to be used
|
||||
* @return {String} The decrypted data of this packet
|
||||
*/
|
||||
this.decrypt = function(symmetric_algorithm_type, key) {
|
||||
var decrypted = openpgp_crypto_symmetricDecrypt(
|
||||
symmetric_algorithm_type, key, this.encrypted, false);
|
||||
|
||||
|
||||
// there must be a modification detection code packet as the
|
||||
// last packet and everything gets hashed except the hash itself
|
||||
this.hash = str_sha1(
|
||||
openpgp_crypto_MDCSystemBytes(symmetric_algorithm_type, key, this.encrypted)
|
||||
+ decrypted.substring(0, decrypted.length - 20));
|
||||
|
||||
util.print_debug_hexstr_dump("calc hash = ", this.hash);
|
||||
|
||||
this.data.read(decrypted);
|
||||
|
||||
// We pop the mandatory modification detection code packet.
|
||||
var mdc = this.data.packets.pop();
|
||||
|
||||
if(this.hash != mdc.hash) {
|
||||
this.data = null;
|
||||
util.print_error("Decryption stopped: discovered a " +
|
||||
"modification of encrypted data.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.toString = function() {
|
||||
var data = '';
|
||||
if(openpgp.config.debug)
|
||||
data = ' data: Bytes ['
|
||||
+ util.hexstrdump(this.encrypted) + ']';
|
||||
|
||||
return '5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n'
|
||||
+ '\n'
|
||||
+ ' version: '
|
||||
+ this.version
|
||||
+ '\n'
|
||||
+ data;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function openpgp_packet_modification_detection_code() {
|
||||
this.hash = null;
|
||||
this.read = function(bytes) {
|
||||
this.hash = bytes;
|
||||
}
|
||||
}
|
||||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Symmetrically Encrypted Data Packet (Tag 9)
|
||||
|
|
23
resources/openpgp.min.js
vendored
23
resources/openpgp.min.js
vendored
|
@ -322,7 +322,8 @@ d=(new openpgp_packet_literaldata).write_packet(b.replace(/\r\n/g,"\n").replace(
|
|||
e)}f=openpgp.config.config.integrity_protect?f+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,e,d):f+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,e,d);return openpgp_encoding_armor(3,f,null,null)};this.read_message=function(a){var c;try{c=openpgp_encoding_deArmor(a.replace(/\r/g,""))}catch(d){return util.print_error("no message found!"),null}return b(c)};this.read_messages_dearmored=b;this.read_publicKey=
|
||||
function(a){for(var b=0,d=[],e=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,f=a.length;b!=a.length;){var g=openpgp_packet.read_packet(a,b,f);if(153==a[b].charCodeAt()||6==g.tagType)d[e]=new openpgp_msg_publickey,d[e].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,f=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),d[e].publicKeyPacket=new openpgp_packet_keymaterial,d[e].publicKeyPacket.header=d[e].header,d[e].publicKeyPacket.read_tag6(a,b,f),b+=d[e].publicKeyPacket.packetLength,b+=d[e].read_nodes(d[e].publicKeyPacket,
|
||||
a,b,a.length-b)):(d[e]=new openpgp_msg_publickey,d[e].publicKeyPacket=g,b+=g.headerLength+g.packetLength,b+=d[e].read_nodes(g,a,b,a.length-b));else return util.print_error("no public key found!"),null;d[e].data=a.substring(0,b);e++}return d};this.read_privateKey=function(a){for(var b=[],d=0,e=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,f=a.length;e!=a.length;){var g=openpgp_packet.read_packet(a,e,f);if(5==g.tagType)b[b.length]=new openpgp_msg_privatekey,e+=g.headerLength+g.packetLength,
|
||||
e+=b[d].read_nodes(g,a,e,f);else return util.print_error("no block packet found!"),null;b[d].data=a.substring(0,e);d++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;openpgp.symmetric={plaintext:0,idea:1,tripledes:2,cast5:3,blowfish:4,aes128:7,aes192:8,aes256:9,twofish:10};
|
||||
e+=b[d].read_nodes(g,a,e,f);else return util.print_error("no block packet found!"),null;b[d].data=a.substring(0,e);d++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;openpgp.publickey={rsa_encrypt_sign:1,rsa_encrypt:2,rsa_sign:3,elgamal:16,dsa:17};openpgp.symmetric={plaintext:0,idea:1,tripledes:2,cast5:3,blowfish:4,aes128:7,aes192:8,aes256:9,twofish:10};
|
||||
openpgp.compression={uncompressed:0,zip:1,zlib:2,bzip2:3};openpgp.hash={md5:1,sha1:2,ripemd:3,sha256:8,sha384:9,sha512:10,sha224:11};
|
||||
function openpgp_keyring(){this.init=function(){var b=JSON.parse(window.localStorage.getItem("privatekeys")),a=JSON.parse(window.localStorage.getItem("publickeys"));if(null==b||0==b.length)b=[];if(null==a||0==a.length)a=[];this.publicKeys=[];this.privateKeys=[];for(var c=0,d=0;d<b.length;d++){var e=openpgp.read_privateKey(b[d]);this.privateKeys[c]={armored:b[d],obj:e[0],keyId:e[0].getKeyId()};c++}for(d=c=0;d<a.length;d++)e=openpgp.read_publicKey(a[d]),null!=e[0]&&(this.publicKeys[c]={armored:a[d],
|
||||
obj:e[0],keyId:e[0].getKeyId()},c++)};this.hasPrivateKey=function(){return 0<this.privateKeys.length};this.store=function(){for(var b=[],a=0;a<this.privateKeys.length;a++)b[a]=this.privateKeys[a].armored;for(var c=[],a=0;a<this.publicKeys.length;a++)c[a]=this.publicKeys[a].armored;window.localStorage.setItem("privatekeys",JSON.stringify(b));window.localStorage.setItem("publickeys",JSON.stringify(c))};this.getPublicKeyForAddress=function(b){var a=[],c=b.split("<"),d="",d=1<c.length?c[1].split(">")[0]:
|
||||
b.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return a;for(b=0;b<this.publicKeys.length;b++)for(c=0;c<this.publicKeys[b].obj.userIds.length;c++)0<=this.publicKeys[b].obj.userIds[c].text.toLowerCase().indexOf(d)&&(a[a.length]=this.publicKeys[b]);return a};this.getPrivateKeyForAddress=function(b){var a=[],c=b.split("<"),d="",d=1<c.length?c[1].split(">")[0]:b.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return a;for(b=0;b<this.privateKeys.length;b++)for(c=0;c<this.privateKeys[b].obj.userIds.length;c++)0<=
|
||||
|
@ -351,18 +352,13 @@ function(){for(var b=" OPENPGP Public Key\n length: "+this.len+"\n",b=b+"
|
|||
return b};this.validate=function(){for(var b=0;b<this.revocationSignatures.length;b++)if(this.revocationSignatures[b].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket))return!1;if(0!=this.subKeys.length){for(var a=!1,b=0;b<this.subKeys.length;b++)if(3==this.subKeys[b].verifyKey()){a=!0;break}if(!a)return!1}a=!1;for(b=0;b<this.userIds.length;b++)if(0==this.userIds[b].verify(this.publicKeyPacket)){a=!0;break}return!a?!1:!0};this.getFingerprint=function(){return this.publicKeyPacket.getFingerprint()};
|
||||
this.getKeyId=function(){return this.publicKeyPacket.getKeyId()};this.verifyBasicSignatures=function(){for(var b=0;b<this.revocationSignatures.length;b++)if(this.revocationSignatures[b].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket))return!1;if(0!=this.subKeys.length){for(var a=!1,b=0;b<this.subKeys.length;b++)if(null!=this.subKeys[b]&&3==this.subKeys[b].verifyKey()){a=!0;break}if(!a)return!1}a=this.getKeyId();for(b=0;b<this.userIds.length;b++)for(var c=0;c<this.userIds[b].certificationRevocationSignatures.length;c++)if(this.userIds[b].certificationSignatures[c].getIssuer==
|
||||
a&&4!=this.userIds[b].certificationSignatures[c].verifyBasic(this.publicKeyPacket))return!1;return!0};this.getSubKeyAsKey=function(b){var a=new openpgp_msg_publickey;a.userIds=this.userIds;a.userAttributes=this.userAttributes;a.publicKeyPacket=this.subKeys[b];return a}}
|
||||
function openpgp_packet_compressed(){this.tag=8;this.packets=new openpgp_packetlist;this.algorithm=openpgp.compression.uncompressed;this.compressed=null;this.read=function(){this.algorithm=input.charCodeAt(0);this.compressed=input.substr(1);this.decompress()};this.write=function(){null==this.compressed&&this.compress();return String.fromCharCode(this.type)+this.compressed};this.decompress=function(){switch(this.algorithm){case openpgp.compression.uncompressed:decompressed=this.compressed;break;case openpgp.compression.zip:util.print_info("Decompressed packet [Type 1-ZIP]: "+
|
||||
this.toString());var b=this.compressed,b=s2r(b).replace(/\n/g,""),b=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(b));decompressed=unescape(b.deflate()[0][0]);break;case openpgp.compression.zlib:util.print_info("Decompressed packet [Type 2-ZLIB]: "+this.toString());if(8==this.compressed.charCodeAt(0)%16){b=this.compressed.substring(0,this.compressed.length-4);b=s2r(b).replace(/\n/g,"");decompressed=JXG.decompress(b);break}else util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
|
||||
break;case openpgp.compression.bzip2:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(decompressed));this.packets.read(decompressed)};this.compress=function(){switch(this.type){case openpgp.compression.uncompressed:this.compressed=this.packets.write();break;case openpgp.compression.zip:util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
|
||||
break;case openpgp.compression.zlib:util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");break;case openpgp.compression.bzip2:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}};this.toString=function(){return"5.6. Compressed Data Packet (Tag 8)\n Compression Algorithm = "+this.algorithm+"\n Compressed Data: Byte ["+util.hexstrdump(this.compressed)+"]\n"}}
|
||||
function openpgp_packet_literal(){this.tag=11;this.format=openpgp_packet_literal.format.utf8;this.data="";this.date=new Date;this.set_data=function(b,a){this.format=a;this.data=b};this.set_data_bytes=function(b,a){this.format=a;a==openpgp_packet_literal.format.utf8&&(b=util.decode_utf8(b));this.data=b};this.get_data_bytes=function(){return this.format==openpgp_packet_literal.format.utf8?util.encode_utf8(this.data):this.data};this.read=function(b){var a=b[0];this.filename=util.decode_utf8(b.substr(2,
|
||||
b.charCodeAt(1)));this.date=new Date(1E3*parseInt(b.substr(2+b.charCodeAt(1),4)));this.set_data_bytes(b.substring(6+b.charCodeAt(1)),a)};this.write=function(){var b=util.encode_utf8("msg.txt"),a=this.get_data_bytes(),c;c=""+this.format;c+=String.fromCharCode(b.length);c=c+b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>24&255);c+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>16&255);c+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>8&255);c+=String.fromCharCode(Math.round(this.date.getTime()/
|
||||
1E3)&255);return c+a};this.toString=function(){return"5.9. Literal Data Packet (Tag 11)\n length: "+this.packetLength+"\n format: "+this.format+"\n filename:"+this.filename+"\n date: "+this.date+"\n data: |"+this.data+"|\n rdata: |"+this.real_data+"|\n"}}openpgp_packet_literal.format={binary:"b",text:"t",utf8:"u"};
|
||||
function openpgp_packet_compressed(b){this.tagType=8;this.compressedData=this.decompressedData=null;this.type=0;void 0!=b&&this.read(b);this.read=function(){this.type=input.charCodeAt(mypos++);this.compressedData=input.substring(position+1,position+len);this.decompressedData=null};this.write=function(){null==this.compressedData&&this.compress();return String.fromCharCode(this.type)+this.compress()};this.read_packet=function(a,b,d){this.packetLength=d;var e=b;this.type=a.charCodeAt(e++);this.compressedData=
|
||||
a.substring(b+1,b+d);return this};this.toString=function(){return"5.6. Compressed Data Packet (Tag 8)\n length: "+this.packetLength+"\n Compression Algorithm = "+this.type+"\n Compressed Data: Byte ["+util.hexstrdump(this.compressedData)+"]\n"};this.compress=function(){switch(this.type){case 0:this.compressedData=this.decompressedData;break;case 1:util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");break;case 2:util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
|
||||
break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}this.packetLength=this.compressedData.length+1;return this.compressedData};this.decompress=function(){if(null!=this.decompressedData)return this.decompressedData;if(null==this.type)return null;switch(this.type){case 0:this.decompressedData=this.compressedData;break;case 1:util.print_info("Decompressed packet [Type 1-ZIP]: "+this.toString());
|
||||
var a=this.compressedData,a=s2r(a).replace(/\n/g,""),a=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(a));this.decompressedData=unescape(a.deflate()[0][0]);break;case 2:util.print_info("Decompressed packet [Type 2-ZLIB]: "+this.toString());if(8==this.compressedData.charCodeAt(0)%16){a=this.compressedData.substring(0,this.compressedData.length-4);a=s2r(a).replace(/\n/g,"");this.decompressedData=JXG.decompress(a);break}else util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
|
||||
break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));return this.decompressedData};this.write_packet=function(a,b){this.decompressedData=b;if(null==a)this.type=1;var d=String.fromCharCode(this.type)+this.compress(this.type);return openpgp_packet.write_packet_header(8,d.length)+d}}
|
||||
function openpgp_packet_encryptedintegrityprotecteddata(){this.tagType=18;this.hash=this.decrytpedData=this.encryptedData=this.packetLength=this.version=null;this.write_packet=function(b,a,c){var d=openpgp_crypto_getPrefixRandom(b),e=d+d.charAt(d.length-2)+d.charAt(d.length-1),c=c+String.fromCharCode(211),c=c+String.fromCharCode(20);util.print_debug_hexstr_dump("data to be hashed:",e+c);c+=str_sha1(e+c);util.print_debug_hexstr_dump("hash:",c.substring(c.length-20,c.length));b=openpgp_crypto_symmetricEncrypt(d,
|
||||
b,a,c,!1).substring(0,e.length+c.length);a=openpgp_packet.write_packet_header(18,b.length+1)+String.fromCharCode(1);this.encryptedData=b;return a+b};this.read_packet=function(b,a,c){this.packetLength=c;this.version=b[a].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+" , @ "+a+"hex:"+util.hexstrdump(b)),null;this.encryptedData=b.substring(a+1,a+1+c);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
|
||||
this.toString());return this};this.toString=function(){var b="";openpgp.config.debug&&(b=" data: Bytes ["+util.hexstrdump(this.encryptedData)+"]");return"5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n length: "+this.packetLength+"\n version: "+this.version+"\n"+b};this.decrypt=function(b,a){this.decryptedData=openpgp_crypto_symmetricDecrypt(b,a,this.encryptedData,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(b,a,this.encryptedData)+this.decryptedData.substring(0,
|
||||
this.decryptedData.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);if(this.hash==this.decryptedData.substring(this.decryptedData.length-20,this.decryptedData.length))return this.decryptedData;util.print_error("Decryption stopped: discovered a modification of encrypted data.");return null}}
|
||||
function openpgp_packet_encryptedsessionkey(){this.read_pub_key_packet=function(b,a,c){this.tagType=1;this.packetLength=c;var d=a;if(10>c)return util.print_error("openpgp.packet.encryptedsessionkey.js\ninvalid length"),null;this.version=b[d++].charCodeAt();this.keyId=new openpgp_type_keyid;this.keyId.read_packet(b,d);d+=8;this.publicKeyAlgorithmUsed=b[d++].charCodeAt();switch(this.publicKeyAlgorithmUsed){case 1:case 2:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(b,d,d-a);break;
|
||||
case 16:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(b,d,d-a);d+=this.MPIs[0].packetLength;this.MPIs[1]=new openpgp_type_mpi;this.MPIs[1].read(b,d,d-a);break;default:util.print_error("openpgp.packet.encryptedsessionkey.js\nunknown public key packet algorithm type "+this.publicKeyAlgorithmType)}return this};this.read_symmetric_key_packet=function(b,a,c){this.tagType=3;var d=a;this.version=b[d++];this.symmetricKeyAlgorithmUsed=b[d++];this.s2k=new openpgp_type_s2k;this.s2k.read(b,
|
||||
d);if(s2k.s2kLength+d<c){this.encryptedSessionKey=[];for(a=d-a;a<c;a++)this.encryptedSessionKey[a]=b[d++]}return this};this.write_pub_key_packet=function(b,a,c,d,e){for(var f=String.fromCharCode(3),d=String.fromCharCode(d),d=d+e,e=util.calc_checksum(e),d=d+String.fromCharCode(e>>8&255),d=d+String.fromCharCode(e&255),f=f+b+String.fromCharCode(c),b=new openpgp_type_mpi,a=openpgp_crypto_asymetricEncrypt(c,a,b.create(openpgp_encoding_eme_pkcs1_encode(d,a[0].mpiByteLength))),c=0;c<a.length;c++)f+=a[c];
|
||||
|
@ -397,7 +393,6 @@ a),f=openpgp_crypto_getRandomBytes(8),util.print_debug_hexstr_dump("write_privat
|
|||
this.IV);e+=this.IV+ciphertextMPIs;break;case 7:case 8:case 9:this.IVLength=16,this.IV=openpgp_crypto_getRandomBytes(this.IVLength),ciphertextMPIs=normal_cfb_encrypt(AESencrypt,this.IVLength,c,b+a,this.IV),e+=this.IV+ciphertextMPIs}else e+=String.fromCharCode(0),e+=a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),c=util.calc_checksum(a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI()),e+=String.fromCharCode(c/256)+String.fromCharCode(c%256),util.print_debug_hexstr_dump("write_private_key basic checksum: "+
|
||||
c);break;default:e="",util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}c=openpgp_packet.write_packet_header(5,e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(b,a,c){var d=String.fromCharCode(4),d=d+c;switch(b){case 1:d+=String.fromCharCode(1);d+=a.n.toMPI();d+=a.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}b=openpgp_packet.write_packet_header(6,d.length);
|
||||
return{string:b+d,header:b,body:d}}}function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(b,a){this.packetLength=3;return 80==b[a].charCodeAt()&&71==b[a+1].charCodeAt()&&80==b[a+2].charCodeAt()?this:null};this.toString=function(){return'5.8. Marker Packet (Obsolete Literal Packet) (Tag 10)\n packet reads: "PGP"\n'}}
|
||||
function openpgp_packet_modificationdetectioncode(){this.tagType=19;this.hash=null;this.read_packet=function(b,a,c){this.packetLength=c;if(20!=c)return util.print_error("openpgp.packet.modificationdetectioncode.js\ninvalid length for a modification detection code packet!"+c),null;this.hash=b.substring(a,a+20);return this};this.toString=function(){return"5.14 Modification detection code packet\n bytes ("+this.hash.length+"): ["+util.hexstrdump(this.hash)+"]"}}
|
||||
function openpgp_packet_onepasssignature(){this.tagType=4;this.flags=this.signingKeyId=this.publicKeyAlgorithm=this.hashAlgorithm=this.type=this.version=null;this.read_packet=read_packet;this.toString=function(){return"5.4. One-Pass Signature Packets (Tag 4)\n length: "+this.packetLength+"\n type: "+this.type+"\n keyID: "+this.signingKeyId.toString()+"\n hashA: "+this.hashAlgorithm+"\n pubKeyA:"+this.publicKeyAlgorithm+"\n flags: "+this.flags+"\n version:"+this.version+
|
||||
"\n"};this.write_packet=write_packet}
|
||||
function openpgp_packet_signature(){function b(a,b){var d;d=""+openpgp_packet.encode_length(b.length+1);d+=String.fromCharCode(a);return d+b}this.tagType=2;this.embeddedSignature=this.signatureTargetHash=this.signatureTargetHashAlgorithm=this.signatureTargetPublicKeyAlgorithm=this.reasonForRevocationString=this.reasonForRevocationFlag=this.signersUserId=this.keyFlags=this.policyURI=this.isPrimaryUserID=this.preferredKeyServer=this.keyServerPreferences=this.preferredCompressionAlgorithms=this.preferredHashAlgorithms=
|
||||
|
@ -447,8 +442,12 @@ null;var e=-1,f=-1,f=0;0!=(a[b].charCodeAt()&64)&&(f=1);var g;f?e=a[b].charCodeA
|
|||
1<<(a[b++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);d=b+packet_length;for(h=a.substring(b,b+packet_length);;)if(192>a[d].charCodeAt()){g=a[d++].charCodeAt();packet_length+=g;h+=a.substring(d,d+g);d+=g;break}else if(192<=a[d].charCodeAt()&&224>a[d].charCodeAt()){g=(a[d++].charCodeAt()-192<<8)+a[d++].charCodeAt()+192;packet_length+=g;h+=a.substring(d,d+g);d+=g;break}else if(223<a[d].charCodeAt()&&255>a[d].charCodeAt())g=1<<(a[d++].charCodeAt()&31),packet_length+=g,h+=a.substring(d,
|
||||
d+g),d+=g;else{d++;g=a[d++].charCodeAt()<<24|a[d++].charCodeAt()<<16|a[d++].charCodeAt()<<8|a[d++].charCodeAt();h+=a.substring(d,d+g);packet_length+=g;d+=g;break}j=d}else b++,packet_length=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<8|a[b++].charCodeAt();else switch(g){case 0:packet_length=a[b++].charCodeAt();break;case 1:packet_length=a[b++].charCodeAt()<<8|a[b++].charCodeAt();break;case 2:packet_length=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<
|
||||
8|a[b++].charCodeAt();break;default:packet_length=d}-1==j&&(j=packet_length);null==h&&(h=a.substring(b,b+j));var a={},k;for(k in this.type)a[this.type[k]]=k;k="openpgp_packet_"+a[e];a=window[k];if(void 0==a)throw k;k=new a;k.read(h);return{packet:k,offset:b+packet_length}};this.type={reserved:0,public_key_encrypted_session_key:1,signature:2,symmetric_key_encrypted_session_key:3,one_pass_signature:4,secret_key:5,public_key:6,secret_subkey:7,compressed:8,symmetrically_encrypted:9,marker:10,literal:11,
|
||||
trust:12,userid:13,public_subkey:14,user_attribute:17,sym_encrypted_and_integrity_protected:18,modification_detection_code:19}}var openpgp_packet=new _openpgp_packet;
|
||||
trust:12,userid:13,public_subkey:14,user_attribute:17,sym_encrypted_integrity_protected:18,modification_detection_code:19}}var openpgp_packet=new _openpgp_packet;
|
||||
function openpgp_packetlist(){this.packets=[];this.read=function(b){this.packets=[];for(var a=0;a<b.length;){var c=openpgp_packet.read_packet(b,a,b.length-a),a=a+c.offset;this.push(c.packet)}};this.write=function(){var b="",a;for(a in this.packets)var c=this.packets[a].write(),b=b+openpgp_packet.write_packet_header(this.packets[a].tag,c.length),b=b+c;return b};this.push=function(b){this.packets.push(b)}}
|
||||
function openpgp_packet_sym_encrypted_integrity_protected(){this.tag=18;this.version=1;this.hash=this.encrypted=null;this.data=new openpgp_packetlist;this.algorithm=openpgp.symmetric.plaintext;this.read=function(b){this.version=b[0].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+"hex:"+util.hexstrdump(b)),null;this.encrypted=b.substr(1)};this.write=function(){return String.fromCharCode(this.version)+
|
||||
this.encrypted};this.encrypt=function(b,a){var c=this.data.write(),d=openpgp_crypto_getPrefixRandom(b),e=d+d.charAt(d.length-2)+d.charAt(d.length-1),c=c+String.fromCharCode(211),c=c+String.fromCharCode(20);util.print_debug_hexstr_dump("data to be hashed:",e+c);c+=str_sha1(e+c);util.print_debug_hexstr_dump("hash:",c.substring(c.length-20,c.length));this.encrypted=openpgp_crypto_symmetricEncrypt(d,b,a,c,!1).substring(0,e.length+c.length)};this.decrypt=function(b,a){var c=openpgp_crypto_symmetricDecrypt(b,
|
||||
a,this.encrypted,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(b,a,this.encrypted)+c.substring(0,c.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);this.data.read(c);if(this.hash!=this.data.packets.pop().hash)this.data=null,util.print_error("Decryption stopped: discovered a modification of encrypted data.")};this.toString=function(){var b="";openpgp.config.debug&&(b=" data: Bytes ["+util.hexstrdump(this.encrypted)+"]");return"5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n\n version: "+
|
||||
this.version+"\n"+b}}function openpgp_packet_modification_detection_code(){this.hash=null;this.read=function(b){this.hash=b}}
|
||||
function openpgp_packet_symmetrically_encrypted(){this.tag=9;this.encrypted=null;this.data=new openpgp_packetlist;this.algorithm=openpgp.symmetric.plaintext;this.read=function(b){this.encrypted=b};this.write=function(){return this.encrypted};this.decrypt=function(b,a){this.data.read(openpgp_crypto_symmetricDecrypt(b,a,this.encrypted,!0))};this.encrypt=function(b,a){var c=this.data.write();this.encrypted=openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(b),b,a,c,!0)};this.toString=function(){return"5.7. Symmetrically Encrypted Data Packet (Tag 9)\n Used symmetric algorithm: "+
|
||||
this.algorithmType+"\n encrypted data: Bytes ["+util.hexstrdump(this.encryptedData)+"]\n"}}function openpgp_type_keyid(){this.read_packet=function(b,a){this.bytes=b.substring(a,a+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}}
|
||||
function openpgp_type_mpi(){this.data=this.mpiByteLength=this.mpiBitLength=this.MPI=null;this.read=function(b,a){var c=a;this.mpiBitLength=b[c++].charCodeAt()<<8|b[c++].charCodeAt();this.mpiByteLength=(this.mpiBitLength-this.mpiBitLength%8)/8;0!=this.mpiBitLength%8&&this.mpiByteLength++;this.MPI=b.substring(c,c+this.mpiByteLength);this.data=b.substring(a,a+2+this.mpiByteLength);this.packetLength=this.mpiByteLength+2;return this};this.toBigInteger=function(){return new BigInteger(util.hexstrdump(this.MPI),
|
||||
|
|
|
@ -458,6 +458,17 @@ function _openpgp () {
|
|||
|
||||
var openpgp = new _openpgp();
|
||||
|
||||
/** RFC4880, section 9.1
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.publickey = {
|
||||
rsa_encrypt_sign: 1,
|
||||
rsa_encrypt: 2,
|
||||
rsa_sign: 3,
|
||||
elgamal: 16,
|
||||
dsa: 17
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.2
|
||||
* @enum {Integer}
|
||||
*/
|
||||
|
@ -474,4 +485,27 @@ openpgp.symmetric = {
|
|||
twofish: 10
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.3
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.compression = {
|
||||
uncompressed: 0,
|
||||
/** RFC1951 */
|
||||
zip: 1,
|
||||
/** RFC1950 */
|
||||
zlib: 2,
|
||||
bzip2: 3
|
||||
};
|
||||
|
||||
/** RFC4880, section 9.4
|
||||
* @enum {Integer}
|
||||
*/
|
||||
openpgp.hash = {
|
||||
md5: 1,
|
||||
sha1: 2,
|
||||
ripemd: 3,
|
||||
sha256: 8,
|
||||
sha384: 9,
|
||||
sha512: 10,
|
||||
sha224: 11
|
||||
};
|
||||
|
|
|
@ -25,14 +25,12 @@
|
|||
* a Signature or One-Pass Signature packet, and contains a literal data
|
||||
* packet.
|
||||
*/
|
||||
function openpgp_packet_compressed(bytes) {
|
||||
this.tagType = 8;
|
||||
this.decompressedData = null;
|
||||
this.compressedData = null;
|
||||
this.type = 0;
|
||||
function openpgp_packet_compressed() {
|
||||
this.tag = 8;
|
||||
this.packets = new openpgp_packetlist();
|
||||
this.algorithm = openpgp.compression.uncompressed;
|
||||
this.compressed = null;
|
||||
|
||||
if(bytes != undefined)
|
||||
this.read(bytes);
|
||||
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
|
@ -42,27 +40,22 @@ function openpgp_packet_compressed(bytes) {
|
|||
* input at position
|
||||
* @return {openpgp_packet_compressed} Object representation
|
||||
*/
|
||||
function read_packet (input, position, len) {
|
||||
this.packetLength = len;
|
||||
var mypos = position;
|
||||
this.read = function(bytes) {
|
||||
// One octet that gives the algorithm used to compress the packet.
|
||||
this.type = input.charCodeAt(mypos++);
|
||||
this.algorithm = input.charCodeAt(0);
|
||||
// Compressed data, which makes up the remainder of the packet.
|
||||
this.compressedData = input.substring(position+1, position+len);
|
||||
return this;
|
||||
this.compressed = input.substr(1);
|
||||
|
||||
this.decompress();
|
||||
}
|
||||
|
||||
this.read = function(bytes) {
|
||||
this.type = input.charCodeAt(mypos++);
|
||||
this.compressedData = input.substring(position+1, position+len);
|
||||
this.decompressedData = null;
|
||||
}
|
||||
|
||||
|
||||
this.write = function() {
|
||||
if(this.compressedData == null)
|
||||
if(this.compressed == null)
|
||||
this.compress();
|
||||
|
||||
return String.fromCharCode(this.type) + this.compress();
|
||||
return String.fromCharCode(this.type) + this.compressed;
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,51 +64,61 @@ function openpgp_packet_compressed(bytes) {
|
|||
* read by read_packet
|
||||
* @return {String} The decompressed data
|
||||
*/
|
||||
function decompress() {
|
||||
if (this.decompressedData != null)
|
||||
return this.decompressedData;
|
||||
this.decompress = function() {
|
||||
var bytes;
|
||||
|
||||
if (this.type == null)
|
||||
return null;
|
||||
|
||||
switch (this.type) {
|
||||
case 0: // - Uncompressed
|
||||
this.decompressedData = this.compressedData;
|
||||
switch (this.algorithm) {
|
||||
case openpgp.compression.uncompressed:
|
||||
decompressed = this.compressed;
|
||||
break;
|
||||
case 1: // - ZIP [RFC1951]
|
||||
|
||||
case openpgp.compression.zip:
|
||||
util.print_info('Decompressed packet [Type 1-ZIP]: ' + this.toString());
|
||||
var compData = this.compressedData;
|
||||
var compData = this.compressed;
|
||||
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
// no header in this case, directly call deflate
|
||||
var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
|
||||
this.decompressedData = unescape(jxg_obj.deflate()[0][0]);
|
||||
|
||||
decompressed = unescape(jxg_obj.deflate()[0][0]);
|
||||
break;
|
||||
case 2: // - ZLIB [RFC1950]
|
||||
|
||||
case openpgp.compression.zlib:
|
||||
util.print_info('Decompressed packet [Type 2-ZLIB]: ' + this.toString());
|
||||
var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method
|
||||
//RFC 1950. Bits 0-3 Compression Method
|
||||
var compressionMethod = this.compressed.charCodeAt(0) % 0x10;
|
||||
|
||||
//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
|
||||
//2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary (how is this defined). Basic checksum, and compression level.
|
||||
// 2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary
|
||||
// (how is this defined). Basic checksum, and compression level.
|
||||
|
||||
if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
|
||||
// remove 4 bytes ADLER32 checksum from the end
|
||||
var compData = this.compressedData.substring(0, this.compressedData.length - 4);
|
||||
var compData = this.compressed.substring(0, this.compressed.length - 4);
|
||||
var radix = s2r(compData).replace(/\n/g,"");
|
||||
//TODO check ADLER32 checksum
|
||||
this.decompressedData = JXG.decompress(radix);
|
||||
decompressed = JXG.decompress(radix);
|
||||
break;
|
||||
|
||||
} else {
|
||||
util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
|
||||
util.print_error("Compression algorithm ZLIB only supports " +
|
||||
"DEFLATE compression method.");
|
||||
}
|
||||
break;
|
||||
case 3: // - BZip2 [BZ2]
|
||||
|
||||
case openpgp.compression.bzip2:
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));
|
||||
return this.decompressedData;
|
||||
|
||||
util.print_debug("decompressed:"+util.hexstrdump(decompressed));
|
||||
|
||||
this.packets.read(decompressed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,59 +127,41 @@ function openpgp_packet_compressed(bytes) {
|
|||
* @param {String} data Data to be compressed
|
||||
* @return {String} The compressed data stored in attribute compressedData
|
||||
*/
|
||||
function compress() {
|
||||
this.compress = function() {
|
||||
switch (this.type) {
|
||||
case 0: // - Uncompressed
|
||||
this.compressedData = this.decompressedData;
|
||||
|
||||
case openpgp.compression.uncompressed: // - Uncompressed
|
||||
this.compressed = this.packets.write();
|
||||
break;
|
||||
case 1: // - ZIP [RFC1951]
|
||||
|
||||
case openpgp.compression.zip: // - ZIP [RFC1951]
|
||||
util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
|
||||
break;
|
||||
case 2: // - ZLIB [RFC1950]
|
||||
|
||||
case openpgp.compression.zlib: // - ZLIB [RFC1950]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
|
||||
break;
|
||||
case 3: // - BZip2 [BZ2]
|
||||
|
||||
case openpgp.compression.bzip2: // - BZip2 [BZ2]
|
||||
// TODO: need to implement this
|
||||
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
|
||||
break;
|
||||
|
||||
default:
|
||||
util.print_error("Compression algorithm unknown :"+this.type);
|
||||
break;
|
||||
}
|
||||
this.packetLength = this.compressedData.length +1;
|
||||
return this.compressedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of the packet
|
||||
* @param {Integer} algorithm Algorithm to be used // See RFC 4880 9.3
|
||||
* @param {String} data Data to be compressed
|
||||
* @return {String} String-representation of the packet
|
||||
*/
|
||||
function write_packet(algorithm, data) {
|
||||
this.decompressedData = data;
|
||||
if (algorithm == null) {
|
||||
this.type = 1;
|
||||
}
|
||||
var result = String.fromCharCode(this.type)+this.compress(this.type);
|
||||
return openpgp_packet.write_packet_header(8, result.length)+result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty printing the packet (useful for debug purposes)
|
||||
* @return {String}
|
||||
*/
|
||||
function toString() {
|
||||
this.toString = function() {
|
||||
return '5.6. Compressed Data Packet (Tag 8)\n'+
|
||||
' length: '+this.packetLength+'\n'+
|
||||
' Compression Algorithm = '+this.type+'\n'+
|
||||
' Compressed Data: Byte ['+util.hexstrdump(this.compressedData)+']\n';
|
||||
' Compression Algorithm = '+this.algorithm+'\n'+
|
||||
' Compressed Data: Byte ['+util.hexstrdump(this.compressed)+']\n';
|
||||
}
|
||||
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
this.compress = compress;
|
||||
this.decompress = decompress;
|
||||
this.write_packet = write_packet;
|
||||
};
|
|
@ -1,79 +0,0 @@
|
|||
// GPG4Browsers - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2011 Recurity Labs GmbH
|
||||
//
|
||||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @classdesc Implementation of the Modification Detection Code Packet (Tag 19)
|
||||
*
|
||||
* RFC4880 5.14: The Modification Detection Code packet contains a SHA-1 hash of
|
||||
* plaintext data, which is used to detect message modification. It is only used
|
||||
* with a Symmetrically Encrypted Integrity Protected Data packet. The
|
||||
* Modification Detection Code packet MUST be the last packet in the plaintext
|
||||
* data that is encrypted in the Symmetrically Encrypted Integrity Protected
|
||||
* Data packet, and MUST appear in no other place.
|
||||
*/
|
||||
|
||||
function openpgp_packet_modificationdetectioncode() {
|
||||
this.tagType = 19;
|
||||
this.hash = null;
|
||||
/**
|
||||
* parsing function for a modification detection code packet (tag 19).
|
||||
*
|
||||
* @param {String} input payload of a tag 19 packet
|
||||
* @param {Integer} position
|
||||
* position to start reading from the input string
|
||||
* @param {Integer} len
|
||||
* length of the packet or the remaining length of
|
||||
* input at position
|
||||
* @return {openpgp_packet_encrypteddata} object representation
|
||||
*/
|
||||
function read_packet(input, position, len) {
|
||||
this.packetLength = len;
|
||||
|
||||
if (len != 20) {
|
||||
util
|
||||
.print_error("openpgp.packet.modificationdetectioncode.js\n"
|
||||
+ 'invalid length for a modification detection code packet!'
|
||||
+ len);
|
||||
return null;
|
||||
}
|
||||
// - A 20-octet SHA-1 hash of the preceding plaintext data of the
|
||||
// Symmetrically Encrypted Integrity Protected Data packet,
|
||||
// including prefix data, the tag octet, and length octet of the
|
||||
// Modification Detection Code packet.
|
||||
this.hash = input.substring(position, position + 20);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* this packet is created within the encryptedintegrityprotected packet
|
||||
* function write_packet(data) { }
|
||||
*/
|
||||
|
||||
/**
|
||||
* generates debug output (pretty print)
|
||||
*
|
||||
* @return {String} String which gives some information about the
|
||||
* modification detection code
|
||||
*/
|
||||
function toString() {
|
||||
return '5.14 Modification detection code packet\n' + ' bytes ('
|
||||
+ this.hash.length + '): [' + util.hexstrdump(this.hash) + ']';
|
||||
}
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
};
|
|
@ -304,7 +304,7 @@ function _openpgp_packet() {
|
|||
userid: 13,
|
||||
public_subkey: 14,
|
||||
user_attribute: 17,
|
||||
sym_encrypted_and_integrity_protected: 18,
|
||||
sym_encrypted_integrity_protected: 18,
|
||||
modification_detection_code: 19
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,13 +27,14 @@
|
|||
* packet.
|
||||
*/
|
||||
|
||||
function openpgp_packet_encryptedintegrityprotecteddata() {
|
||||
this.tagType = 18;
|
||||
this.version = null; // integer == 1
|
||||
this.packetLength = null; // integer
|
||||
this.encryptedData = null; // string
|
||||
this.decrytpedData = null; // string
|
||||
function openpgp_packet_sym_encrypted_integrity_protected() {
|
||||
this.tag = 18;
|
||||
this.version = 1;
|
||||
this.encrypted = null; // string
|
||||
this.hash = null; // string
|
||||
this.data = new openpgp_packetlist();
|
||||
this.algorithm = openpgp.symmetric.plaintext;
|
||||
|
||||
/**
|
||||
* Parsing function for the packet.
|
||||
*
|
||||
|
@ -45,28 +46,23 @@ function openpgp_packet_encryptedintegrityprotecteddata() {
|
|||
* @return {openpgp_packet_encryptedintegrityprotecteddata} object
|
||||
* representation
|
||||
*/
|
||||
function read_packet(input, position, len) {
|
||||
this.packetLength = len;
|
||||
this.read = function(bytes) {
|
||||
// - A one-octet version number. The only currently defined value is
|
||||
// 1.
|
||||
this.version = input[position].charCodeAt();
|
||||
this.version = bytes[0].charCodeAt();
|
||||
if (this.version != 1) {
|
||||
util
|
||||
.print_error('openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: '
|
||||
util.print_error('openpgp.packet.encryptedintegrityprotecteddata.js' +
|
||||
'\nunknown encrypted integrity protected data packet version: '
|
||||
+ this.version
|
||||
+ " , @ "
|
||||
+ position
|
||||
+ "hex:"
|
||||
+ util.hexstrdump(input));
|
||||
+ util.hexstrdump(bytes));
|
||||
return null;
|
||||
}
|
||||
|
||||
// - Encrypted data, the output of the selected symmetric-key cipher
|
||||
// operating in Cipher Feedback mode with shift amount equal to the
|
||||
// block size of the cipher (CFB-n where n is the block size).
|
||||
this.encryptedData = input.substring(position + 1, position + 1 + len);
|
||||
util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"
|
||||
+ this.toString());
|
||||
return this;
|
||||
this.encrypted = bytes.substr(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,28 +76,34 @@ function openpgp_packet_encryptedintegrityprotecteddata() {
|
|||
* Plaintext data to be encrypted within the packet
|
||||
* @return {String} A string representation of the packet
|
||||
*/
|
||||
function write_packet(symmetric_algorithm, key, data) {
|
||||
this.write = function(symmetric_algorithm, key, data) {
|
||||
return String.fromCharCode(this.version) + this.encrypted;
|
||||
}
|
||||
|
||||
this.encrypt = function(symmetric_algorithm, key) {
|
||||
var bytes = this.data.write()
|
||||
|
||||
var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm);
|
||||
var prefix = prefixrandom
|
||||
+ prefixrandom.charAt(prefixrandom.length - 2)
|
||||
+ prefixrandom.charAt(prefixrandom.length - 1);
|
||||
var tohash = data;
|
||||
+ prefixrandom.charAt(prefixrandom.length - 1)
|
||||
|
||||
var tohash = bytes;
|
||||
tohash += String.fromCharCode(0xD3);
|
||||
tohash += String.fromCharCode(0x14);
|
||||
|
||||
util.print_debug_hexstr_dump("data to be hashed:"
|
||||
, prefix + tohash);
|
||||
|
||||
tohash += str_sha1(prefix + tohash);
|
||||
|
||||
util.print_debug_hexstr_dump("hash:"
|
||||
, tohash.substring(tohash.length - 20,
|
||||
tohash.length));
|
||||
var result = openpgp_crypto_symmetricEncrypt(prefixrandom,
|
||||
|
||||
this.encrypted = openpgp_crypto_symmetricEncrypt(prefixrandom,
|
||||
symmetric_algorithm, key, tohash, false).substring(0,
|
||||
prefix.length + tohash.length);
|
||||
var header = openpgp_packet.write_packet_header(18, result.length + 1)
|
||||
+ String.fromCharCode(1);
|
||||
this.encryptedData = result;
|
||||
return header + result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,34 +115,39 @@ function openpgp_packet_encryptedintegrityprotecteddata() {
|
|||
* @param {String} key The key of cipher blocksize length to be used
|
||||
* @return {String} The decrypted data of this packet
|
||||
*/
|
||||
function decrypt(symmetric_algorithm_type, key) {
|
||||
this.decryptedData = openpgp_crypto_symmetricDecrypt(
|
||||
symmetric_algorithm_type, key, this.encryptedData, false);
|
||||
this.decrypt = function(symmetric_algorithm_type, key) {
|
||||
var decrypted = openpgp_crypto_symmetricDecrypt(
|
||||
symmetric_algorithm_type, key, this.encrypted, false);
|
||||
|
||||
|
||||
// there must be a modification detection code packet as the
|
||||
// last packet and everything gets hashed except the hash itself
|
||||
this.hash = str_sha1(openpgp_crypto_MDCSystemBytes(
|
||||
symmetric_algorithm_type, key, this.encryptedData)
|
||||
+ this.decryptedData.substring(0,
|
||||
this.decryptedData.length - 20));
|
||||
this.hash = str_sha1(
|
||||
openpgp_crypto_MDCSystemBytes(symmetric_algorithm_type, key, this.encrypted)
|
||||
+ decrypted.substring(0, decrypted.length - 20));
|
||||
|
||||
util.print_debug_hexstr_dump("calc hash = ", this.hash);
|
||||
if (this.hash == this.decryptedData.substring(
|
||||
this.decryptedData.length - 20, this.decryptedData.length))
|
||||
return this.decryptedData;
|
||||
else
|
||||
util
|
||||
.print_error("Decryption stopped: discovered a modification of encrypted data.");
|
||||
return null;
|
||||
|
||||
this.data.read(decrypted);
|
||||
|
||||
// We pop the mandatory modification detection code packet.
|
||||
var mdc = this.data.packets.pop();
|
||||
|
||||
if(this.hash != mdc.hash) {
|
||||
this.data = null;
|
||||
util.print_error("Decryption stopped: discovered a " +
|
||||
"modification of encrypted data.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function toString() {
|
||||
this.toString = function() {
|
||||
var data = '';
|
||||
if(openpgp.config.debug)
|
||||
data = ' data: Bytes ['
|
||||
+ util.hexstrdump(this.encryptedData) + ']';
|
||||
+ util.hexstrdump(this.encrypted) + ']';
|
||||
|
||||
return '5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n'
|
||||
+ ' length: '
|
||||
+ this.packetLength
|
||||
+ '\n'
|
||||
+ ' version: '
|
||||
+ this.version
|
||||
|
@ -148,8 +155,11 @@ function openpgp_packet_encryptedintegrityprotecteddata() {
|
|||
+ data;
|
||||
}
|
||||
|
||||
this.write_packet = write_packet;
|
||||
this.read_packet = read_packet;
|
||||
this.toString = toString;
|
||||
this.decrypt = decrypt;
|
||||
};
|
||||
|
||||
function openpgp_packet_modification_detection_code() {
|
||||
this.hash = null;
|
||||
this.read = function(bytes) {
|
||||
this.hash = bytes;
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@ unittests.register("Packet testing", function() {
|
|||
|
||||
var tests = [function() {
|
||||
|
||||
|
||||
|
||||
var literal = new openpgp_packet_literal();
|
||||
literal.set_data('Hello world', openpgp_packet_literal.format.utf8);
|
||||
|
||||
|
@ -27,6 +25,27 @@ unittests.register("Packet testing", function() {
|
|||
|
||||
return new test_result('Symmetrically encrypted data packet',
|
||||
msg2.packets[0].data.packets[0].data == literal.data);
|
||||
}, function() {
|
||||
var key = '12345678901234567890123456789012',
|
||||
algo = openpgp.symmetric.aes256;
|
||||
|
||||
var literal = new openpgp_packet_literal(),
|
||||
enc = new openpgp_packet_sym_encrypted_integrity_protected(),
|
||||
msg = new openpgp_packetlist();
|
||||
|
||||
literal.set_data('Hello world!', openpgp_packet_literal.format.utf8);
|
||||
enc.data.push(literal);
|
||||
enc.encrypt(algo, key);
|
||||
msg.push(enc);
|
||||
|
||||
var msg2 = new openpgp_packetlist();
|
||||
msg2.read(msg.write());
|
||||
|
||||
msg2.packets[0].decrypt(algo, key);
|
||||
|
||||
return new test_result('Sym. encrypted integrity protected data packet',
|
||||
msg2.packets[0].data.packets[0].data == literal.data);
|
||||
|
||||
}];
|
||||
|
||||
var results = [];
|
||||
|
|
Loading…
Reference in New Issue
Block a user