Verify V3 certification signatures

This commit is contained in:
Thomas Oberndörfer 2013-12-12 14:22:23 +01:00
parent ff8d93f956
commit d7d74ec5e3
4 changed files with 167 additions and 59 deletions

File diff suppressed because one or more lines are too long

View File

@ -31,6 +31,7 @@ var util = require('../util'),
* major versions. Consequently, this section is complex. * major versions. Consequently, this section is complex.
*/ */
module.exports = function packet_public_key() { module.exports = function packet_public_key() {
this.version = 4;
/** Key creation date. /** Key creation date.
* @type {Date} */ * @type {Date} */
this.created = new Date(); this.created = new Date();
@ -40,6 +41,7 @@ module.exports = function packet_public_key() {
/** Public key algorithm /** Public key algorithm
* @type {openpgp.publickey} */ * @type {openpgp.publickey} */
this.algorithm = 'rsa_sign'; this.algorithm = 'rsa_sign';
this.expirationTimeV3 = 0;
/** /**
@ -53,9 +55,9 @@ module.exports = function packet_public_key() {
*/ */
this.readPublicKey = this.read = function(bytes) { this.readPublicKey = this.read = function(bytes) {
// A one-octet version number (3 or 4). // A one-octet version number (3 or 4).
var version = bytes.charCodeAt(0); this.version = bytes.charCodeAt(0);
if (version == 4) { if (this.version == 4) {
// - A four-octet number denoting the time that the key was created. // - A four-octet number denoting the time that the key was created.
this.created = util.readDate(bytes.substr(1, 4)); this.created = util.readDate(bytes.substr(1, 4));
@ -78,6 +80,34 @@ module.exports = function packet_public_key() {
util.print_error("openpgp.packet.keymaterial.js\n" + 'error reading MPI @:' + p); util.print_error("openpgp.packet.keymaterial.js\n" + 'error reading MPI @:' + p);
} }
return p + 6;
} else if (this.version == 3) {
// - A four-octet number denoting the time that the key was created.
this.created = util.readDate(bytes.substr(1, 4));
// - A two-octet number denoting the time in days that this key is
// valid. If this number is zero, then it does not expire.
this.expirationTimeV3 = util.readNumber(bytes.substr(5, 2));
// - A one-octet number denoting the public-key algorithm of this key.
this.algorithm = enums.read(enums.publicKey, bytes.charCodeAt(7));
var mpicount = crypto.getPublicMpiCount(this.algorithm);
this.mpi = [];
var bmpi = bytes.substr(8);
var p = 0;
for (var i = 0; i < mpicount && p < bmpi.length; i++) {
this.mpi[i] = new type_mpi();
p += this.mpi[i].read(bmpi.substr(p))
if (p > bmpi.length)
util.print_error("openpgp.packet.keymaterial.js\n" + 'error reading MPI @:' + p);
}
return p + 6; return p + 6;
} else { } else {
throw new Error('Version ' + version + ' of the key packet is unsupported.'); throw new Error('Version ' + version + ' of the key packet is unsupported.');
@ -96,8 +126,11 @@ module.exports = function packet_public_key() {
*/ */
this.writePublicKey = this.write = function() { this.writePublicKey = this.write = function() {
// Version // Version
var result = String.fromCharCode(4); var result = String.fromCharCode(this.version);
result += util.writeDate(this.created); result += util.writeDate(this.created);
if (this.version == 3) {
result += util.writeNumber(this.expirationTimeV3, 2);
}
result += String.fromCharCode(enums.write(enums.publicKey, this.algorithm)); result += String.fromCharCode(enums.write(enums.publicKey, this.algorithm));
var mpicount = crypto.getPublicMpiCount(this.algorithm); var mpicount = crypto.getPublicMpiCount(this.algorithm);

View File

@ -33,7 +33,7 @@ var util = require('../util'),
*/ */
module.exports = function packet_signature() { module.exports = function packet_signature() {
this.version = null; this.version = 4;
this.signatureType = null; this.signatureType = null;
this.hashAlgorithm = null; this.hashAlgorithm = null;
this.publicKeyAlgorithm = null; this.publicKeyAlgorithm = null;
@ -517,39 +517,42 @@ module.exports = function packet_signature() {
case t.cert_casual: case t.cert_casual:
case t.cert_positive: case t.cert_positive:
case t.cert_revocation: case t.cert_revocation:
{ var packet, tag;
var packet, tag;
if (data.userid !== undefined) { if (data.userid !== undefined) {
tag = 0xB4; tag = 0xB4;
packet = data.userid; packet = data.userid;
} else if (data.userattribute !== undefined) { } else if (data.userattribute !== undefined) {
tag = 0xD1; tag = 0xD1;
packet = data.userattribute; packet = data.userattribute;
} else throw new Error('Either a userid or userattribute packet needs to be ' + } else throw new Error('Either a userid or userattribute packet needs to be ' +
'supplied for certification.'); 'supplied for certification.');
var bytes = packet.write(); var bytes = packet.write();
if (this.version == 4) {
return this.toSign(t.key, data) + return this.toSign(t.key, data) +
String.fromCharCode(tag) + String.fromCharCode(tag) +
util.writeNumber(bytes.length, 4) + util.writeNumber(bytes.length, 4) +
bytes; bytes;
} else if (this.version == 3) {
return this.toSign(t.key, data) +
bytes;
} }
break;
case t.subkey_binding: case t.subkey_binding:
case t.key_binding: case t.key_binding:
{ return this.toSign(t.key, data) + this.toSign(t.key, {
return this.toSign(t.key, data) + this.toSign(t.key, { key: data.bind
key: data.bind });
});
} case t.key:
case t.key: if (data.key == undefined)
{ throw new Error('Key packet is required for this sigtature.');
if (data.key == undefined)
throw new Error('Key packet is required for this sigtature.'); return data.key.writeOld();
return data.key.writeOld();
}
case t.key_revocation: case t.key_revocation:
case t.subkey_revocation: case t.subkey_revocation:
return this.toSign(t.key, data); return this.toSign(t.key, data);

View File

@ -221,6 +221,35 @@ var pub_revoked =
'=ok+o', '=ok+o',
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); '-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
var pub_v3 =
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: SKS 1.1.3',
'',
'mQENAy9J/w4AAAEIALBDDD4vWqG/Jg59ghhMYAa+E7ECCTv2At8hxsM5cMP8P9sMLjs+GMfD',
'IdQSOqlQXbunYADvM1l/h2fOuUMoYFIIGaUsO5Daxvd9uWceM4DVzhXMeJZb9wc5jEJEF21+',
'qidKj5OGsMyTrg++mn4Gh/aFXvvy3N3KWaQpPfNi3NRZUpNLz0IlfbXVBQGD6reLoxPptJun',
'NqpClyRiesgq8HCscmB2oQo+b9KzSSgzU9qQJA4SljMYVmJ2sDE/sjREI8iKL8lIgUMhJG9q',
'NggWjuxFTpVcGKkuQFJIvdL+UhTVvEBuqw6n4cmFAzfZ/AInJM032qLtsaIf5begFKI3up0A',
'BRGJARUDBSAxm7HC5begFKI3up0BAbdDB/0TOcI0ec+OPxC5RTZAltgIgyUc0yOjHoTD/yBh',
'WjZdQ9YVrLGMWTW4fjhm4rFnppVZKS/N71bwI76SnN9zO4pPfx86aQPR7StmSLJxB+cfh2GL',
'gudJoG9ifhJWdNYMUD/yhA0TpJkdHMD5yTDE5Ce/PqKLviiX9C5MPW0AT1MDvafQlzeUXfb5',
'1a71vQNPw7W1NBAVZRwztm7TNUaxWMFuOmUtOJpq4F/qDQTIHW2zGPJvl47rpf6JSiyIyU70',
'l0deiQcZOXPC80tgInhNoBrz3zbEXhXRJo1fHkr2YSLclpJaoUOHsPxoyrNB28ASL5ZknPwI',
'Zx3+cFxaGpRprfSdtCFKb2huIEEuIFBlcnJ5IDxwZXJyeUBwaG9lbml4Lm5ldD6JARUDBRAv',
'Sf8k5begFKI3up0BAcbGB/0eLod2qrQxoE2/RUWQtqklOPUj/p/ZTmvZm8BgsdIflb0AMeey',
'9o8AbxyAgA3pcrcCjcye79M1Ma2trEvRksvs8hViuq3BXXjDbjPZi3wTtKSvbAC022OV52Sb',
'8/sgiTGp7xC8QMqS8w4ZeKoxJGh1TVMYrevUA8a2Rr5aDqrR3EA4rifSHwkVjJWOPF69xiKt',
'IVA0LcYJvGsPOQCf2ag+nOcnDrF4dvcmg6XZ/RyLepve+1qkhXsA/oq+yHoaqWfe+bwgssk/',
'qw1aEUk7Di8x7vY+cfjvWaazcYGw8kkIwSSqqIq0pkKFz2xDDfSaDJl6OW/2GUK0wDpJmYZo',
'PN40iJUDBRAvSgDsU5OkROGu2G8BAeUqBACbC45t4+wYxWCxxp81pkFRb8RWBvEvbXI+Spwd',
'4NcKs8jc5OVC8V02yiq4KbKFDRxdw2OWpUCSRAJe1gjsfFrZ+2RivpKk06kbAYthES03MjXg',
'cfcV3z2d7IWanJzdcOlzsHzPe1+RoUAaqBjvcqPRCGRlk0ogkYHyWYxElc6574iVAwUQL9iL',
'CXr7ES8bepftAQGPywP/d9GSpEmS7LLIqazl4rgN1nkXN5KqduiH8Whu3xcBrdOAn7IYnGTp',
'O+Ag4qwKKH+y/ke9CeZL6AnrU9c0pux150dHsDeHtpTPyInkjgKI7BofprydvpiFNd0nlAi4',
'J4SAEYr3q92Qn/IiKpnLgo6Ls/GFb7q6y1O/2LL8PC2zrYU=',
'=eoGb',
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
var tests = [function() { var tests = [function() {
var priv_key = openpgp.key.readArmored(priv_key_arm1).packets; var priv_key = openpgp.key.readArmored(priv_key_arm1).packets;
@ -483,6 +512,13 @@ var pub_revoked =
var verified = !pubKey.packets[4].keyNeverExpires && pubKey.packets[4].keyExpirationTime == 5*365*24*60*60; var verified = !pubKey.packets[4].keyNeverExpires && pubKey.packets[4].keyExpirationTime == 5*365*24*60*60;
return new unit.result("Verify key expiration date", verified); return new unit.result("Verify key expiration date", verified);
}, function() {
var pubKey = openpgp.key.readArmored(pub_v3);
var verified = pubKey.packets[3].verify(pubKey.packets[0], {key: pubKey.packets[0], userid: pubKey.packets[2]});
return new unit.result("Verify V3 certification signature", verified);
}]; }];
var results = []; var results = [];