Drop support for verification of detached cleartext signatures (#1265)
(Also, use turnstyle to avoid CI browserstack tasks running in parallel.)
This commit is contained in:
parent
eba791e11e
commit
3e808c1578
12
.github/workflows/browserstack.yml
vendored
12
.github/workflows/browserstack.yml
vendored
|
@ -14,6 +14,12 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- uses: softprops/turnstyle@v1
|
||||||
|
with:
|
||||||
|
poll-interval-seconds: 30
|
||||||
|
abort-after-seconds: 900
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build-test
|
- run: npm run build-test
|
||||||
|
@ -28,6 +34,12 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- uses: softprops/turnstyle@v1
|
||||||
|
with:
|
||||||
|
poll-interval-seconds: 30
|
||||||
|
abort-after-seconds: 900
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build-test --lightweight
|
- run: npm run build-test --lightweight
|
||||||
|
|
|
@ -66,25 +66,10 @@ export class CleartextMessage {
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async sign(privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = [], config = defaultConfig) {
|
async sign(privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = [], config = defaultConfig) {
|
||||||
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, signingKeyIds, date, userIds, config));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sign the cleartext message
|
|
||||||
* @param {Array<Key>} privateKeys - private keys with decrypted secret key data for signing
|
|
||||||
* @param {Signature} [signature] - Any existing detached signature
|
|
||||||
* @param {Array<module:type/keyid~Keyid>} [signingKeyIds] - Array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
|
||||||
* @param {Date} [date] - The creation time of the signature that should be created
|
|
||||||
* @param {Array} [userIds] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
||||||
* @returns {Signature} New detached signature of message content.
|
|
||||||
* @async
|
|
||||||
*/
|
|
||||||
async signDetached(privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = [], config = defaultConfig) {
|
|
||||||
const literalDataPacket = new LiteralDataPacket();
|
const literalDataPacket = new LiteralDataPacket();
|
||||||
literalDataPacket.setText(this.text);
|
literalDataPacket.setText(this.text);
|
||||||
|
const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIds, true, undefined, config));
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIds, true, undefined, config));
|
return new CleartextMessage(this.text, newSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,19 +81,7 @@ export class CleartextMessage {
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
verify(keys, date = new Date(), config = defaultConfig) {
|
verify(keys, date = new Date(), config = defaultConfig) {
|
||||||
return this.verifyDetached(this.signature, keys, date, config);
|
const signatureList = this.signature.packets;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify signatures of cleartext signed message
|
|
||||||
* @param {Array<Key>} keys - Array of keys to verify signatures
|
|
||||||
* @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time
|
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
||||||
* @returns {Array<{keyid: module:type/keyid~Keyid, valid: Boolean}>} List of signer's keyid and validity of signature.
|
|
||||||
* @async
|
|
||||||
*/
|
|
||||||
verifyDetached(signature, keys, date = new Date(), config = defaultConfig) {
|
|
||||||
const signatureList = signature.packets;
|
|
||||||
const literalDataPacket = new LiteralDataPacket();
|
const literalDataPacket = new LiteralDataPacket();
|
||||||
// we assume that cleartext signature is generated based on UTF8 cleartext
|
// we assume that cleartext signature is generated based on UTF8 cleartext
|
||||||
literalDataPacket.setText(this.text);
|
literalDataPacket.setText(this.text);
|
||||||
|
|
|
@ -353,7 +353,7 @@ export function sign({ message, privateKeys, armor = true, streaming = message &
|
||||||
config = { ...defaultConfig, ...config };
|
config = { ...defaultConfig, ...config };
|
||||||
checkCleartextOrMessage(message);
|
checkCleartextOrMessage(message);
|
||||||
if (message instanceof CleartextMessage && !armor) throw new Error("Can't sign non-armored cleartext message");
|
if (message instanceof CleartextMessage && !armor) throw new Error("Can't sign non-armored cleartext message");
|
||||||
if (message instanceof CleartextMessage && detached) throw new Error("Can't sign detached cleartext message");
|
if (message instanceof CleartextMessage && detached) throw new Error("Can't detach-sign a cleartext message");
|
||||||
privateKeys = toArray(privateKeys); fromUserIds = toArray(fromUserIds);
|
privateKeys = toArray(privateKeys); fromUserIds = toArray(fromUserIds);
|
||||||
|
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
|
@ -408,12 +408,13 @@ export function verify({ message, publicKeys, format = 'utf8', streaming = messa
|
||||||
config = { ...defaultConfig, ...config };
|
config = { ...defaultConfig, ...config };
|
||||||
checkCleartextOrMessage(message);
|
checkCleartextOrMessage(message);
|
||||||
if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary");
|
if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary");
|
||||||
|
if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature");
|
||||||
publicKeys = toArray(publicKeys);
|
publicKeys = toArray(publicKeys);
|
||||||
|
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
const result = {};
|
const result = {};
|
||||||
if (message instanceof CleartextMessage) {
|
if (message instanceof CleartextMessage) {
|
||||||
result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, config) : await message.verify(publicKeys, date, config);
|
result.signatures = await message.verify(publicKeys, date, config);
|
||||||
} else {
|
} else {
|
||||||
result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming, config) : await message.verify(publicKeys, date, streaming, config);
|
result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming, config) : await message.verify(publicKeys, date, streaming, config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,61 +279,43 @@ EJ4QcD/oQ6x1M/8X/iKQCtxZP8RnlrbH7ExkNON5s5g=
|
||||||
});
|
});
|
||||||
|
|
||||||
function omnibus() {
|
function omnibus() {
|
||||||
it('Omnibus BrainpoolP256r1 Test', function() {
|
it('Omnibus BrainpoolP256r1 Test', async function() {
|
||||||
const options = { userIds: { name: "Hi", email: "hi@hel.lo" }, curve: "brainpoolP256r1" };
|
const testData = input.createSomeMessage();
|
||||||
return openpgp.generateKey(options).then(function(firstKey) {
|
const testData2 = input.createSomeMessage();
|
||||||
const hi = firstKey.key;
|
|
||||||
const pubHi = hi.toPublic();
|
|
||||||
|
|
||||||
const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "brainpoolP256r1" };
|
const firstKey = await openpgp.generateKey({ userIds: { name: "Hi", email: "hi@hel.lo" }, curve: "brainpoolP256r1" });
|
||||||
return openpgp.generateKey(options).then(function(secondKey) {
|
const hi = firstKey.key;
|
||||||
const bye = secondKey.key;
|
const pubHi = hi.toPublic();
|
||||||
const pubBye = bye.toPublic();
|
const secondKey = await openpgp.generateKey({ userIds: { name: "Bye", email: "bye@good.bye" }, curve: "brainpoolP256r1" });
|
||||||
|
const bye = secondKey.key;
|
||||||
|
const pubBye = bye.toPublic();
|
||||||
|
|
||||||
const testData = input.createSomeMessage();
|
const cleartextMessage = await openpgp.sign({ message: openpgp.CleartextMessage.fromText(testData), privateKeys: hi });
|
||||||
const testData2 = input.createSomeMessage();
|
await openpgp.verify({
|
||||||
return Promise.all([
|
message: await openpgp.readCleartextMessage({ cleartextMessage }),
|
||||||
// Signing message
|
publicKeys: pubHi
|
||||||
openpgp.sign(
|
}).then(output => expect(output.signatures[0].valid).to.be.true);
|
||||||
{ message: openpgp.CleartextMessage.fromText(testData), privateKeys: hi }
|
// Verifying detached signature
|
||||||
).then(async signed => {
|
await openpgp.verify({
|
||||||
const msg = await openpgp.readCleartextMessage({ cleartextMessage: signed });
|
message: openpgp.Message.fromText(util.removeTrailingSpaces(testData)),
|
||||||
// Verifying signed message
|
publicKeys: pubHi,
|
||||||
return Promise.all([
|
signature: (await openpgp.readCleartextMessage({ cleartextMessage })).signature
|
||||||
openpgp.verify(
|
}).then(output => expect(output.signatures[0].valid).to.be.true);
|
||||||
{ message: msg, publicKeys: pubHi }
|
|
||||||
).then(output => expect(output.signatures[0].valid).to.be.true),
|
// Encrypting and signing
|
||||||
// Verifying detached signature
|
const encrypted = await openpgp.encrypt({
|
||||||
openpgp.verify({
|
message: openpgp.Message.fromText(testData2),
|
||||||
message: openpgp.CleartextMessage.fromText(testData),
|
publicKeys: [pubBye],
|
||||||
publicKeys: pubHi,
|
privateKeys: [hi]
|
||||||
signature: msg.signature
|
});
|
||||||
}).then(output => expect(output.signatures[0].valid).to.be.true)
|
// Decrypting and verifying
|
||||||
]);
|
return openpgp.decrypt({
|
||||||
}),
|
message: await openpgp.readMessage({ armoredMessage: encrypted }),
|
||||||
// Encrypting and signing
|
privateKeys: bye,
|
||||||
openpgp.encrypt(
|
publicKeys: [pubHi]
|
||||||
{
|
}).then(output => {
|
||||||
message: openpgp.Message.fromText(testData2),
|
expect(output.data).to.equal(testData2);
|
||||||
publicKeys: [pubBye],
|
expect(output.signatures[0].valid).to.be.true;
|
||||||
privateKeys: [hi]
|
|
||||||
}
|
|
||||||
).then(async encrypted => {
|
|
||||||
const msg = await openpgp.readMessage({ armoredMessage: encrypted });
|
|
||||||
// Decrypting and verifying
|
|
||||||
return openpgp.decrypt(
|
|
||||||
{
|
|
||||||
message: msg,
|
|
||||||
privateKeys: bye,
|
|
||||||
publicKeys: [pubHi]
|
|
||||||
}
|
|
||||||
).then(output => {
|
|
||||||
expect(output.data).to.equal(testData2);
|
|
||||||
expect(output.signatures[0].valid).to.be.true;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,63 +3,49 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
chai.use(require('chai-as-promised'));
|
chai.use(require('chai-as-promised'));
|
||||||
const input = require('./testInputs.js');
|
const input = require('./testInputs.js');
|
||||||
|
const util = require('../../src/util');
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
module.exports = () => describe('Elliptic Curve Cryptography for NIST P-256,P-384,P-521 curves @lightweight', function () {
|
module.exports = () => describe('Elliptic Curve Cryptography for NIST P-256,P-384,P-521 curves @lightweight', function () {
|
||||||
function omnibus() {
|
function omnibus() {
|
||||||
it('Omnibus NIST P-256 Test', function () {
|
it('Omnibus NIST P-256 Test', async function () {
|
||||||
const options = { userIds: { name: "Hi", email: "hi@hel.lo" }, curve: "p256" };
|
|
||||||
const testData = input.createSomeMessage();
|
const testData = input.createSomeMessage();
|
||||||
const testData2 = input.createSomeMessage();
|
const testData2 = input.createSomeMessage();
|
||||||
return openpgp.generateKey(options).then(function (firstKey) {
|
|
||||||
const hi = firstKey.key;
|
|
||||||
const pubHi = hi.toPublic();
|
|
||||||
|
|
||||||
const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "p256" };
|
const firstKey = await openpgp.generateKey({ userIds: { name: "Hi", email: "hi@hel.lo" }, curve: "p256" });
|
||||||
return openpgp.generateKey(options).then(function (secondKey) {
|
const hi = firstKey.key;
|
||||||
const bye = secondKey.key;
|
const pubHi = hi.toPublic();
|
||||||
const pubBye = bye.toPublic();
|
const secondKey = await openpgp.generateKey({ userIds: { name: "Bye", email: "bye@good.bye" }, curve: "p256" });
|
||||||
|
const bye = secondKey.key;
|
||||||
|
const pubBye = bye.toPublic();
|
||||||
|
|
||||||
return Promise.all([
|
const cleartextMessage = await openpgp.sign({ message: openpgp.CleartextMessage.fromText(testData), privateKeys: hi });
|
||||||
// Signing message
|
await openpgp.verify({
|
||||||
|
message: await openpgp.readCleartextMessage({ cleartextMessage }),
|
||||||
|
publicKeys: pubHi
|
||||||
|
}).then(output => expect(output.signatures[0].valid).to.be.true);
|
||||||
|
// Verifying detached signature
|
||||||
|
await openpgp.verify({
|
||||||
|
message: openpgp.Message.fromText(util.removeTrailingSpaces(testData)),
|
||||||
|
publicKeys: pubHi,
|
||||||
|
signature: (await openpgp.readCleartextMessage({ cleartextMessage })).signature
|
||||||
|
}).then(output => expect(output.signatures[0].valid).to.be.true);
|
||||||
|
|
||||||
openpgp.sign(
|
// Encrypting and signing
|
||||||
{ message: openpgp.CleartextMessage.fromText(testData), privateKeys: hi }
|
const encrypted = await openpgp.encrypt({
|
||||||
).then(async signed => {
|
message: openpgp.Message.fromText(testData2),
|
||||||
const msg = await openpgp.readCleartextMessage({ cleartextMessage: signed });
|
publicKeys: [pubBye],
|
||||||
// Verifying signed message
|
privateKeys: [hi]
|
||||||
return Promise.all([
|
});
|
||||||
openpgp.verify(
|
// Decrypting and verifying
|
||||||
{ message: msg, publicKeys: pubHi }
|
return openpgp.decrypt({
|
||||||
).then(output => expect(output.signatures[0].valid).to.be.true),
|
message: await openpgp.readMessage({ armoredMessage: encrypted }),
|
||||||
// Verifying detached signature
|
privateKeys: bye,
|
||||||
openpgp.verify({
|
publicKeys: [pubHi]
|
||||||
message: openpgp.CleartextMessage.fromText(testData),
|
}).then(output => {
|
||||||
publicKeys: pubHi,
|
expect(output.data).to.equal(testData2);
|
||||||
signature: msg.signature
|
expect(output.signatures[0].valid).to.be.true;
|
||||||
}).then(output => expect(output.signatures[0].valid).to.be.true)
|
|
||||||
]);
|
|
||||||
}),
|
|
||||||
// Encrypting and signing
|
|
||||||
openpgp.encrypt(
|
|
||||||
{ message: openpgp.Message.fromText(testData2),
|
|
||||||
publicKeys: [pubBye],
|
|
||||||
privateKeys: [hi] }
|
|
||||||
).then(async encrypted => {
|
|
||||||
const msg = await openpgp.readMessage({ armoredMessage: encrypted });
|
|
||||||
// Decrypting and verifying
|
|
||||||
return openpgp.decrypt(
|
|
||||||
{ message: msg,
|
|
||||||
privateKeys: bye,
|
|
||||||
publicKeys: [pubHi] }
|
|
||||||
).then(output => {
|
|
||||||
expect(output.data).to.equal(testData2);
|
|
||||||
expect(output.signatures[0].valid).to.be.true;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user