
work correctly with utf8 strings. Fixeda visibility issue with the testing suite and added relevant unit tests.
779 lines
38 KiB
HTML
779 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>JSDoc: Source: packet/openpgp.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/openpgp.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
|
|
|
|
/**
|
|
* @class
|
|
* @classdesc Implementation of the Signature Packet (Tag 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.
|
|
*/
|
|
function openpgp_packet_signature() {
|
|
this.tagType = 2;
|
|
this.signatureType = null;
|
|
this.creationTime = null;
|
|
this.keyId = null;
|
|
this.signatureData = null;
|
|
this.signatureExpirationTime = null;
|
|
this.signatureNeverExpires = null;
|
|
this.signedHashValue = null;
|
|
this.MPIs = null;
|
|
this.publicKeyAlgorithm = null;
|
|
this.hashAlgorithm = null;
|
|
this.exportable = null;
|
|
this.trustLevel = null;
|
|
this.trustAmount = null;
|
|
this.regular_expression = null;
|
|
this.revocable = null;
|
|
this.keyExpirationTime = null;
|
|
this.keyNeverExpires = null;
|
|
this.preferredSymmetricAlgorithms = null;
|
|
this.revocationKeyClass = null;
|
|
this.revocationKeyAlgorithm = null;
|
|
this.revocationKeyFingerprint = null;
|
|
this.issuerKeyId = null;
|
|
this.notationFlags = null;
|
|
this.notationName = null;
|
|
this.notationValue = 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.signatureTargetPublicKeyAlgorithm = null;
|
|
this.signatureTargetHashAlgorithm = null;
|
|
this.signatureTargetHash = null;
|
|
this.embeddedSignature = null;
|
|
this.verified = false;
|
|
|
|
|
|
/**
|
|
* parsing function for a signature packet (tag 2).
|
|
* @param {String} input payload of a tag 2 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.data = input.substring (position, position+len);
|
|
if (len < 0) {
|
|
util.print_debug("openpgp.packet.signature.js\n"+"openpgp_packet_signature read_packet length < 0 @:"+position);
|
|
return null;
|
|
}
|
|
var mypos = position;
|
|
this.packetLength = len;
|
|
// alert('starting parsing signature: '+position+' '+this.packetLength);
|
|
this.version = input[mypos++].charCodeAt();
|
|
// switch on version (3 and 4)
|
|
switch (this.version) {
|
|
case 3:
|
|
// One-octet length of following hashed material. MUST be 5.
|
|
if (input[mypos++].charCodeAt() != 5)
|
|
util.print_debug("openpgp.packet.signature.js\n"+'invalid One-octet length of following hashed material. MUST be 5. @:'+(mypos-1));
|
|
var sigpos = mypos;
|
|
// One-octet signature type.
|
|
this.signatureType = input[mypos++].charCodeAt();
|
|
|
|
// Four-octet creation time.
|
|
this.creationTime = new Date(((input[mypos++].charCodeAt()) << 24 |
|
|
(input[mypos++].charCodeAt() << 16) | (input[mypos++].charCodeAt() << 8) |
|
|
input[mypos++].charCodeAt())* 1000);
|
|
|
|
// storing data appended to data which gets verified
|
|
this.signatureData = input.substring(position, mypos);
|
|
|
|
// Eight-octet Key ID of signer.
|
|
this.keyId = input.substring(mypos, mypos +8);
|
|
mypos += 8;
|
|
|
|
// One-octet public-key algorithm.
|
|
this.publicKeyAlgorithm = input[mypos++].charCodeAt();
|
|
|
|
// One-octet hash algorithm.
|
|
this.hashAlgorithm = input[mypos++].charCodeAt();
|
|
|
|
// Two-octet field holding left 16 bits of signed hash value.
|
|
this.signedHashValue = (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
|
|
var mpicount = 0;
|
|
// Algorithm-Specific Fields for RSA signatures:
|
|
// - multiprecision integer (MPI) of RSA signature value m**d mod n.
|
|
if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
|
|
mpicount = 1;
|
|
// Algorithm-Specific Fields for DSA signatures:
|
|
// - MPI of DSA value r.
|
|
// - MPI of DSA value s.
|
|
else if (this.publicKeyAlgorithm == 17)
|
|
mpicount = 2;
|
|
|
|
this.MPIs = new Array();
|
|
for (var i = 0; i < mpicount; i++) {
|
|
this.MPIs[i] = new openpgp_type_mpi();
|
|
if (this.MPIs[i].read(input, mypos, (mypos-position)) != null &&
|
|
!this.packetLength < (mypos-position)) {
|
|
mypos += this.MPIs[i].packetLength;
|
|
} else {
|
|
util.print_error('signature contains invalid MPI @:'+mypos);
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
this.signatureType = input[mypos++].charCodeAt();
|
|
this.publicKeyAlgorithm = input[mypos++].charCodeAt();
|
|
this.hashAlgorithm = input[mypos++].charCodeAt();
|
|
|
|
// Two-octet scalar octet count for following hashed subpacket
|
|
// data.
|
|
var hashed_subpacket_count = (input[mypos++].charCodeAt() << 8) + input[mypos++].charCodeAt();
|
|
|
|
// Hashed subpacket data set (zero or more subpackets)
|
|
var subpacket_length = 0;
|
|
while (hashed_subpacket_count != subpacket_length) {
|
|
if (hashed_subpacket_count < subpacket_length) {
|
|
util.print_debug("openpgp.packet.signature.js\n"+"hashed missed something: "+mypos+" c:"+hashed_subpacket_count+" l:"+subpacket_length);
|
|
}
|
|
|
|
subpacket_length += this._raw_read_signature_sub_packet(input,
|
|
mypos + subpacket_length, hashed_subpacket_count
|
|
- subpacket_length);
|
|
}
|
|
|
|
mypos += hashed_subpacket_count;
|
|
this.signatureData = input.substring(position, mypos);
|
|
|
|
// alert("signatureData: "+util.hexstrdump(this.signatureData));
|
|
|
|
// Two-octet scalar octet count for the following unhashed subpacket
|
|
var subpacket_count = (input[mypos++].charCodeAt() << 8) + input[mypos++].charCodeAt();
|
|
|
|
// Unhashed subpacket data set (zero or more subpackets).
|
|
subpacket_length = 0;
|
|
while (subpacket_count != subpacket_length) {
|
|
if (subpacket_count < subpacket_length) {
|
|
util.print_debug("openpgp.packet.signature.js\n"+"missed something: "+subpacket_length+" c:"+subpacket_count+" "+" l:"+subpacket_length);
|
|
}
|
|
subpacket_length += this._raw_read_signature_sub_packet(input,
|
|
mypos + subpacket_length, subpacket_count
|
|
- subpacket_length);
|
|
|
|
}
|
|
mypos += subpacket_count;
|
|
// Two-octet field holding the left 16 bits of the signed hash
|
|
// value.
|
|
this.signedHashValue = (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
|
|
// One or more multiprecision integers comprising the signature.
|
|
// This portion is algorithm specific, as described above.
|
|
var mpicount = 0;
|
|
if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
|
|
mpicount = 1;
|
|
else if (this.publicKeyAlgorithm == 17)
|
|
mpicount = 2;
|
|
|
|
this.MPIs = new Array();
|
|
for (var i = 0; i < mpicount; i++) {
|
|
this.MPIs[i] = new openpgp_type_mpi();
|
|
if (this.MPIs[i].read(input, mypos, (mypos-position)) != null &&
|
|
!this.packetLength < (mypos-position)) {
|
|
mypos += this.MPIs[i].packetLength;
|
|
} else {
|
|
util.print_error('signature contains invalid MPI @:'+mypos);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
util.print_error("openpgp.packet.signature.js\n"+'unknown signature packet version'+this.version);
|
|
break;
|
|
}
|
|
// util.print_message("openpgp.packet.signature.js\n"+"end signature: l: "+this.packetLength+"m: "+mypos+" m-p: "+(mypos-position));
|
|
return this;
|
|
}
|
|
/**
|
|
* creates a string representation of a message signature packet (tag 2).
|
|
* This can be only used on text data
|
|
* @param {Integer} signature_type should be 1 (one)
|
|
* @param {String} data data to be signed
|
|
* @param {openpgp_msg_privatekey} privatekey private key used to sign the message. (secMPIs MUST be unlocked)
|
|
* @return {String} string representation of a signature packet
|
|
*/
|
|
function write_message_signature(signature_type, data, privatekey) {
|
|
var publickey = privatekey.privateKeyPacket.publicKey;
|
|
var hash_algo = privatekey.getPreferredSignatureHashAlgorithm();
|
|
var result = String.fromCharCode(4);
|
|
result += String.fromCharCode(signature_type);
|
|
result += String.fromCharCode(publickey.publicKeyAlgorithm);
|
|
result += String.fromCharCode(hash_algo);
|
|
var d = Math.round(new Date().getTime() / 1000);
|
|
var datesubpacket = write_sub_signature_packet(2,""+
|
|
String.fromCharCode((d >> 24) & 0xFF) +
|
|
String.fromCharCode((d >> 16) & 0xFF) +
|
|
String.fromCharCode((d >> 8) & 0xFF) +
|
|
String.fromCharCode(d & 0xFF));
|
|
var issuersubpacket = write_sub_signature_packet(16, privatekey.getKeyId());
|
|
result += String.fromCharCode(((datesubpacket.length + issuersubpacket.length) >> 8) & 0xFF);
|
|
result += String.fromCharCode ((datesubpacket.length + issuersubpacket.length) & 0xFF);
|
|
result += datesubpacket;
|
|
result += issuersubpacket;
|
|
var trailer = '';
|
|
|
|
trailer += String.fromCharCode(4);
|
|
trailer += String.fromCharCode(0xFF);
|
|
trailer += String.fromCharCode((result.length) >> 24);
|
|
trailer += String.fromCharCode(((result.length) >> 16) & 0xFF);
|
|
trailer += String.fromCharCode(((result.length) >> 8) & 0xFF);
|
|
trailer += String.fromCharCode((result.length) & 0xFF);
|
|
var result2 = String.fromCharCode(0);
|
|
result2 += String.fromCharCode(0);
|
|
var hash = openpgp_crypto_hashData(hash_algo, data+result+trailer);
|
|
util.print_debug("DSA Signature is calculated with:|"+data+result+trailer+"|\n"+util.hexstrdump(data+result+trailer)+"\n hash:"+util.hexstrdump(hash));
|
|
result2 += hash.charAt(0);
|
|
result2 += hash.charAt(1);
|
|
result2 += openpgp_crypto_signData(hash_algo,privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm,
|
|
publickey.MPIs,
|
|
privatekey.privateKeyPacket.secMPIs,
|
|
data+result+trailer);
|
|
return {openpgp: (openpgp_packet.write_packet_header(2, (result+result2).length)+result + result2),
|
|
hash: util.get_hashAlgorithmString(hash_algo)};
|
|
}
|
|
/**
|
|
* creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
|
|
* @param {Integer} type subpacket signature type. Signature types as described in RFC4880 Section 5.2.3.2
|
|
* @param {String} data data to be included
|
|
* @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
|
|
*/
|
|
function write_sub_signature_packet(type, data) {
|
|
var result = "";
|
|
result += openpgp_packet.encode_length(data.length+1);
|
|
result += String.fromCharCode(type);
|
|
result += data;
|
|
return result;
|
|
}
|
|
|
|
// V4 signature sub packets
|
|
|
|
this._raw_read_signature_sub_packet = function(input, position, len) {
|
|
if (len < 0)
|
|
util.print_debug("openpgp.packet.signature.js\n"+"_raw_read_signature_sub_packet length < 0 @:"+position);
|
|
var mypos = position;
|
|
var subplen = 0;
|
|
// alert('starting signature subpackage read at position:'+position+' length:'+len);
|
|
if (input[mypos].charCodeAt() < 192) {
|
|
subplen = input[mypos++].charCodeAt();
|
|
} else if (input[mypos].charCodeAt() >= 192 && input[mypos].charCodeAt() < 224) {
|
|
subplen = ((input[mypos++].charCodeAt() - 192) << 8) + (input[mypos++].charCodeAt()) + 192;
|
|
} else if (input[mypos].charCodeAt() > 223 && input[mypos].charCodeAt() < 255) {
|
|
subplen = 1 << (input[mypos++].charCodeAt() & 0x1F);
|
|
} else if (input[mypos].charCodeAt() < 255) {
|
|
mypos++;
|
|
subplen = (input[mypos++].charCodeAt() << 24) | (input[mypos++].charCodeAt() << 16)
|
|
| (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
|
|
}
|
|
|
|
var type = input[mypos++].charCodeAt() & 0x7F;
|
|
// alert('signature subpacket type '+type+" with length: "+subplen);
|
|
// subpacket type
|
|
switch (type) {
|
|
case 2: // Signature Creation Time
|
|
this.creationTime = new Date(((input[mypos++].charCodeAt() << 24) | (input[mypos++].charCodeAt() << 16)
|
|
| (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt())*1000);
|
|
break;
|
|
case 3: // Signature Expiration Time
|
|
this.signatureExpirationTime = (input[mypos++].charCodeAt() << 24)
|
|
| (input[mypos++].charCodeAt() << 16) | (input[mypos++].charCodeAt() << 8)
|
|
| input[mypos++].charCodeAt();
|
|
this.signatureNeverExpires = (this.signature_expiration_time == 0);
|
|
|
|
break;
|
|
case 4: // Exportable Certification
|
|
this.exportable = input[mypos++].charCodeAt() == 1;
|
|
break;
|
|
case 5: // Trust Signature
|
|
this.trustLevel = input[mypos++].charCodeAt();
|
|
this.trustAmount = input[mypos++].charCodeAt();
|
|
break;
|
|
case 6: // Regular Expression
|
|
this.regular_expression = new String();
|
|
for (var i = 0; i < subplen - 1; i++)
|
|
this.regular_expression += (input[mypos++]);
|
|
break;
|
|
case 7: // Revocable
|
|
this.revocable = input[mypos++].charCodeAt() == 1;
|
|
break;
|
|
case 9: // Key Expiration Time
|
|
this.keyExpirationTime = (input[mypos++].charCodeAt() << 24)
|
|
| (input[mypos++].charCodeAt() << 16) | (input[mypos++].charCodeAt() << 8)
|
|
| input[mypos++].charCodeAt();
|
|
this.keyNeverExpires = (this.keyExpirationTime == 0);
|
|
break;
|
|
case 11: // Preferred Symmetric Algorithms
|
|
this.preferredSymmetricAlgorithms = new Array();
|
|
for (var i = 0; i < subplen-1; i++) {
|
|
this.preferredSymmetricAlgorithms = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 12: // Revocation Key
|
|
// (1 octet of class, 1 octet of public-key algorithm ID, 20
|
|
// octets of
|
|
// fingerprint)
|
|
this.revocationKeyClass = input[mypos++].charCodeAt();
|
|
this.revocationKeyAlgorithm = input[mypos++].charCodeAt();
|
|
this.revocationKeyFingerprint = new Array();
|
|
for ( var i = 0; i < 20; i++) {
|
|
this.revocationKeyFingerprint = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 16: // Issuer
|
|
this.issuerKeyId = input.substring(mypos,mypos+8);
|
|
mypos += 8;
|
|
break;
|
|
case 20: // Notation Data
|
|
this.notationFlags = (input[mypos++].charCodeAt() << 24) |
|
|
(input[mypos++].charCodeAt() << 16) |
|
|
(input[mypos++].charCodeAt() << 8) |
|
|
(input[mypos++].charCodeAt());
|
|
var nameLength = (input[mypos++].charCodeAt() << 8) | (input[mypos++].charCodeAt());
|
|
var valueLength = (input[mypos++].charCodeAt() << 8) | (input[mypos++].charCodeAt());
|
|
this.notationName = "";
|
|
for (var i = 0; i < nameLength; i++) {
|
|
this.notationName += input[mypos++];
|
|
}
|
|
this.notationValue = "";
|
|
for (var i = 0; i < valueLength; i++) {
|
|
this.notationValue += input[mypos++];
|
|
}
|
|
break;
|
|
case 21: // Preferred Hash Algorithms
|
|
this.preferredHashAlgorithms = new Array();
|
|
for (var i = 0; i < subplen-1; i++) {
|
|
this.preferredHashAlgorithms = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 22: // Preferred Compression Algorithms
|
|
this.preferredCompressionAlgorithms = new Array();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.preferredCompressionAlgorithms = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 23: // Key Server Preferences
|
|
this.keyServerPreferences = new Array();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.keyServerPreferences = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 24: // Preferred Key Server
|
|
this.preferredKeyServer = new String();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.preferredKeyServer += input[mypos++];
|
|
}
|
|
break;
|
|
case 25: // Primary User ID
|
|
this.isPrimaryUserID = input[mypos++] != 0;
|
|
break;
|
|
case 26: // Policy URI
|
|
this.policyURI = new String();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.policyURI += input[mypos++];
|
|
}
|
|
break;
|
|
case 27: // Key Flags
|
|
this.keyFlags = new Array();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.keyFlags = input[mypos++].charCodeAt();
|
|
}
|
|
break;
|
|
case 28: // Signer's User ID
|
|
this.signersUserId = new String();
|
|
for ( var i = 0; i < subplen-1; i++) {
|
|
this.signersUserId += input[mypos++];
|
|
}
|
|
break;
|
|
case 29: // Reason for Revocation
|
|
this.reasonForRevocationFlag = input[mypos++].charCodeAt();
|
|
this.reasonForRevocationString = new String();
|
|
for ( var i = 0; i < subplen -2; i++) {
|
|
this.reasonForRevocationString += input[mypos++];
|
|
}
|
|
break;
|
|
case 30: // Features
|
|
// TODO: to be implemented
|
|
return subplen+1;
|
|
case 31: // Signature Target
|
|
// (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash)
|
|
this.signatureTargetPublicKeyAlgorithm = input[mypos++].charCodeAt();
|
|
this.signatureTargetHashAlgorithm = input[mypos++].charCodeAt();
|
|
var signatureTargetHashAlgorithmLength = 0;
|
|
switch(this.signatureTargetHashAlgorithm) {
|
|
case 1: // - MD5 [HAC] "MD5"
|
|
case 2: // - SHA-1 [FIPS180] "SHA1"
|
|
signatureTargetHashAlgorithmLength = 20;
|
|
break;
|
|
case 3: // - RIPE-MD/160 [HAC] "RIPEMD160"
|
|
case 8: // - SHA256 [FIPS180] "SHA256"
|
|
case 9: // - SHA384 [FIPS180] "SHA384"
|
|
case 10: // - SHA512 [FIPS180] "SHA512"
|
|
case 11: // - SHA224 [FIPS180] "SHA224"
|
|
break;
|
|
// 100 to 110 - Private/Experimental algorithm
|
|
default:
|
|
util.print_error("openpgp.packet.signature.js\n"+"unknown signature target hash algorithm:"+this.signatureTargetHashAlgorithm);
|
|
return null;
|
|
}
|
|
this.signatureTargetHash = new Array();
|
|
for (var i = 0; i < signatureTargetHashAlgorithmLength; i++) {
|
|
this.signatureTargetHash[i] = input[mypos++];
|
|
}
|
|
case 32: // Embedded Signature
|
|
this.embeddedSignature = new openpgp_packet_signature();
|
|
this.embeddedSignature.read_packet(input, mypos, len -(mypos-position));
|
|
return ((mypos+ this.embeddedSignature.packetLength) - position);
|
|
break;
|
|
case 100: // Private or experimental
|
|
case 101: // Private or experimental
|
|
case 102: // Private or experimental
|
|
case 103: // Private or experimental
|
|
case 104: // Private or experimental
|
|
case 105: // Private or experimental
|
|
case 106: // Private or experimental
|
|
case 107: // Private or experimental
|
|
case 108: // Private or experimental
|
|
case 109: // Private or experimental
|
|
case 110: // Private or experimental
|
|
util.print_error("openpgp.packet.signature.js\n"+'private or experimental signature subpacket type '+type+" @:"+mypos+" subplen:"+subplen+" len:"+len);
|
|
return subplen+1;
|
|
break;
|
|
case 0: // Reserved
|
|
case 1: // Reserved
|
|
case 8: // Reserved
|
|
case 10: // Placeholder for backward compatibility
|
|
case 13: // Reserved
|
|
case 14: // Reserved
|
|
case 15: // Reserved
|
|
case 17: // Reserved
|
|
case 18: // Reserved
|
|
case 19: // Reserved
|
|
default:
|
|
util.print_error("openpgp.packet.signature.js\n"+'unknown signature subpacket type '+type+" @:"+mypos+" subplen:"+subplen+" len:"+len);
|
|
return subplen+1;
|
|
break;
|
|
}
|
|
return mypos -position;
|
|
};
|
|
/**
|
|
* verifys the signature packet. Note: not signature types are implemented
|
|
* @param {String} data data which on the signature applies
|
|
* @param {openpgp_msg_privatekey} key the public key to verify the signature
|
|
* @return {boolean} True if message is verified, else false.
|
|
*/
|
|
function verify(data, key) {
|
|
// calculating the trailer
|
|
var trailer = '';
|
|
trailer += String.fromCharCode(this.version);
|
|
trailer += String.fromCharCode(0xFF);
|
|
trailer += String.fromCharCode(this.signatureData.length >> 24);
|
|
trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF);
|
|
trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF);
|
|
trailer += String.fromCharCode(this.signatureData.length & 0xFF);
|
|
switch(this.signatureType) {
|
|
case 0: // 0x00: Signature of a binary document.
|
|
if (this.version == 4) {
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer);
|
|
}
|
|
break;
|
|
|
|
case 1: // 0x01: Signature of a canonical text document.
|
|
if (this.version == 4) {
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer);
|
|
return this.verified;
|
|
}
|
|
break;
|
|
|
|
case 2: // 0x02: Standalone signature.
|
|
// This signature is a signature of only its own subpacket contents.
|
|
// It is calculated identically to a signature over a zero-length
|
|
// binary document. Note that it doesn't make sense to have a V3
|
|
// standalone signature.
|
|
if (this.version == 3) {
|
|
this.verified = false;
|
|
break;
|
|
}
|
|
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.obj.publicKeyPacket.MPIs, this.signatureData+trailer);
|
|
break;
|
|
case 16:
|
|
// 0x10: Generic certification of a User ID and Public-Key packet.
|
|
// The issuer of this certification does not make any particular
|
|
// assertion as to how well the certifier has checked that the owner
|
|
// of the key is in fact the person described by the User ID.
|
|
case 17:
|
|
// 0x11: Persona certification of a User ID and Public-Key packet.
|
|
// The issuer of this certification has not done any verification of
|
|
// the claim that the owner of this key is the User ID specified.
|
|
case 18:
|
|
// 0x12: Casual certification of a User ID and Public-Key packet.
|
|
// The issuer of this certification has done some casual
|
|
// verification of the claim of identity.
|
|
case 19:
|
|
// 0x13: Positive certification of a User ID and Public-Key packet.
|
|
// The issuer of this certification has done substantial
|
|
// verification of the claim of identity.
|
|
//
|
|
// Most OpenPGP implementations make their "key signatures" as 0x10
|
|
// certifications. Some implementations can issue 0x11-0x13
|
|
// certifications, but few differentiate between the types.
|
|
case 48:
|
|
// 0x30: Certification revocation signature
|
|
// This signature revokes an earlier User ID certification signature
|
|
// (signature class 0x10 through 0x13) or direct-key signature
|
|
// (0x1F). It should be issued by the same key that issued the
|
|
// revoked signature or an authorized revocation key. The signature
|
|
// is computed over the same data as the certificate that it
|
|
// revokes, and should have a later creation date than that
|
|
// certificate.
|
|
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.MPIs, data+this.signatureData+trailer);
|
|
break;
|
|
|
|
case 24:
|
|
// 0x18: Subkey Binding Signature
|
|
// This signature is a statement by the top-level signing key that
|
|
// indicates that it owns the subkey. This signature is calculated
|
|
// directly on the primary key and subkey, and not on any User ID or
|
|
// other packets. A signature that binds a signing subkey MUST have
|
|
// an Embedded Signature subpacket in this binding signature that
|
|
// contains a 0x19 signature made by the signing subkey on the
|
|
// primary key and subkey.
|
|
if (this.version == 3) {
|
|
this.verified = false;
|
|
break;
|
|
}
|
|
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.MPIs, data+this.signatureData+trailer);
|
|
break;
|
|
case 25:
|
|
// 0x19: Primary Key Binding Signature
|
|
// This signature is a statement by a signing subkey, indicating
|
|
// that it is owned by the primary key and subkey. This signature
|
|
// is calculated the same way as a 0x18 signature: directly on the
|
|
// primary key and subkey, and not on any User ID or other packets.
|
|
|
|
// When a signature is made over a key, the hash data starts with the
|
|
// octet 0x99, followed by a two-octet length of the key, and then body
|
|
// of the key packet. (Note that this is an old-style packet header for
|
|
// a key packet with two-octet length.) A subkey binding signature
|
|
// (type 0x18) or primary key binding signature (type 0x19) then hashes
|
|
// the subkey using the same format as the main key (also using 0x99 as
|
|
// the first octet).
|
|
case 31:
|
|
// 0x1F: Signature directly on a key
|
|
// This signature is calculated directly on a key. It binds the
|
|
// information in the Signature subpackets to the key, and is
|
|
// appropriate to be used for subpackets that provide information
|
|
// about the key, such as the Revocation Key subpacket. It is also
|
|
// appropriate for statements that non-self certifiers want to make
|
|
// about the key itself, rather than the binding between a key and a
|
|
// name.
|
|
case 32:
|
|
// 0x20: Key revocation signature
|
|
// The signature is calculated directly on the key being revoked. A
|
|
// revoked key is not to be used. Only revocation signatures by the
|
|
// key being revoked, or by an authorized revocation key, should be
|
|
// considered valid revocation signatures.
|
|
case 40:
|
|
// 0x28: Subkey revocation signature
|
|
// The signature is calculated directly on the subkey being revoked.
|
|
// A revoked subkey is not to be used. Only revocation signatures
|
|
// by the top-level signature key that is bound to this subkey, or
|
|
// by an authorized revocation key, should be considered valid
|
|
// revocation signatures.
|
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
|
this.MPIs, key.MPIs, data+this.signatureData+trailer);
|
|
break;
|
|
|
|
// Key revocation signatures (types 0x20 and 0x28)
|
|
// hash only the key being revoked.
|
|
case 64:
|
|
// 0x40: Timestamp signature.
|
|
// This signature is only meaningful for the timestamp contained in
|
|
// it.
|
|
case 80:
|
|
// 0x50: Third-Party Confirmation signature.
|
|
// This signature is a signature over some other OpenPGP Signature
|
|
// packet(s). It is analogous to a notary seal on the signed data.
|
|
// A third-party signature SHOULD include Signature Target
|
|
// subpacket(s) to give easy identification. Note that we really do
|
|
// mean SHOULD. There are plausible uses for this (such as a blind
|
|
// party that only sees the signature, not the key or source
|
|
// document) that cannot include a target subpacket.
|
|
default:
|
|
util.print_error("openpgp.packet.signature.js\n"+"signature verification for type"+ this.signatureType+" not implemented");
|
|
break;
|
|
}
|
|
return this.verified;
|
|
}
|
|
/**
|
|
* generates debug output (pretty print)
|
|
* @return {String} String which gives some information about the signature packet
|
|
*/
|
|
|
|
function toString () {
|
|
if (this.version == 3) {
|
|
var result = '5.2. Signature Packet (Tag 2)\n'+
|
|
"Packet Length: :"+this.packetLength+'\n'+
|
|
"Packet version: :"+this.version+'\n'+
|
|
"One-octet signature type :"+this.signatureType+'\n'+
|
|
"Four-octet creation time. :"+this.creationTime+'\n'+
|
|
"Eight-octet Key ID of signer. :"+util.hexidump(this.keyId)+'\n'+
|
|
"One-octet public-key algorithm. :"+this.publicKeyAlgorithm+'\n'+
|
|
"One-octet hash algorithm. :"+this.hashAlgorithm+'\n'+
|
|
"Two-octet field holding left\n" +
|
|
" 16 bits of signed hash value. :"+this.signedHashValue+'\n';
|
|
} else {
|
|
var result = '5.2. Signature Packet (Tag 2)\n'+
|
|
"Packet Length: :"+this.packetLength+'\n'+
|
|
"Packet version: :"+this.version+'\n'+
|
|
"One-octet signature type :"+this.signatureType+'\n'+
|
|
"One-octet public-key algorithm. :"+this.publicKeyAlgorithm+'\n'+
|
|
"One-octet hash algorithm. :"+this.hashAlgorithm+'\n'+
|
|
"Two-octet field holding left\n" +
|
|
" 16 bits of signed hash value. :"+this.signedHashValue+'\n'+
|
|
"Signature Creation Time :"+this.creationTime+'\n'+
|
|
"Signature Expiration Time :"+this.signatureExpirationTime+'\n'+
|
|
"Signature Never Expires :"+this.signatureNeverExpires+'\n'+
|
|
"Exportable Certification :"+this.exportable+'\n'+
|
|
"Trust Signature level: :"+this.trustLevel+' amount'+this.trustAmount+'\n'+
|
|
"Regular Expression :"+this.regular_expression+'\n'+
|
|
"Revocable :"+this.revocable+'\n'+
|
|
"Key Expiration Time :"+this.keyExpirationTime+" "+this.keyNeverExpires+'\n'+
|
|
"Preferred Symmetric Algorithms :"+this.preferredSymmetricAlgorithms+'\n'+
|
|
"Revocation Key"+'\n'+
|
|
" ( 1 octet of class, :"+this.revocationKeyClass +'\n'+
|
|
" 1 octet of public-key ID, :" +this.revocationKeyAlgorithm+'\n'+
|
|
" 20 octets of fingerprint) :"+this.revocationKeyFingerprint+'\n'+
|
|
"Issuer :"+util.hexstrdump(this.issuerKeyId)+'\n'+
|
|
"Preferred Hash Algorithms :"+this.preferredHashAlgorithms+'\n'+
|
|
"Preferred Compression Alg. :"+this.preferredCompressionAlgorithms+'\n'+
|
|
"Key Server Preferences :"+this.keyServerPreferences+'\n'+
|
|
"Preferred Key Server :"+this.preferredKeyServer+'\n'+
|
|
"Primary User ID :"+this.isPrimaryUserID+'\n'+
|
|
"Policy URI :"+this.policyURI+'\n'+
|
|
"Key Flags :"+this.keyFlags+'\n'+
|
|
"Signer's User ID :"+this.signersUserId+'\n'+
|
|
"Notation :"+this.notationName+" = "+this.notationValue+"\n"+
|
|
"Reason for Revocation\n"+
|
|
" Flag :"+this.reasonForRevocationFlag+'\n'+
|
|
" Reason :"+this.reasonForRevocationString+'\nMPI:\n';
|
|
}
|
|
for (var i = 0; i < this.MPIs.length; i++) {
|
|
result += this.MPIs[i].toString();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* gets the issuer key id of this signature
|
|
* @return {String} issuer key id as string (8bytes)
|
|
*/
|
|
function getIssuer() {
|
|
if (this.version == 4)
|
|
return this.issuerKeyId;
|
|
if (this.verions == 4)
|
|
return this.keyId;
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Tries to get the corresponding public key out of the public keyring for the issuer created this signature
|
|
* @return {Object} {obj: [openpgp_msg_publickey], text: [String]} if found the public key will be returned. null otherwise
|
|
*/
|
|
function getIssuerKey() {
|
|
var result = null;
|
|
if (this.version == 4) {
|
|
result = openpgp.keyring.getPublicKeysForKeyId(this.issuerKeyId);
|
|
} else if (this.version == 3) {
|
|
result = openpgp.keyring.getPublicKeysForKeyId(this.keyId);
|
|
} else return null;
|
|
if (result.length == 0)
|
|
return null;
|
|
return result[0];
|
|
}
|
|
this.getIssuerKey = getIssuerKey;
|
|
this.getIssuer = getIssuer;
|
|
this.write_message_signature = write_message_signature;
|
|
this.verify = verify;
|
|
this.read_packet = read_packet;
|
|
this.toString = toString;
|
|
}
|
|
</code></pre>
|
|
</article>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<nav>
|
|
<h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="_openpgp_packet.html">_openpgp_packet</a></li><li><a href="JXG.Util.html">Util</a></li><li><a href="openpgp.html">openpgp</a></li><li><a href="openpgp_config.html">openpgp_config</a></li><li><a href="openpgp_keyring.html">openpgp_keyring</a></li><li><a href="openpgp_msg_message.html">openpgp_msg_message</a></li><li><a href="openpgp_msg_privatekey.html">openpgp_msg_privatekey</a></li><li><a href="openpgp_msg_publickey.html">openpgp_msg_publickey</a></li><li><a href="openpgp_packet_compressed.html">openpgp_packet_compressed</a></li><li><a href="openpgp_packet_encrypteddata.html">openpgp_packet_encrypteddata</a></li><li><a href="openpgp_packet_encryptedintegrityprotecteddata.html">openpgp_packet_encryptedintegrityprotecteddata</a></li><li><a href="openpgp_packet_encryptedsessionkey.html">openpgp_packet_encryptedsessionkey</a></li><li><a href="openpgp_packet_keymaterial.html">openpgp_packet_keymaterial</a></li><li><a href="openpgp_packet_literaldata.html">openpgp_packet_literaldata</a></li><li><a href="openpgp_packet_marker.html">openpgp_packet_marker</a></li><li><a href="openpgp_packet_modificationdetectioncode.html">openpgp_packet_modificationdetectioncode</a></li><li><a href="openpgp_packet_onepasssignature.html">openpgp_packet_onepasssignature</a></li><li><a href="openpgp_packet_signature.html">openpgp_packet_signature</a></li><li><a href="openpgp_packet_userattribute.html">openpgp_packet_userattribute</a></li><li><a href="openpgp_packet_userid.html">openpgp_packet_userid</a></li><li><a href="openpgp_type_keyid.html">openpgp_type_keyid</a></li><li><a href="openpgp_type_mpi.html">openpgp_type_mpi</a></li><li><a href="openpgp_type_s2k.html">openpgp_type_s2k</a></li></ul><h3>Global</h3><ul><li><a href="global.html#bin2str">bin2str</a></li><li><a href="global.html#calc_checksum">calc_checksum</a></li><li><a href="global.html#crc_table">crc_table</a></li><li><a href="global.html#decode_utf8">decode_utf8</a></li><li><a href="global.html#encode_utf8">encode_utf8</a></li><li><a href="global.html#get_hashAlgorithmString">get_hashAlgorithmString</a></li><li><a href="global.html#getCheckSum">getCheckSum</a></li><li><a href="global.html#getPGPMessageType">getPGPMessageType</a></li><li><a href="global.html#hash_headers">hash_headers</a></li><li><a href="global.html#hex2bin">hex2bin</a></li><li><a href="global.html#hexidump">hexidump</a></li><li><a href="global.html#hexstrdump">hexstrdump</a></li><li><a href="global.html#MD5">MD5</a></li><li><a href="global.html#openpgp_cfb_decrypt">openpgp_cfb_decrypt</a></li><li><a href="global.html#openpgp_cfb_encrypt">openpgp_cfb_encrypt</a></li><li><a href="global.html#openpgp_cfb_mdc">openpgp_cfb_mdc</a></li><li><a href="global.html#openpgp_crypto_asymetricDecrypt">openpgp_crypto_asymetricDecrypt</a></li><li><a href="global.html#openpgp_crypto_asymetricEncrypt">openpgp_crypto_asymetricEncrypt</a></li><li><a href="global.html#openpgp_crypto_generateKeyPair">openpgp_crypto_generateKeyPair</a></li><li><a href="global.html#openpgp_crypto_generateSessionKey">openpgp_crypto_generateSessionKey</a></li><li><a href="global.html#openpgp_crypto_getHashByteLength">openpgp_crypto_getHashByteLength</a></li><li><a href="global.html#openpgp_crypto_getPrefixRandom">openpgp_crypto_getPrefixRandom</a></li><li><a href="global.html#openpgp_crypto_getPseudoRandom">openpgp_crypto_getPseudoRandom</a></li><li><a href="global.html#openpgp_crypto_getRandomBigInteger">openpgp_crypto_getRandomBigInteger</a></li><li><a href="global.html#openpgp_crypto_getRandomBytes">openpgp_crypto_getRandomBytes</a></li><li><a href="global.html#openpgp_crypto_getSecureRandom">openpgp_crypto_getSecureRandom</a></li><li><a href="global.html#openpgp_crypto_hashData">openpgp_crypto_hashData</a></li><li><a href="global.html#openpgp_crypto_MDCSystemBytes">openpgp_crypto_MDCSystemBytes</a></li><li><a href="global.html#openpgp_crypto_signData">openpgp_crypto_signData</a></li><li><a href="global.html#openpgp_crypto_symmetricDecrypt">openpgp_crypto_symmetricDecrypt</a></li><li><a href="global.html#openpgp_crypto_symmetricEncrypt">openpgp_crypto_symmetricEncrypt</a></li><li><a href="global.html#openpgp_crypto_verifySignature">openpgp_crypto_verifySignature</a></li><li><a href="global.html#openpgp_encoding_armor">openpgp_encoding_armor</a></li><li><a href="global.html#openpgp_encoding_armor_addheader">openpgp_encoding_armor_addheader</a></li><li><a href="global.html#openpgp_encoding_base64_decode">openpgp_encoding_base64_decode</a></li><li><a href="global.html#openpgp_encoding_base64_encode">openpgp_encoding_base64_encode</a></li><li><a href="global.html#openpgp_encoding_deArmor">openpgp_encoding_deArmor</a></li><li><a href="global.html#openpgp_encoding_eme_pkcs1_decode">openpgp_encoding_eme_pkcs1_decode</a></li><li><a href="global.html#openpgp_encoding_eme_pkcs1_encode">openpgp_encoding_eme_pkcs1_encode</a></li><li><a href="global.html#openpgp_encoding_emsa_pkcs1_decode">openpgp_encoding_emsa_pkcs1_decode</a></li><li><a href="global.html#openpgp_encoding_emsa_pkcs1_encode">openpgp_encoding_emsa_pkcs1_encode</a></li><li><a href="global.html#openpgp_encoding_html_encode">openpgp_encoding_html_encode</a></li><li><a href="global.html#print_debug">print_debug</a></li><li><a href="global.html#print_debug_hexstr_dump">print_debug_hexstr_dump</a></li><li><a href="global.html#print_error">print_error</a></li><li><a href="global.html#print_info">print_info</a></li><li><a href="global.html#shiftRight">shiftRight</a></li><li><a href="global.html#str2bin">str2bin</a></li><li><a href="global.html#str2Uint8Array">str2Uint8Array</a></li><li><a href="global.html#Uint8Array2str">Uint8Array2str</a></li><li><a href="global.html#util">util</a></li><li><a href="global.html#verifyCheckSum">verifyCheckSum</a></li></ul>
|
|
</nav>
|
|
|
|
<br clear="both">
|
|
|
|
<footer>
|
|
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Tue Apr 16 2013 10:42:39 GMT+0200 (CEST)
|
|
</footer>
|
|
|
|
<script> prettyPrint(); </script>
|
|
</body>
|
|
</html>
|