71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
const { use: chaiUse, expect } = require('chai');
|
|
chaiUse(require('chai-as-promised'));
|
|
|
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
|
|
|
|
const { readKey, PublicKey, readCleartextMessage, createCleartextMessage, enums, PacketList, SignaturePacket } = openpgp;
|
|
|
|
async function generateTestData() {
|
|
const { privateKey: victimPrivKey } = await openpgp.generateKey({
|
|
userIDs: [{ name: 'Victim', email: 'victim@example.com' }],
|
|
type: 'rsa',
|
|
rsaBits: 2048,
|
|
subkeys: [{ sign: true }],
|
|
format: 'object'
|
|
});
|
|
|
|
const { privateKey: attackerPrivKey } = await openpgp.generateKey({
|
|
userIDs: [{ name: 'Attacker', email: 'attacker@example.com' }],
|
|
type: 'rsa',
|
|
rsaBits: 2048,
|
|
subkeys: [],
|
|
format: 'object'
|
|
});
|
|
|
|
const signed = await openpgp.sign({
|
|
message: await createCleartextMessage({ text: 'I am batman' }),
|
|
signingKeys: victimPrivKey
|
|
});
|
|
return {
|
|
victimPubKey: victimPrivKey.toPublic(),
|
|
attackerPrivKey,
|
|
signed
|
|
};
|
|
}
|
|
|
|
module.exports = () => it('Does not trust subkeys without Primary Key Binding Signature', async function() {
|
|
// attacker only has his own private key,
|
|
// the victim's public key and a signed message
|
|
const { victimPubKey, attackerPrivKey, signed } = await generateTestData();
|
|
|
|
const pktPubVictim = victimPubKey.toPacketList();
|
|
const pktPubAttacker = attackerPrivKey.toPublic().toPacketList();
|
|
const dataToSign = {
|
|
key: attackerPrivKey.toPublic().keyPacket,
|
|
bind: pktPubVictim[3] // victim subkey
|
|
};
|
|
const fakeBindingSignature = new SignaturePacket();
|
|
fakeBindingSignature.signatureType = enums.signature.subkeyBinding;
|
|
fakeBindingSignature.publicKeyAlgorithm = attackerPrivKey.keyPacket.algorithm;
|
|
fakeBindingSignature.hashAlgorithm = enums.hash.sha256;
|
|
fakeBindingSignature.keyFlags = [enums.keyFlags.signData];
|
|
await fakeBindingSignature.sign(attackerPrivKey.keyPacket, dataToSign);
|
|
const newList = new PacketList();
|
|
newList.push(
|
|
pktPubAttacker[0], // attacker private key
|
|
pktPubAttacker[1], // attacker user
|
|
pktPubAttacker[2], // attacker self signature
|
|
pktPubVictim[3], // victim subkey
|
|
fakeBindingSignature // faked key binding
|
|
);
|
|
let fakeKey = new PublicKey(newList);
|
|
fakeKey = await readKey({ armoredKey: await fakeKey.toPublic().armor() });
|
|
const verifyAttackerIsBatman = await openpgp.verify({
|
|
message: await readCleartextMessage({ cleartextMessage: signed }),
|
|
verificationKeys: fakeKey
|
|
});
|
|
// expect the signature to have the expected keyID, but be invalid due to fake key binding signature in the subkey
|
|
expect(verifyAttackerIsBatman.signatures[0].keyID.equals(victimPubKey.subkeys[0].getKeyID())).to.be.true;
|
|
await expect(verifyAttackerIsBatman.signatures[0].verified).to.be.rejectedWith(/Could not find valid signing key packet/);
|
|
});
|