fork-openpgpjs/test/security/subkey_trust.js
larabr 7f37a8aaca
Add config parameter to top-level functions (#1241)
Refactor functions to take the configuration as a parameter.

This allows setting a config option for a single function call, whereas
setting `openpgp.config` could lead to concurrency-related issues when
multiple async function calls are made at the same time.

`openpgp.config` is used as default for unset config values in top-level
functions.
`openpgp.config` is used as default config object in low-level functions
(i.e., when calling a low-level function, it may be required to pass
`{ ...openpgp.config, modifiedConfig: modifiedValue }`).

Also,

- remove `config.rsaBlinding`: blinding is now always applied to RSA decryption
- remove `config.debug`: debugging mode can be enabled by setting
  `process.env.NODE_ENV = 'development'`
- remove `config.useNative`: native crypto is always used when available
2021-02-26 20:04:54 +01:00

79 lines
2.7 KiB
JavaScript

const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
const { readKey, Key, readCleartextMessage, CleartextMessage, enums, PacketList, SignaturePacket } = openpgp;
const chai = require('chai');
chai.use(require('chai-as-promised'));
const expect = chai.expect;
async function generateTestData() {
const victimPrivKey = (await openpgp.generateKey({
userIds: [{ name: 'Victim', email: 'victim@example.com' }],
type: 'rsa',
rsaBits: 2048,
subkeys: [{
sign: true
}]
})).key;
victimPrivKey.revocationSignatures = [];
const attackerPrivKey = (await openpgp.generateKey({
userIds: [{ name: 'Attacker', email: 'attacker@example.com' }],
type: 'rsa',
rsaBits: 2048,
subkeys: [],
sign: false
})).key;
attackerPrivKey.revocationSignatures = [];
const signed = await openpgp.sign({
message: await CleartextMessage.fromText('I am batman'),
privateKeys: victimPrivKey,
streaming: false,
armor: true
});
return {
victimPubKey: victimPrivKey.toPublic(),
attackerPrivKey,
signed
};
}
async function testSubkeyTrust() {
// 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 pktPrivAttacker = attackerPrivKey.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.concat([
pktPrivAttacker[0], // attacker private key
pktPrivAttacker[1], // attacker user
pktPrivAttacker[2], // attacker self signature
pktPubVictim[3], // victim subkey
fakeBindingSignature // faked key binding
]);
let fakeKey = new Key(newList);
fakeKey = await readKey({ armoredKey: await fakeKey.toPublic().armor() });
const verifyAttackerIsBatman = await openpgp.verify({
message: await readCleartextMessage({ cleartextMessage: signed }),
publicKeys: fakeKey,
streaming: false
});
expect(verifyAttackerIsBatman.signatures[0].keyid.equals(victimPubKey.subKeys[0].getKeyId())).to.be.true;
expect(verifyAttackerIsBatman.signatures[0].valid).to.be.null;
}
module.exports = () => it('Does not trust subkeys without Primary Key Binding Signature', testSubkeyTrust);