<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: packet/signature.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: packet/signature.js</h1> <section> <article> <pre class="prettyprint source"><code>// 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 /** * Implementation of the Signature Packet (Tag 2)<br/> * <br/> * {@link http://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: * A Signature packet describes a binding between some public key and * some data. The most common signatures are a signature of a file or a * block of text, and a signature that is a certification of a User ID. * @requires crypto * @requires enums * @requires packet/packet * @requires type/keyid * @requires type/mpi * @requires util * @module packet/signature */ module.exports = Signature; var util = require('../util.js'), packet = require('./packet.js'), enums = require('../enums.js'), crypto = require('../crypto'), type_mpi = require('../type/mpi.js'), type_keyid = require('../type/keyid.js'); /** * @constructor */ function Signature() { this.tag = enums.packet.signature; this.version = 4; this.signatureType = null; this.hashAlgorithm = null; this.publicKeyAlgorithm = null; this.signatureData = null; this.signedHashValue = null; this.created = new Date(); this.signatureExpirationTime = null; this.signatureNeverExpires = true; this.exportable = null; this.trustLevel = null; this.trustAmount = null; this.regularExpression = null; this.revocable = null; this.keyExpirationTime = null; this.keyNeverExpires = null; this.preferredSymmetricAlgorithms = null; this.revocationKeyClass = null; this.revocationKeyAlgorithm = null; this.revocationKeyFingerprint = null; this.issuerKeyId = new type_keyid(); this.notation = null; this.preferredHashAlgorithms = null; this.preferredCompressionAlgorithms = null; this.keyServerPreferences = null; this.preferredKeyServer = null; this.isPrimaryUserID = null; this.policyURI = null; this.keyFlags = null; this.signersUserId = null; this.reasonForRevocationFlag = null; this.reasonForRevocationString = null; this.features = null; this.signatureTargetPublicKeyAlgorithm = null; this.signatureTargetHashAlgorithm = null; this.signatureTargetHash = null; this.embeddedSignature = null; this.verified = false; } /** * parsing function for a signature packet (tag 2). * @param {String} bytes payload of a tag 2 packet * @param {Integer} position position to start reading from the bytes string * @param {Integer} len length of the packet or the remaining length of bytes at position * @return {module:packet/signature} object representation */ Signature.prototype.read = function (bytes) { var i = 0; this.version = bytes.charCodeAt(i++); // switch on version (3 and 4) switch (this.version) { case 3: // One-octet length of following hashed material. MUST be 5. if (bytes.charCodeAt(i++) != 5) util.print_debug("packet/signature.js\n" + 'invalid One-octet length of following hashed material.' + 'MUST be 5. @:' + (i - 1)); var sigpos = i; // One-octet signature type. this.signatureType = bytes.charCodeAt(i++); // Four-octet creation time. this.created = util.readDate(bytes.substr(i, 4)); i += 4; // storing data appended to data which gets verified this.signatureData = bytes.substring(sigpos, i); // Eight-octet Key ID of signer. this.issuerKeyId.read(bytes.substring(i, i + 8)); i += 8; // One-octet public-key algorithm. this.publicKeyAlgorithm = bytes.charCodeAt(i++); // One-octet hash algorithm. this.hashAlgorithm = bytes.charCodeAt(i++); break; case 4: this.signatureType = bytes.charCodeAt(i++); this.publicKeyAlgorithm = bytes.charCodeAt(i++); this.hashAlgorithm = bytes.charCodeAt(i++); function subpackets(bytes) { // Two-octet scalar octet count for following subpacket data. var subpacket_length = util.readNumber( bytes.substr(0, 2)); var i = 2; // subpacket data set (zero or more subpackets) var subpacked_read = 0; while (i < 2 + subpacket_length) { var len = packet.readSimpleLength(bytes.substr(i)); i += len.offset; this.read_sub_packet(bytes.substr(i, len.len)); i += len.len; } return i; } // hashed subpackets i += subpackets.call(this, bytes.substr(i), true); // A V4 signature hashes the packet body // starting from its first field, the version number, through the end // of the hashed subpacket data. Thus, the fields hashed are the // signature version, the signature type, the public-key algorithm, the // hash algorithm, the hashed subpacket length, and the hashed // subpacket body. this.signatureData = bytes.substr(0, i); // unhashed subpackets i += subpackets.call(this, bytes.substr(i), false); break; default: throw new Error('Version ' + version + ' of the signature is unsupported.'); } // Two-octet field holding left 16 bits of signed hash value. this.signedHashValue = bytes.substr(i, 2); i += 2; this.signature = bytes.substr(i); }; Signature.prototype.write = function () { return this.signatureData + util.writeNumber(0, 2) + // Number of unsigned subpackets. this.signedHashValue + this.signature; }; /** * Signs provided data. This needs to be done prior to serialization. * @param {module:packet/secret_key} key private key used to sign the message. * @param {Object} data Contains packets to be signed. */ Signature.prototype.sign = function (key, data) { var signatureType = enums.write(enums.signature, this.signatureType), publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm), hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm); var result = String.fromCharCode(4); result += String.fromCharCode(signatureType); result += String.fromCharCode(publicKeyAlgorithm); result += String.fromCharCode(hashAlgorithm); this.issuerKeyId = key.getKeyId(); // Add hashed subpackets result += this.write_all_sub_packets(); this.signatureData = result; var trailer = this.calculateTrailer(); var toHash = this.toSign(signatureType, data) + this.signatureData + trailer; var hash = crypto.hash.digest(hashAlgorithm, toHash); this.signedHashValue = hash.substr(0, 2); this.signature = crypto.signature.sign(hashAlgorithm, publicKeyAlgorithm, key.mpi, toHash); }; /** * Creates string of bytes with all subpacket data * @return {String} a string-representation of a all subpacket data */ Signature.prototype.write_all_sub_packets = function () { var sub = enums.signatureSubpacket; var result = ''; var bytes = ''; if (this.created !== null) { result += write_sub_packet(sub.signature_creation_time, util.writeDate(this.created)); } if (this.signatureExpirationTime !== null) { result += write_sub_packet(sub.signature_expiration_time, util.writeNumber(this.signatureExpirationTime, 4)); } if (this.exportable !== null) { result += write_sub_packet(sub.exportable_certification, String.fromCharCode(this.exportable ? 1 : 0)); } if (this.trustLevel !== null) { bytes = String.fromCharCode(this.trustLevel) + String.fromCharCode(this.trustAmount); result += write_sub_packet(sub.trust_signature, bytes); } if (this.regularExpression !== null) { result += write_sub_packet(sub.regular_expression, this.regularExpression); } if (this.revocable !== null) { result += write_sub_packet(sub.revocable, String.fromCharCode(this.revocable ? 1 : 0)); } if (this.keyExpirationTime !== null) { result += write_sub_packet(sub.key_expiration_time, util.writeNumber(this.keyExpirationTime, 4)); } if (this.preferredSymmetricAlgorithms !== null) { bytes = util.bin2str(this.preferredSymmetricAlgorithms); result += write_sub_packet(sub.preferred_symmetric_algorithms, bytes); } if (this.revocationKeyClass !== null) { bytes = String.fromCharCode(this.revocationKeyClass); bytes += String.fromCharCode(this.revocationKeyAlgorithm); bytes += this.revocationKeyFingerprint; result += write_sub_packet(sub.revocation_key, bytes); } if (!this.issuerKeyId.isNull()) { result += write_sub_packet(sub.issuer, this.issuerKeyId.write()); } if (this.notation !== null) { for (var name in this.notation) { if (this.notation.hasOwnProperty(name)) { var value = this.notation[name]; bytes = String.fromCharCode(0x80); bytes += String.fromCharCode(0); bytes += String.fromCharCode(0); bytes += String.fromCharCode(0); // 2 octets of name length bytes += util.writeNumber(name.length, 2); // 2 octets of value length bytes += util.writeNumber(value.length, 2); bytes += name + value; result += write_sub_packet(sub.notation_data, bytes); } } } if (this.preferredHashAlgorithms !== null) { bytes = util.bin2str(this.preferredHashAlgorithms); result += write_sub_packet(sub.preferred_hash_algorithms, bytes); } if (this.preferredCompressionAlgorithms !== null) { bytes = util.bin2str(this.preferredCompressionAlgorithms); result += write_sub_packet(sub.preferred_hash_algorithms, bytes); } if (this.keyServerPreferences !== null) { bytes = util.bin2str(this.keyServerPreferences); result += write_sub_packet(sub.key_server_preferences, bytes); } if (this.preferredKeyServer !== null) { result += write_sub_packet(sub.preferred_key_server, this.preferredKeyServer); } if (this.isPrimaryUserID !== null) { result += write_sub_packet(sub.primary_user_id, String.fromCharCode(this.isPrimaryUserID ? 1 : 0)); } if (this.policyURI !== null) { result += write_sub_packet(sub.policy_uri, this.policyURI); } if (this.keyFlags !== null) { bytes = util.bin2str(this.keyFlags); result += write_sub_packet(sub.key_flags, bytes); } if (this.signersUserId !== null) { result += write_sub_packet(sub.signers_user_id, this.signersUserId); } if (this.reasonForRevocationFlag !== null) { bytes = String.fromCharCode(this.reasonForRevocationFlag); bytes += this.reasonForRevocationString; result += write_sub_packet(sub.reason_for_revocation, bytes); } if (this.features !== null) { bytes = util.bin2str(this.features); result += write_sub_packet(sub.features, bytes); } if (this.signatureTargetPublicKeyAlgorithm !== null) { bytes = String.fromCharCode(this.signatureTargetPublicKeyAlgorithm); bytes += String.fromCharCode(this.signatureTargetHashAlgorithm); bytes += this.signatureTargetHash; result += write_sub_packet(sub.signature_target, bytes); } if (this.embeddedSignature !== null) { result += write_sub_packet(sub.embedded_signature, this.embeddedSignature.write()); } result = util.writeNumber(result.length, 2) + result; return result; }; /** * creates a string representation of a sub signature packet (See {@link http://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC 4880 5.2.3.1}) * @param {Integer} type subpacket signature type. Signature types as described * in {@link http://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 Section 5.2.3.2} * @param {String} data data to be included * @return {String} a string-representation of a sub signature packet (See {@link http://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC 4880 5.2.3.1}) */ function write_sub_packet(type, data) { var result = ""; result += packet.writeSimpleLength(data.length + 1); result += String.fromCharCode(type); result += data; return result; } // V4 signature sub packets Signature.prototype.read_sub_packet = function (bytes) { var mypos = 0; function read_array(prop, bytes) { this[prop] = []; for (var i = 0; i < bytes.length; i++) { this[prop].push(bytes.charCodeAt(i)); } } // The leftwost bit denotes a "critical" packet, but we ignore it. var type = bytes.charCodeAt(mypos++) & 0x7F; var seconds; // subpacket type switch (type) { case 2: // Signature Creation Time this.created = util.readDate(bytes.substr(mypos)); break; case 3: // Signature Expiration Time in seconds seconds = util.readNumber(bytes.substr(mypos)); this.signatureNeverExpires = seconds === 0; this.signatureExpirationTime = seconds; break; case 4: // Exportable Certification this.exportable = bytes.charCodeAt(mypos++) == 1; break; case 5: // Trust Signature this.trustLevel = bytes.charCodeAt(mypos++); this.trustAmount = bytes.charCodeAt(mypos++); break; case 6: // Regular Expression this.regularExpression = bytes.substr(mypos); break; case 7: // Revocable this.revocable = bytes.charCodeAt(mypos++) == 1; break; case 9: // Key Expiration Time in seconds seconds = util.readNumber(bytes.substr(mypos)); this.keyExpirationTime = seconds; this.keyNeverExpires = seconds === 0; break; case 11: // Preferred Symmetric Algorithms this.preferredSymmetricAlgorithms = []; while (mypos != bytes.length) { this.preferredSymmetricAlgorithms.push(bytes.charCodeAt(mypos++)); } break; case 12: // Revocation Key // (1 octet of class, 1 octet of public-key algorithm ID, 20 // octets of // fingerprint) this.revocationKeyClass = bytes.charCodeAt(mypos++); this.revocationKeyAlgorithm = bytes.charCodeAt(mypos++); this.revocationKeyFingerprint = bytes.substr(mypos, 20); break; case 16: // Issuer this.issuerKeyId.read(bytes.substr(mypos)); break; case 20: // Notation Data // We don't know how to handle anything but a text flagged data. if (bytes.charCodeAt(mypos) == 0x80) { // We extract key/value tuple from the byte stream. mypos += 4; var m = util.readNumber(bytes.substr(mypos, 2)); mypos += 2; var n = util.readNumber(bytes.substr(mypos, 2)); mypos += 2; var name = bytes.substr(mypos, m), value = bytes.substr(mypos + m, n); this.notation = this.notation || {}; this.notation[name] = value; } else throw new Error("Unsupported notation flag."); break; case 21: // Preferred Hash Algorithms read_array.call(this, 'preferredHashAlgorithms', bytes.substr(mypos)); break; case 22: // Preferred Compression Algorithms read_array.call(this, 'preferredCompressionAlgorithms ', bytes.substr(mypos)); break; case 23: // Key Server Preferences read_array.call(this, 'keyServerPreferencess', bytes.substr(mypos)); break; case 24: // Preferred Key Server this.preferredKeyServer = bytes.substr(mypos); break; case 25: // Primary User ID this.isPrimaryUserID = bytes[mypos++] !== 0; break; case 26: // Policy URI this.policyURI = bytes.substr(mypos); break; case 27: // Key Flags read_array.call(this, 'keyFlags', bytes.substr(mypos)); break; case 28: // Signer's User ID this.signersUserId += bytes.substr(mypos); break; case 29: // Reason for Revocation this.reasonForRevocationFlag = bytes.charCodeAt(mypos++); this.reasonForRevocationString = bytes.substr(mypos); break; case 30: // Features read_array.call(this, 'features', bytes.substr(mypos)); break; case 31: // Signature Target // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) this.signatureTargetPublicKeyAlgorithm = bytes.charCodeAt(mypos++); this.signatureTargetHashAlgorithm = bytes.charCodeAt(mypos++); var len = crypto.getHashByteLength(this.signatureTargetHashAlgorithm); this.signatureTargetHash = bytes.substr(mypos, len); break; case 32: // Embedded Signature this.embeddedSignature = new Signature(); this.embeddedSignature.read(bytes.substr(mypos)); break; default: throw new Error("Unknown signature subpacket type " + type + " @:" + mypos); } }; // Produces data to produce signature on Signature.prototype.toSign = function (type, data) { var t = enums.signature; switch (type) { case t.binary: case t.text: return data.getBytes(); case t.standalone: return ''; case t.cert_generic: case t.cert_persona: case t.cert_casual: case t.cert_positive: case t.cert_revocation: var packet, tag; if (data.userid !== undefined) { tag = 0xB4; packet = data.userid; } else if (data.userattribute !== undefined) { tag = 0xD1; packet = data.userattribute; } else throw new Error('Either a userid or userattribute packet needs to be ' + 'supplied for certification.'); var bytes = packet.write(); if (this.version == 4) { return this.toSign(t.key, data) + String.fromCharCode(tag) + util.writeNumber(bytes.length, 4) + bytes; } else if (this.version == 3) { return this.toSign(t.key, data) + bytes; } break; case t.subkey_binding: case t.subkey_revocation: case t.key_binding: return this.toSign(t.key, data) + this.toSign(t.key, { key: data.bind }); case t.key: if (data.key === undefined) throw new Error('Key packet is required for this sigtature.'); return data.key.writeOld(); case t.key_revocation: return this.toSign(t.key, data); case t.timestamp: return ''; case t.third_party: throw new Error('Not implemented'); default: throw new Error('Unknown signature type.'); } }; Signature.prototype.calculateTrailer = function () { // calculating the trailer var trailer = ''; // V3 signatures don't have a trailer if (this.version == 3) return trailer; trailer += String.fromCharCode(4); // Version trailer += String.fromCharCode(0xFF); trailer += util.writeNumber(this.signatureData.length, 4); return trailer; }; /** * verifys the signature packet. Note: not signature types are implemented * @param {String|Object} data data which on the signature applies * @param {module:packet/public_subkey|module:packet/public_key} key the public key to verify the signature * @return {boolean} True if message is verified, else false. */ Signature.prototype.verify = function (key, data) { var signatureType = enums.write(enums.signature, this.signatureType), publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm), hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm); var bytes = this.toSign(signatureType, data), trailer = this.calculateTrailer(); var mpicount = 0; // Algorithm-Specific Fields for RSA signatures: // - multiprecision number (MPI) of RSA signature value m**d mod n. if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4) mpicount = 1; // Algorithm-Specific Fields for DSA signatures: // - MPI of DSA value r. // - MPI of DSA value s. else if (publicKeyAlgorithm == 17) mpicount = 2; var mpi = [], i = 0; for (var j = 0; j < mpicount; j++) { mpi[j] = new type_mpi(); i += mpi[j].read(this.signature.substr(i)); } this.verified = crypto.signature.verify(publicKeyAlgorithm, hashAlgorithm, mpi, key.mpi, bytes + this.signatureData + trailer); return this.verified; }; /** * Verifies signature expiration date * @return {Boolean} true if expired */ Signature.prototype.isExpired = function () { if (!this.signatureNeverExpires) { return Date.now() > (this.created.getTime() + this.signatureExpirationTime*1000); } return false; }; /** * Fix custom types after cloning */ Signature.prototype.postCloneTypeFix = function() { this.issuerKeyId = type_keyid.fromClone(this.issuerKeyId); }; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-async_proxy.html">async_proxy</a></li><li><a href="module-cleartext.html">cleartext</a></li><li><a href="module-config.html">config</a></li><li><a href="config.html">config/config</a></li><li><a href="localStorage.html">config/localStorage</a></li><li><a href="module-crypto.html">crypto</a></li><li><a href="cfb.html">crypto/cfb</a></li><li><a href="cipher.html">crypto/cipher</a></li><li><a href="aes.html">crypto/cipher/aes</a></li><li><a href="blowfish.html">crypto/cipher/blowfish</a></li><li><a href="cast5.html">crypto/cipher/cast5</a></li><li><a href="des.html">crypto/cipher/des</a></li><li><a href="twofish.html">crypto/cipher/twofish</a></li><li><a href="crypto.html">crypto/crypto</a></li><li><a href="hash.html">crypto/hash</a></li><li><a href="md5.html">crypto/hash/md5</a></li><li><a href="ripe-md.html">crypto/hash/ripe-md</a></li><li><a href="sha.html">crypto/hash/sha</a></li><li><a href="pkcs1.html">crypto/pkcs1</a></li><li><a href="public_key.html">crypto/public_key</a></li><li><a href="dsa.html">crypto/public_key/dsa</a></li><li><a href="elgamal.html">crypto/public_key/elgamal</a></li><li><a href="jsbn.html">crypto/public_key/jsbn</a></li><li><a href="rsa.html">crypto/public_key/rsa</a></li><li><a href="random.html">crypto/random</a></li><li><a href="signature.html">crypto/signature</a></li><li><a href="armor.html">encoding/armor</a></li><li><a href="base64.html">encoding/base64</a></li><li><a href="module-enums.html">enums</a></li><li><a href="module-key.html">key</a></li><li><a href="module-keyring.html">keyring</a></li><li><a href="keyring.html">keyring/keyring</a></li><li><a href="localstore.html">keyring/localstore</a></li><li><a href="module-message.html">message</a></li><li><a href="module-openpgp.html">openpgp</a></li><li><a href="module-packet.html">packet</a></li><li><a href="compressed.html">packet/compressed</a></li><li><a href="literal.html">packet/literal</a></li><li><a href="marker.html">packet/marker</a></li><li><a href="one_pass_signature.html">packet/one_pass_signature</a></li><li><a href="packet.html">packet/packet</a></li><li><a href="packetlist.html">packet/packetlist</a></li><li><a href="public_key_.html">packet/public_key</a></li><li><a href="public_key_encrypted_session_key.html">packet/public_key_encrypted_session_key</a></li><li><a href="public_subkey.html">packet/public_subkey</a></li><li><a href="secret_key.html">packet/secret_key</a></li><li><a href="secret_subkey.html">packet/secret_subkey</a></li><li><a href="signature_.html">packet/signature</a></li><li><a href="sym_encrypted_integrity_protected.html">packet/sym_encrypted_integrity_protected</a></li><li><a href="sym_encrypted_session_key.html">packet/sym_encrypted_session_key</a></li><li><a href="symmetrically_encrypted.html">packet/symmetrically_encrypted</a></li><li><a href="trust.html">packet/trust</a></li><li><a href="user_attribute.html">packet/user_attribute</a></li><li><a href="userid.html">packet/userid</a></li><li><a href="keyid.html">type/keyid</a></li><li><a href="mpi.html">type/mpi</a></li><li><a href="s2k.html">type/s2k</a></li><li><a href="module-util.html">util</a></li></ul><h3>Classes</h3><ul><li><a href="JXG.Util.html">JXG.Util</a></li><li><a href="module-async_proxy-AsyncProxy.html">async_proxy~AsyncProxy</a></li><li><a href="module-cleartext-CleartextMessage.html">cleartext~CleartextMessage</a></li><li><a href="localStorage-LocalStorage.html">config/localStorage~LocalStorage</a></li><li><a href="keyring-Keyring.html">keyring/keyring~Keyring</a></li><li><a href="module-key-Key.html">key~Key</a></li><li><a href="module-key-SubKey.html">key~SubKey</a></li><li><a href="module-key-User.html">key~User</a></li><li><a href="module-message-Message.html">message~Message</a></li><li><a href="compressed-Compressed.html">packet/compressed~Compressed</a></li><li><a href="literal-Literal.html">packet/literal~Literal</a></li><li><a href="marker-Marker.html">packet/marker~Marker</a></li><li><a href="one_pass_signature-OnePassSignature.html">packet/one_pass_signature~OnePassSignature</a></li><li><a href="packetlist-Packetlist.html">packet/packetlist~Packetlist</a></li><li><a href="public_key_encrypted_session_key-PublicKeyEncryptedSessionKey.html">packet/public_key_encrypted_session_key~PublicKeyEncryptedSessionKey</a></li><li><a href="public_key-PublicKey.html">packet/public_key~PublicKey</a></li><li><a href="public_subkey-PublicSubkey.html">packet/public_subkey~PublicSubkey</a></li><li><a href="secret_key-SecretKey.html">packet/secret_key~SecretKey</a></li><li><a href="secret_subkey-SecretSubkey.html">packet/secret_subkey~SecretSubkey</a></li><li><a href="signature-Signature.html">packet/signature~Signature</a></li><li><a href="sym_encrypted_integrity_protected-SymEncryptedIntegrityProtected.html">packet/sym_encrypted_integrity_protected~SymEncryptedIntegrityProtected</a></li><li><a href="sym_encrypted_session_key-SymEncryptedSessionKey.html">packet/sym_encrypted_session_key~SymEncryptedSessionKey</a></li><li><a href="symmetrically_encrypted-SymmetricallyEncrypted.html">packet/symmetrically_encrypted~SymmetricallyEncrypted</a></li><li><a href="trust-Trust.html">packet/trust~Trust</a></li><li><a href="user_attribute-UserAttribute.html">packet/user_attribute~UserAttribute</a></li><li><a href="userid-Userid.html">packet/userid~Userid</a></li><li><a href="keyid-Keyid.html">type/keyid~Keyid</a></li><li><a href="mpi-MPI.html">type/mpi~MPI</a></li><li><a href="s2k-S2K.html">type/s2k~S2K</a></li></ul> </nav> <br clear="both"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Wed Feb 12 2014 15:09:02 GMT+0100 (MEZ) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>