Indicate an error when parsing a key with an authorized revocation key
Since we will ignore revocation signatures from authorized revocation keys, it is dangerous to use these keys.
This commit is contained in:
parent
5cf61daa19
commit
a1c47ecdea
16
src/key.js
16
src/key.js
|
@ -1220,9 +1220,16 @@ SubKey.prototype.revoke = async function(primaryKey, {
|
||||||
export async function read(data) {
|
export async function read(data) {
|
||||||
const result = {};
|
const result = {};
|
||||||
result.keys = [];
|
result.keys = [];
|
||||||
|
const err = [];
|
||||||
try {
|
try {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
await packetlist.read(data);
|
await packetlist.read(data);
|
||||||
|
if (packetlist.filterByTag(enums.packet.signature).some(
|
||||||
|
signature => signature.revocationKeyClass !== null
|
||||||
|
)) {
|
||||||
|
// Indicate an error, but still parse the key.
|
||||||
|
err.push(new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'));
|
||||||
|
}
|
||||||
const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey);
|
const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey);
|
||||||
if (keyIndex.length === 0) {
|
if (keyIndex.length === 0) {
|
||||||
throw new Error('No key packet found');
|
throw new Error('No key packet found');
|
||||||
|
@ -1233,13 +1240,14 @@ export async function read(data) {
|
||||||
const newKey = new Key(oneKeyList);
|
const newKey = new Key(oneKeyList);
|
||||||
result.keys.push(newKey);
|
result.keys.push(newKey);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result.err = result.err || [];
|
err.push(e);
|
||||||
result.err.push(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result.err = result.err || [];
|
err.push(e);
|
||||||
result.err.push(e);
|
}
|
||||||
|
if (err.length) {
|
||||||
|
result.err = err;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import util from '../util';
|
||||||
* are stored as numerical indices.
|
* are stored as numerical indices.
|
||||||
* @memberof module:packet
|
* @memberof module:packet
|
||||||
* @constructor
|
* @constructor
|
||||||
|
* @extends Array
|
||||||
*/
|
*/
|
||||||
function List() {
|
function List() {
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +32,8 @@ function List() {
|
||||||
this.length = 0;
|
this.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List.prototype = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a stream of binary data and interprents it as a list of packets.
|
* Reads a stream of binary data and interprents it as a list of packets.
|
||||||
* @param {Uint8Array | ReadableStream<Uint8Array>} A Uint8Array of bytes.
|
* @param {Uint8Array | ReadableStream<Uint8Array>} A Uint8Array of bytes.
|
||||||
|
@ -145,37 +148,6 @@ List.prototype.push = function (packet) {
|
||||||
this.length++;
|
this.length++;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a packet from the list and return it.
|
|
||||||
* @returns {Object} The packet that was removed
|
|
||||||
*/
|
|
||||||
List.prototype.pop = function() {
|
|
||||||
if (this.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const packet = this[this.length - 1];
|
|
||||||
delete this[this.length - 1];
|
|
||||||
this.length--;
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new PacketList with all packets that pass the test implemented by the provided function.
|
|
||||||
*/
|
|
||||||
List.prototype.filter = function (callback) {
|
|
||||||
const filtered = new List();
|
|
||||||
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
if (callback(this[i], i, this)) {
|
|
||||||
filtered.push(this[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PacketList with all packets from the given types
|
* Creates a new PacketList with all packets from the given types
|
||||||
*/
|
*/
|
||||||
|
@ -193,58 +165,6 @@ List.prototype.filterByTag = function (...args) {
|
||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the provided callback once for each element
|
|
||||||
*/
|
|
||||||
List.prototype.forEach = function (callback) {
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
callback(this[i], i, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array containing return values of callback
|
|
||||||
* on each element
|
|
||||||
*/
|
|
||||||
List.prototype.map = function (callback) {
|
|
||||||
const packetArray = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
packetArray.push(callback(this[i], i, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return packetArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the callback function once for each element
|
|
||||||
* until it finds one where callback returns a truthy value
|
|
||||||
* @param {Function} callback
|
|
||||||
* @returns {Promise<Boolean>}
|
|
||||||
* @async
|
|
||||||
*/
|
|
||||||
List.prototype.some = async function (callback) {
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
if (await callback(this[i], i, this)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the callback function once for each element,
|
|
||||||
* returns true if all callbacks returns a truthy value
|
|
||||||
*/
|
|
||||||
List.prototype.every = function (callback) {
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
if (!callback(this[i], i, this)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Traverses packet tree and returns first matching packet
|
* Traverses packet tree and returns first matching packet
|
||||||
* @param {module:enums.packet} type The packet type
|
* @param {module:enums.packet} type The packet type
|
||||||
|
@ -285,20 +205,6 @@ List.prototype.indexOfTag = function (...args) {
|
||||||
return tagIndex;
|
return tagIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns slice of packetlist
|
|
||||||
*/
|
|
||||||
List.prototype.slice = function (begin, end) {
|
|
||||||
if (!end) {
|
|
||||||
end = this.length;
|
|
||||||
}
|
|
||||||
const part = new List();
|
|
||||||
for (let i = begin; i < end; i++) {
|
|
||||||
part.push(this[i]);
|
|
||||||
}
|
|
||||||
return part;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concatenates packetlist or array of packets
|
* Concatenates packetlist or array of packets
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1223,6 +1223,41 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
|
||||||
=C0fJ
|
=C0fJ
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
const key_with_authorized_revocation_key = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
Version: OpenPGP.js VERSION
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
xsBNBFujnwwBCADK1xX03tSCmktPDS9Ncij3O5wG+F5/5Zm7QJDc39Wt1t/K
|
||||||
|
szCSobWtm/UObQVZjsTGwg0ZUPgepgWGGDBL0dlc1NObwUiOhGYnJnd4V25P
|
||||||
|
iU5Mg3+DhRq+LzNK+oGlpVPDpwQ48S8HOphbswKUpuaDcEQ2f+NKIc0eXe5m
|
||||||
|
ut5x9uoVj8jneUNsHYq6FIlxh4knzpJWFj5+LNi7plMCwKip6srVNf8He/q0
|
||||||
|
0xA/4vjSIOfGIE7TCBH33CbHEr98p81Cf4g0E+kswEz5iWE2SDCyYgQkMrkz
|
||||||
|
H9mtVqk3nFT8NR0USxKqH9bGhaTx1AWq/HDgsphayPEWQ0usjQDrbQUnABEB
|
||||||
|
AAHNDnRlc3QgPGFAYi5jb20+wsCNBBABCABBBQJbo58MBgsJBwgDAhcMgAH0
|
||||||
|
cOUNyxrV8eZOCGRKY2E6TW5AlAkQWICi/ReDcrkEFQgKAgMWAgECGQECGwMC
|
||||||
|
HgEAADgHB/0WIHh6maX2LZ0u5ujk1tZxWMrCycccopdQNKN0RGD98X4fyY6J
|
||||||
|
wfmKb107gcidJBFct0sVWFW8GU42w9pVMU5qWD6kyFkgcmov319UL+7aZ19b
|
||||||
|
HOWVKUTb6rFG8/qAbq3BF7YB/cZIBWMFKAS3BRJ4Kz23GheAB2A9oVLmuq5o
|
||||||
|
gW5c2R1YC0T0XyXEFiw9uZ+AS6kEZymFPRQfPUIbJs1ct/lAN+mC9Qp0Y6CL
|
||||||
|
60Hd6jlKUb6TgljaQ6CtLfT9v72GeKznapKr9IEtsgYv69j0c/MRM2nmu50c
|
||||||
|
g+fICiiHrTbNS6jkUz0pZLe7hdhWHeEiqcA9+GC1DxOQCRCS/YNfzsBNBFuj
|
||||||
|
nwwBCADK1xX03tSCmktPDS9Ncij3O5wG+F5/5Zm7QJDc39Wt1t/KszCSobWt
|
||||||
|
m/UObQVZjsTGwg0ZUPgepgWGGDBL0dlc1NObwUiOhGYnJnd4V25PiU5Mg3+D
|
||||||
|
hRq+LzNK+oGlpVPDpwQ48S8HOphbswKUpuaDcEQ2f+NKIc0eXe5mut5x9uoV
|
||||||
|
j8jneUNsHYq6FIlxh4knzpJWFj5+LNi7plMCwKip6srVNf8He/q00xA/4vjS
|
||||||
|
IOfGIE7TCBH33CbHEr98p81Cf4g0E+kswEz5iWE2SDCyYgQkMrkzH9mtVqk3
|
||||||
|
nFT8NR0USxKqH9bGhaTx1AWq/HDgsphayPEWQ0usjQDrbQUnABEBAAHCwF8E
|
||||||
|
GAEIABMFAlujnwwJEFiAov0Xg3K5AhsMAACI/QgArvTcutod+7n1D8wCwM50
|
||||||
|
jo3x4KPuQw+NwbOnMbFwv0R8i8NqtSFf2bYkkZ7RLViTmphvSon4h2WgfczL
|
||||||
|
SBulZ1QZF7zCKXmXDg8/HZgRUflC1XMixpB8Hqouin5AVgMbsbHg30V2uPco
|
||||||
|
V3DeFQ8HWxQC9symaMW/20MkqNXgCjM0us7kVwTEJQqZ6KYrFVjKyprSQRyP
|
||||||
|
rfckEBuZnj91OS+kAHlZ+ScZIuV4QVF0e2U6oEuB+qFXppR030PJoO6WDOzm
|
||||||
|
67hkzfrc3VpKw/I+vVJnZb4GOhNTSpa+p8i4gTyWmrOZ0G85QoldHWlWaRBg
|
||||||
|
lbjwPj3QUTbLFvHisYzXEQ==
|
||||||
|
=aT8U
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
`;
|
||||||
|
|
||||||
function versionSpecificTests() {
|
function versionSpecificTests() {
|
||||||
it('Preferences of generated key', function() {
|
it('Preferences of generated key', function() {
|
||||||
const testPref = function(key) {
|
const testPref = function(key) {
|
||||||
|
@ -1688,6 +1723,15 @@ describe('Key', function() {
|
||||||
expect(pubKeys.keys[1].getKeyId().toHex()).to.equal('dbf223e870534df4');
|
expect(pubKeys.keys[1].getKeyId().toHex()).to.equal('dbf223e870534df4');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Parsing armored key with an authorized revocation key', async function() {
|
||||||
|
const pubKeys = await openpgp.key.readArmored(key_with_authorized_revocation_key);
|
||||||
|
expect(pubKeys).to.exist;
|
||||||
|
expect(pubKeys.err).to.exist.and.have.length(1);
|
||||||
|
expect(pubKeys.err[0].message).to.equal('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.');
|
||||||
|
expect(pubKeys.keys).to.have.length(1);
|
||||||
|
expect(pubKeys.keys[0].getKeyId().toHex()).to.equal('5880a2fd178372b9');
|
||||||
|
});
|
||||||
|
|
||||||
it('Parsing V5 public key packet', async function() {
|
it('Parsing V5 public key packet', async function() {
|
||||||
// Manually modified from https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b2092/back.mkd#sample-eddsa-key
|
// Manually modified from https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b2092/back.mkd#sample-eddsa-key
|
||||||
let packetBytes = openpgp.util.hex_to_Uint8Array(`
|
let packetBytes = openpgp.util.hex_to_Uint8Array(`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user