Merge pull request #901 from wiktor-k/notations

Expose all signature notations
This commit is contained in:
Daniel Huigens 2019-05-16 13:31:47 +02:00 committed by GitHub
commit 5987e99c5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 16 deletions

View File

@ -183,5 +183,12 @@ export default {
* @memberof module:config
* @property {Integer} max_userid_length
*/
max_userid_length: 1024 * 5
max_userid_length: 1024 * 5,
/**
* Contains notatations that are considered "known". Known notations do not trigger
* validation error when the notation is marked as critical.
* @memberof module:config
* @property {Array} known_notations
*/
known_notations: ["preferred-email-encoding@pgp.com", "pka-address@gnupg.org"]
};

View File

@ -32,6 +32,7 @@ import type_mpi from '../type/mpi.js';
import crypto from '../crypto';
import enums from '../enums';
import util from '../util';
import config from '../config';
/**
* Implementation of the Signature Packet (Tag 2)
@ -70,7 +71,7 @@ function Signature(date=new Date()) {
this.revocationKeyAlgorithm = null;
this.revocationKeyFingerprint = null;
this.issuerKeyId = new type_keyid();
this.notation = null;
this.notations = [];
this.preferredHashAlgorithms = null;
this.preferredCompressionAlgorithms = null;
this.keyServerPreferences = null;
@ -228,18 +229,16 @@ Signature.prototype.write_hashed_sub_packets = function () {
bytes = util.concat([bytes, this.revocationKeyFingerprint]);
arr.push(write_sub_packet(sub.revocation_key, bytes));
}
if (this.notation !== null) {
Object.entries(this.notation).forEach(([name, value]) => {
bytes = [new Uint8Array([0x80, 0, 0, 0])];
// 2 octets of name length
bytes.push(util.writeNumber(name.length, 2));
// 2 octets of value length
bytes.push(util.writeNumber(value.length, 2));
bytes.push(util.str_to_Uint8Array(name + value));
bytes = util.concat(bytes);
arr.push(write_sub_packet(sub.notation_data, bytes));
});
}
this.notations.forEach(([name, value]) => {
bytes = [new Uint8Array([0x80, 0, 0, 0])];
// 2 octets of name length
bytes.push(util.writeNumber(name.length, 2));
// 2 octets of value length
bytes.push(util.writeNumber(value.length, 2));
bytes.push(util.str_to_Uint8Array(name + value));
bytes = util.concat(bytes);
arr.push(write_sub_packet(sub.notation_data, bytes));
});
if (this.preferredHashAlgorithms !== null) {
bytes = util.str_to_Uint8Array(util.Uint8Array_to_str(this.preferredHashAlgorithms));
arr.push(write_sub_packet(sub.preferred_hash_algorithms, bytes));
@ -447,8 +446,11 @@ Signature.prototype.read_sub_packet = function (bytes, trusted=true) {
const name = util.Uint8Array_to_str(bytes.subarray(mypos, mypos + m));
const value = util.Uint8Array_to_str(bytes.subarray(mypos + m, mypos + m + n));
this.notation = this.notation || {};
this.notation[name] = value;
this.notations.push([name, value]);
if (critical && (config.known_notations.indexOf(name) === -1)) {
throw new Error("Unknown critical notation: " + name);
}
} else {
util.print_debug("Unsupported notation flag "+bytes[mypos]);
}

View File

@ -801,6 +801,51 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu
expect(signature.packets[0].signersUserId).to.equal('test-wkd@metacode.biz');
});
it('Reading notations from armored key', async function() {
const pubkey =
`-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFzQOToBCADd0Pwh8edZ6gR3x49L1PaBPtiAQUr1QDUDWeNes8co5MTFl5hG
lHzptt+VD0JGucuIkvi34f5z2ZbInAV/xYDX3kSYefy6LB8XJD527I/o9bqY1P7T
PjtTZ4emcqNGkGhV2hNGV+hFcTevUS9Ty4vGg6P7X6RjfjeTrClHelJT8+9IiH+4
0h4X/Y1hwoijRWanYnZjuAUIrOXnG76iknXQRGc8th8iI0oIZfKQomfF0K5lXFhH
SU8Yvmik3vCTLHC6Ce0GVRCTIcU0/Xi2MK/Yrg9bGzSblHxomLU0NT6pee+2UjqR
BZXOAPLY66Lsh1oqxQ6ihVnOmbraU9glAGm1ABEBAAG0EFRlc3R0IDx0ZXN0QGV4
YT6JAYoEEwEIAHQCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQQZ
jHIqS6wzbp2qrkRXnQGzq+FUDgUCXNA5VBoUgAAAAAAQAAF0ZXN0QGV4YW1wbGUu
Y29tMhoUgAAAAAAQAAF0ZXN0QGV4YW1wbGUuY29tMwAKCRBXnQGzq+FUDoLiCACn
ls1iy0hT59Xt3o3tmmxe1jLzkbQEprR6MMfZamtex5/BHViu2HPAu5i13mXyBRnJ
4Zvd/HUxJukP3tdQyJIlZFe8XwloMoRAA37KOZ5QGyKH8Jxq3LcAcQOOkFtWgr+Z
JbjUKF1IuqCsK6SYB8f7SVKgpZk/kqG3HE3gk72ONnqdvwOa9cIhAuZScdgZ+PLC
6W/0+IrnQIasvKeEWeK4u6/NYT35HUsUE/9Z6WKF+qxJnp5Pi2Q5cio6bFlGDNQb
+MiuiEb3Mzb3ev2PVg7WELBRXOg8QlCxrghqfi1SH791mmiyGK+GIQgnjRwMejTh
dNsnHYag/KAewag55AQvuQENBFzQOToBCADJD+auK+Opo1q3ZLxODMyw5//XHJH4
0vQPNawyBiOdBuneWHF3jfDwGa+lOftUx1abSwsq+Qs955THgLVSiJvivHWVy8pN
tPv0XLa9rMj2wh/OmckbcgzSMeJJIz09bTj095ONPGYW2D4AcpkOc+b5bkqV6r+N
yk9nopPJNCNqYYJtecTClDT5haRKBP5XjXRVsIXva/nHZGXKQLX8iWG2D5DOJNDP
ZkAEoIPg+7J85Q3u2iSFPnLPzKHlMAoQW8d9RAEYyJ6WqiILUIDShhvXg+RIkzri
wY/WkvhB/Kpj0r1SRbNhWRpmOWCR+0a2uHaLz9X0KTP7WMqQbmIdpRgZABEBAAGJ
ATwEGAEIACYWIQQZjHIqS6wzbp2qrkRXnQGzq+FUDgUCXNA5OgIbDAUJA8JnAAAK
CRBXnQGzq+FUDgI6B/9Far0CUR6rWvUiviBY4P5oe44I9P9P7ilWmum1cIQWxMyF
0sc5tRcVLpMomURlrDz0TR5GNs+nuGAHTRBfN7VO0Y+R/LyEd1Rf80ONObXOqzMp
vF9CdW3a7W4WicZwnGgUOImTICazR2VmR+RREdZshqrOCaOnuKmN3QwGH1zzFwJA
sTbLoNMdBv8SEARaRVOWPM1HwJ701mMYF48FqhHd5uinH/ZCeBhqrBfhmXa68FWx
xuyJz6ttl5Fp4nsB3waQdgPGZJ9NUrGfopLUZ44xDuJjBONd7rbYOh71TWbHd8wG
V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
=et/d
-----END PGP PUBLIC KEY BLOCK-----`;
const key = (await openpgp.key.readArmored(pubkey)).keys[0];
const notations = key.users[0].selfCertifications[0].notations;
expect(notations.length).to.equal(2);
expect(notations[0][0]).to.equal('test@example.com');
expect(notations[0][1]).to.equal('2');
expect(notations[1][0]).to.equal('test@example.com');
expect(notations[1][1]).to.equal('3');
});
it('Writing and encryption of a secret key packet.', function() {
const key = new openpgp.packet.List();
key.push(new openpgp.packet.SecretKey());

View File

@ -467,6 +467,16 @@ describe("Signature", function() {
'=NbaL',
'-----END PGP PRIVATE KEY BLOCK-----'].join("\n");
const signature_with_critical_notation = `-----BEGIN PGP MESSAGE-----
owGbwMvMwMH4oOW7S46CznTG09xJDDE3Wl1KUotLuDousDAwcjBYiSmyXL+48d6x
U1PSGUxcj8IUszKBVMpMaWAAAgEGZpAeh9SKxNyCnFS95PzcytRiBi5OAZjyXXzM
f8WYLqv7TXP61Sa4rqT12CI3xaN73YS2pt089f96odCKaEPnWJ3iSGmzJaW/ug10
2Zo8Wj2k4s7t8wt4H3HtTu+y5UZfV3VOO+l//sdE/o+Lsub8FZH7/eOq7OnbNp4n
vwjE8mqJXetNMfj8r2SCyvkEnlVRYR+/mnge+ib56FdJ8uKtqSxyvgA=
=fRXs
-----END PGP MESSAGE-----`;
it('Testing signature checking on CAST5-enciphered message', async function() {
const priv_key = (await openpgp.key.readArmored(priv_key_arm1)).keys[0];
const pub_key = (await openpgp.key.readArmored(pub_key_arm1)).keys[0];
@ -606,6 +616,39 @@ describe("Signature", function() {
});
});
it('Verify fails with signed message with critical notations', async function() {
let testFailed = true;
try {
openpgp.config.tolerant = false;
const sMsg = await openpgp.message.readArmored(signature_with_critical_notation);
const pub_key = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
const verified = await sMsg.verify([pub_key]);
await verified[0].verified;
testFailed = false;
} catch (e) {
expect(e.message).to.equal('Unknown critical notation: test@example.com');
} finally {
openpgp.config.tolerant = true;
}
// fail the test if execution does not throw an exception
expect(testFailed).to.be.true;
});
it('Verify succeeds with known signed message with critical notations', async function() {
openpgp.config.tolerant = false;
openpgp.config.known_notations.push('test@example.com');
try {
const sMsg = await openpgp.message.readArmored(signature_with_critical_notation);
const pub_key = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
const verified = await sMsg.verify([pub_key]);
openpgp.stream.pipe(sMsg.getLiteralData(), new WritableStream());
expect(await verified[0].verified).to.be.true;
} finally {
openpgp.config.known_notations.pop();
openpgp.config.tolerant = true;
}
});
it('Verify cleartext signed message with two signatures with openpgp.verify', async function() {
const msg_armor =
['-----BEGIN PGP SIGNED MESSAGE-----',