mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-11-26 07:25:51 +00:00
Merge 366d2c8eee9403cf0a64d3dd45dbb131bfdd4e22 into 843a69d0adbdec0f87af09f9000a9223e6614e5c
This commit is contained in:
commit
80af48438c
5
openpgp.d.ts
vendored
5
openpgp.d.ts
vendored
@ -383,7 +383,7 @@ declare abstract class BasePublicKeyPacket extends BasePacket {
|
||||
public hasSameFingerprintAs(other: BasePublicKeyPacket): boolean;
|
||||
public getCreationTime(): Date;
|
||||
public getKeyID(): KeyID;
|
||||
public isDecrypted(): boolean;
|
||||
public isDecrypted(): boolean | null;
|
||||
public publicParams: object;
|
||||
// `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa.
|
||||
// The key class hierarchy is already modelled to cover this, but the concrete key packet classes
|
||||
@ -394,11 +394,13 @@ declare abstract class BasePublicKeyPacket extends BasePacket {
|
||||
export class PublicKeyPacket extends BasePublicKeyPacket {
|
||||
static readonly tag: enums.packet.publicKey;
|
||||
protected isSubkey(): false;
|
||||
public isDecrypted(): null;
|
||||
}
|
||||
|
||||
export class PublicSubkeyPacket extends BasePublicKeyPacket {
|
||||
static readonly tag: enums.packet.publicSubkey;
|
||||
protected isSubkey(): true;
|
||||
public isDecrypted(): null;
|
||||
}
|
||||
|
||||
declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket {
|
||||
@ -406,6 +408,7 @@ declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket {
|
||||
public encrypt(passphrase: string, config?: Config): Promise<void>; // throws on error
|
||||
public decrypt(passphrase: string): Promise<void>; // throws on error
|
||||
public validate(): Promise<void>; // throws on error
|
||||
public isDecrypted(): boolean;
|
||||
public isDummy(): boolean;
|
||||
public isMissingSecretKeyMaterial(): boolean;
|
||||
public makeDummy(config?: Config): void;
|
||||
|
||||
@ -51,15 +51,18 @@ const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([
|
||||
* @throws if no key packet was found
|
||||
*/
|
||||
function createKey(packetlist) {
|
||||
for (const packet of packetlist) {
|
||||
switch (packet.constructor.tag) {
|
||||
case enums.packet.secretKey:
|
||||
return new PrivateKey(packetlist);
|
||||
case enums.packet.publicKey:
|
||||
return new PublicKey(packetlist);
|
||||
if (packetlist[0]?.constructor.tag === enums.packet.secretKey) {
|
||||
return new PrivateKey(packetlist);
|
||||
} else if (packetlist[0]?.constructor.tag === enums.packet.publicKey) {
|
||||
if (packetlist.findPacket(enums.packet.secretSubkey)) {
|
||||
return new PrivateKey(packetlist);
|
||||
} else {
|
||||
return new PublicKey(packetlist);
|
||||
}
|
||||
} else {
|
||||
throw new Error('No primary key packet found');
|
||||
}
|
||||
throw new Error('No key packet found');
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -383,10 +386,10 @@ export async function readPrivateKey({ armoredKey, binaryKey, config, ...rest })
|
||||
const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config);
|
||||
const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey);
|
||||
for (let i = 0; i < keyIndex.length; i++) {
|
||||
if (packetlist[keyIndex[i]].constructor.tag === enums.packet.publicKey) {
|
||||
const firstPrivateKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]);
|
||||
if (packetlist[keyIndex[i]].constructor.tag === enums.packet.publicKey && !firstPrivateKeyList.findPacket(enums.packet.secretSubkey)) {
|
||||
continue;
|
||||
}
|
||||
const firstPrivateKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]);
|
||||
return new PrivateKey(firstPrivateKeyList);
|
||||
}
|
||||
throw new Error('No secret key packet found');
|
||||
@ -470,10 +473,10 @@ export async function readPrivateKeys({ armoredKeys, binaryKeys, config }) {
|
||||
const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config);
|
||||
const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey);
|
||||
for (let i = 0; i < keyIndex.length; i++) {
|
||||
if (packetlist[keyIndex[i]].constructor.tag === enums.packet.publicKey) {
|
||||
const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]);
|
||||
if (packetlist[keyIndex[i]].constructor.tag === enums.packet.publicKey && !oneKeyList.findPacket(enums.packet.secretSubkey)) {
|
||||
continue;
|
||||
}
|
||||
const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]);
|
||||
const newKey = new PrivateKey(oneKeyList);
|
||||
keys.push(newKey);
|
||||
}
|
||||
|
||||
@ -523,3 +523,5 @@ export function checkKeyRequirements(keyPacket, config) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export const isPublicOrDummyKeyPacket = keyPacket => keyPacket.isDecrypted() === null || keyPacket.isDummy();
|
||||
|
||||
@ -49,13 +49,14 @@ class Key {
|
||||
/**
|
||||
* Transforms packetlist to structured key data
|
||||
* @param {PacketList} packetlist - The packets that form a key
|
||||
* @param {Set<enums.packet>} disallowedPackets - disallowed packet tags
|
||||
* @param {Boolean} expectPrivateKey - if a private key is expected, a SecretKeyPacket or SecretKeySubpacket must be present.
|
||||
*/
|
||||
packetListToStructure(packetlist, disallowedPackets = new Set()) {
|
||||
packetListToStructure(packetlist, expectPrivateKey) {
|
||||
let user;
|
||||
let primaryKeyID;
|
||||
let subkey;
|
||||
let ignoreUntil;
|
||||
let isPrivateKey;
|
||||
|
||||
for (const packet of packetlist) {
|
||||
|
||||
@ -78,7 +79,8 @@ class Key {
|
||||
if (!ignoreUntil.has(tag)) continue;
|
||||
ignoreUntil = null;
|
||||
}
|
||||
if (disallowedPackets.has(tag)) {
|
||||
isPrivateKey = isPrivateKey || tag === enums.packet.secretKey || tag === enums.packet.secretSubkey;
|
||||
if (!expectPrivateKey && isPrivateKey) {
|
||||
throw new Error(`Unexpected packet type: ${tag}`);
|
||||
}
|
||||
switch (tag) {
|
||||
@ -151,6 +153,13 @@ class Key {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.keyPacket) {
|
||||
throw new Error('Invalid key: missing primary key packet');
|
||||
}
|
||||
if (expectPrivateKey && !isPrivateKey) {
|
||||
throw new Error('No secret key packet found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,7 +273,13 @@ class Key {
|
||||
} catch (err) {
|
||||
throw util.wrapError('Could not verify primary key', err);
|
||||
}
|
||||
const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created);
|
||||
const subkeys = this.subkeys.slice().sort((a, b) => {
|
||||
const aIsPrivate = !helper.isPublicOrDummyKeyPacket(a.keyPacket);
|
||||
const bIsPrivate = !helper.isPublicOrDummyKeyPacket(b.keyPacket);
|
||||
const diffIsPrivate = bIsPrivate - aIsPrivate;
|
||||
// return non-dummy private (sub)keys first
|
||||
return diffIsPrivate !== 0 ? diffIsPrivate : b.keyPacket.created - a.keyPacket.created;
|
||||
});
|
||||
let exception;
|
||||
for (const subkey of subkeys) {
|
||||
if (!keyID || subkey.getKeyID().equals(keyID)) {
|
||||
|
||||
@ -18,10 +18,7 @@ class PrivateKey extends PublicKey {
|
||||
*/
|
||||
constructor(packetlist) {
|
||||
super();
|
||||
this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey]));
|
||||
if (!this.keyPacket) {
|
||||
throw new Error('Invalid key: missing private-key packet');
|
||||
}
|
||||
this.packetListToStructure(packetlist, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,8 +83,8 @@ class PrivateKey extends PublicKey {
|
||||
let exception = null;
|
||||
for (let i = 0; i < this.subkeys.length; i++) {
|
||||
if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) {
|
||||
if (this.subkeys[i].keyPacket.isDummy()) {
|
||||
exception = exception || new Error('Gnu-dummy key packets cannot be used for decryption');
|
||||
if (helper.isPublicOrDummyKeyPacket(this.subkeys[i].keyPacket)) {
|
||||
exception = exception || new Error('Public or gnu-dummy key packets cannot be used for decryption');
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -106,8 +103,8 @@ class PrivateKey extends PublicKey {
|
||||
// evaluate primary key
|
||||
const selfCertification = await this.getPrimarySelfSignature(date, userID, config);
|
||||
if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && helper.validateDecryptionKeyPacket(primaryKey, selfCertification, config)) {
|
||||
if (primaryKey.isDummy()) {
|
||||
exception = exception || new Error('Gnu-dummy key packets cannot be used for decryption');
|
||||
if (helper.isPublicOrDummyKeyPacket(primaryKey)) {
|
||||
exception = exception || new Error('Public or gnu-dummy key packets cannot be used for decryption');
|
||||
} else {
|
||||
keys.push(this);
|
||||
}
|
||||
@ -145,7 +142,7 @@ class PrivateKey extends PublicKey {
|
||||
}
|
||||
|
||||
let signingKeyPacket;
|
||||
if (!this.keyPacket.isDummy()) {
|
||||
if (!helper.isPublicOrDummyKeyPacket(this.keyPacket)) {
|
||||
signingKeyPacket = this.keyPacket;
|
||||
} else {
|
||||
/**
|
||||
@ -154,7 +151,7 @@ class PrivateKey extends PublicKey {
|
||||
*/
|
||||
const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 });
|
||||
// This could again be a dummy key
|
||||
if (signingKey && !signingKey.keyPacket.isDummy()) {
|
||||
if (signingKey && !helper.isPublicOrDummyKeyPacket(signingKey.keyPacket)) {
|
||||
signingKeyPacket = signingKey.keyPacket;
|
||||
}
|
||||
}
|
||||
@ -163,12 +160,12 @@ class PrivateKey extends PublicKey {
|
||||
return signingKeyPacket.validate();
|
||||
} else {
|
||||
const keys = this.getKeys();
|
||||
const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean);
|
||||
if (allDummies) {
|
||||
throw new Error('Cannot validate an all-gnu-dummy key');
|
||||
const allPublicOrDummies = keys.map(key => helper.isPublicOrDummyKeyPacket(key.keyPacket)).every(Boolean);
|
||||
if (allPublicOrDummies) {
|
||||
throw new Error('Cannot validate key without secret key material');
|
||||
}
|
||||
|
||||
return Promise.all(keys.map(async key => key.keyPacket.validate()));
|
||||
return Promise.all(keys.map(async key => helper.isPublicOrDummyKeyPacket(key.keyPacket) || key.keyPacket.validate()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,14 +235,14 @@ class PrivateKey extends PublicKey {
|
||||
if (options.rsaBits < config.minRSABits) {
|
||||
throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`);
|
||||
}
|
||||
const secretKeyPacket = this.keyPacket;
|
||||
if (secretKeyPacket.isDummy()) {
|
||||
throw new Error('Cannot add subkey to gnu-dummy primary key');
|
||||
const primaryKeyPacket = this.keyPacket;
|
||||
if (helper.isPublicOrDummyKeyPacket(primaryKeyPacket)) {
|
||||
throw new Error('Cannot add subkey to gnu-dummy or public primary key');
|
||||
}
|
||||
if (!secretKeyPacket.isDecrypted()) {
|
||||
if (!primaryKeyPacket.isDecrypted()) {
|
||||
throw new Error('Key is not decrypted');
|
||||
}
|
||||
const defaultOptions = secretKeyPacket.getAlgorithmInfo();
|
||||
const defaultOptions = primaryKeyPacket.getAlgorithmInfo();
|
||||
defaultOptions.type = getDefaultSubkeyType(defaultOptions.algorithm);
|
||||
defaultOptions.rsaBits = defaultOptions.bits || 4096;
|
||||
defaultOptions.curve = defaultOptions.curve || 'curve25519Legacy';
|
||||
@ -256,7 +253,7 @@ class PrivateKey extends PublicKey {
|
||||
// The config is always overwritten since we cannot tell if the defaultConfig was changed by the user.
|
||||
const keyPacket = await helper.generateSecretSubkey(options, { ...config, v6Keys: this.keyPacket.version === 6 });
|
||||
helper.checkKeyRequirements(keyPacket, config);
|
||||
const bindingSignature = await helper.createBindingSignature(keyPacket, secretKeyPacket, options, config);
|
||||
const bindingSignature = await helper.createBindingSignature(keyPacket, primaryKeyPacket, options, config);
|
||||
const packetList = this.toPacketList();
|
||||
packetList.push(keyPacket, bindingSignature);
|
||||
return new PrivateKey(packetList);
|
||||
|
||||
@ -32,10 +32,7 @@ class PublicKey extends Key {
|
||||
this.users = [];
|
||||
this.subkeys = [];
|
||||
if (packetlist) {
|
||||
this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey]));
|
||||
if (!this.keyPacket) {
|
||||
throw new Error('Invalid key: missing public-key packet');
|
||||
}
|
||||
this.packetListToStructure(packetlist, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ import { CleartextMessage } from './cleartext';
|
||||
import { generate, reformat, getPreferredCompressionAlgo } from './key';
|
||||
import defaultConfig from './config';
|
||||
import util from './util';
|
||||
import { checkKeyRequirements } from './key/helper';
|
||||
import { checkKeyRequirements, isPublicOrDummyKeyPacket } from './key/helper';
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -189,10 +189,13 @@ export async function decryptKey({ privateKey, passphrase, config, ...rest }) {
|
||||
const passphrases = util.isArray(passphrase) ? passphrase : [passphrase];
|
||||
|
||||
try {
|
||||
await Promise.all(clonedPrivateKey.getKeys().map(key => (
|
||||
await Promise.all(clonedPrivateKey.getKeys().map(key => {
|
||||
if (isPublicOrDummyKeyPacket(key.keyPacket)) {
|
||||
return;
|
||||
}
|
||||
// try to decrypt each key with any of the given passphrases
|
||||
util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase)))
|
||||
)));
|
||||
return util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase)));
|
||||
}));
|
||||
|
||||
await clonedPrivateKey.validate(config);
|
||||
return clonedPrivateKey;
|
||||
@ -230,6 +233,9 @@ export async function encryptKey({ privateKey, passphrase, config, ...rest }) {
|
||||
try {
|
||||
await Promise.all(keys.map(async (key, i) => {
|
||||
const { keyPacket } = key;
|
||||
if (isPublicOrDummyKeyPacket(keyPacket)) {
|
||||
return;
|
||||
}
|
||||
await keyPacket.encrypt(passphrases[i], config);
|
||||
keyPacket.clearPrivateParams();
|
||||
}));
|
||||
|
||||
@ -1857,6 +1857,54 @@ S2rSjQ4JF0Ktgdr9585haknpGwr31t486KxXOY4AEsiBmRyvTbaQegwKaQ+C
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
`;
|
||||
|
||||
// public primary key with:
|
||||
// - one signing private subkey
|
||||
// - one signing public subkey
|
||||
// - one encryption private subkey
|
||||
// - one encryption public subkey
|
||||
const privateKeyWithPublicKeyPackets = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xjMEZr9cyxYJKwYBBAHaRw8BAQdAlC7g7Q4UZmN5zNhFynWuEXYn1KV8Jfp4
|
||||
DMiKf8ZQ5oDNDzx0ZXN0QHRlc3QuY29tPsLAEwQTFgoAhQWCZr9cywMLCQcJ
|
||||
kPhnPZ0LDe1wRRQAAAAAABwAIHNhbHRAbm90YXRpb25zLm9wZW5wZ3Bqcy5v
|
||||
cmeWobLLkXmgpg9Pet9xOLiKvUAGKchlrMxBubhvTpBGygUVCAoMDgQWAAIB
|
||||
AhkBApsDAh4BFiEEYmvn2jb9uzAG41Ql+Gc9nQsN7XAAAHGyAP9URiF2uq/O
|
||||
8PJkjoehixMx9h9a8L+lPd56ymbdxUb/swEA0tNWA9alk/m3rml0aTPNucuG
|
||||
Aj/FLBixvbva+SWEkgrOMwRmv1zLFgkrBgEEAdpHDwEBB0DdyjGHiVCA0Cbr
|
||||
5u5pcuZmYZylLDURujjhEWYcLKIg0MLAuwQYFgoBLQWCZr9cywmQ+Gc9nQsN
|
||||
7XBFFAAAAAAAHAAgc2FsdEBub3RhdGlvbnMub3BlbnBncGpzLm9yZ5UtjGIA
|
||||
N+2fOlsIv9vwi5MaTUxoXXc+Mw6ETjRvW3fUApsCvKAEGRYKAG0Fgma/XMsJ
|
||||
kHC3NLlxFk7wRRQAAAAAABwAIHNhbHRAbm90YXRpb25zLm9wZW5wZ3Bqcy5v
|
||||
cme74M+JTJ/Clb0bApLqL/QGKOZbaXdL3Y/p02QX2o6AgRYhBFFraL50hRm3
|
||||
RC4PZHC3NLlxFk7wAABAgwEAhQ+EgvirBcabNlmHV6nEbqyTz85oBj8SKNM2
|
||||
d+tDQ3YBAN3jXoPGx22sVoy5rAMerwq1lhnlgCh4xfdTw1jtr2QEFiEEYmvn
|
||||
2jb9uzAG41Ql+Gc9nQsN7XAAALGsAQCCDkhWJRgiCoHIvjWwRqVWU1BsVaj5
|
||||
dr6fxkK9yaOv6QEA+JjqAgPcRo/LGHpO0dZS9qi1Zpy4u5bT2FunXqvNDQ7O
|
||||
MwRmv1zLFgkrBgEEAdpHDwEBB0A4CyxR5ZSvF8FrEhjzFO8W6paAtqm92p7k
|
||||
+HQC7TRhKcLAuwQYFgoBLQWCZr9cywmQ+Gc9nQsN7XBFFAAAAAAAHAAgc2Fs
|
||||
dEBub3RhdGlvbnMub3BlbnBncGpzLm9yZ8eA420LE1oqZm9UQ2mAl0VpYysv
|
||||
9w9FhamakpSbum0jApsCvKAEGRYKAG0Fgma/XMsJkMrApZFFMT1MRRQAAAAA
|
||||
ABwAIHNhbHRAbm90YXRpb25zLm9wZW5wZ3Bqcy5vcmcyU0rvMw4GVCasfsGO
|
||||
ke8VBnf9DX73KF4Fuw5HRwy65BYhBPmjv8j7/15Fu3bvL8rApZFFMT1MAADv
|
||||
OgEAp2P/olg/8frAKhZNhBNNcnZ3mBPgw+jnVB2q3lJR3G4A/Az8kxPmyhmf
|
||||
vaorTRswb2d7xes3ubunWLvHBcU+LSAIFiEEYmvn2jb9uzAG41Ql+Gc9nQsN
|
||||
7XAAAO9CAP4y3wh7tKf5QkWhz18Lo2Zjqv4S+rCVJZWe9SDRFJq4rwD/eJTb
|
||||
wFTiP1x1KHQY+bnZQUll10A9c/G9yMrOC0qR8gHHXQRmv1zLEgorBgEEAZdV
|
||||
AQUBAQdAdWmLtTwhcOH7tlr+2FEysYY3Z6gPpP6EalQnbXEHKRsDAQgHAAD/
|
||||
ROS5zCtNP0O2t9U7T/Cs2+n1snTVW+RBTbESM+hjWfgTIcK+BBgWCgBwBYJm
|
||||
v1zLCZD4Zz2dCw3tcEUUAAAAAAAcACBzYWx0QG5vdGF0aW9ucy5vcGVucGdw
|
||||
anMub3JniqUd+21Sxr5oHb+ctdQKLEpRYCSR1I0Ap/Z5o3XfqRACmwwWIQRi
|
||||
a+faNv27MAbjVCX4Zz2dCw3tcAAABPQBAK7S2Izm3D4dEkoJb869wOqtK4be
|
||||
zdP4cdQMfO/4hsLRAPwMxCX51Okaj/SvwEzjI/RCPmfv9l441PmzQheQ4Gqr
|
||||
BM44BGa/XMsSCisGAQQBl1UBBQEBB0CqHCGPBZg8ioGvjV4nKteCFs4hAzLn
|
||||
nFHyv2RF+YdFJgMBCAfCvgQYFgoAcAWCZr9cywmQ+Gc9nQsN7XBFFAAAAAAA
|
||||
HAAgc2FsdEBub3RhdGlvbnMub3BlbnBncGpzLm9yZw1hBEkI2dXfJXMVH/ha
|
||||
uCz6Opp4tu616/VBZWGParIfApsMFiEEYmvn2jb9uzAG41Ql+Gc9nQsN7XAA
|
||||
ABWvAQDZznAKuYpaWKklOVw2z8fgLP6sL9ai+zBjlWogKoswNgEAoXTZ1SOJ
|
||||
bWGFbTrrvSBYui/idHvj8Tax0EDVVw6W1Qc=
|
||||
=OKHa
|
||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||
|
||||
const eddsaKeyAsEcdsa = `
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: OpenPGP.js VERSION
|
||||
@ -3016,6 +3064,18 @@ export default () => describe('Key', function() {
|
||||
expect(key.write()).to.deep.equal(expectedSerializedKey.data);
|
||||
});
|
||||
|
||||
it('Parsing armored key with public primary key and private subkeys', async function() {
|
||||
const key = await openpgp.readKey({ armoredKey: privateKeyWithPublicKeyPackets });
|
||||
|
||||
expect(key.isDecrypted()).to.be.true;
|
||||
expect(key.isPrivate()).to.be.true;
|
||||
const signingKey = await key.getSigningKey();
|
||||
expect(signingKey.getKeyID().equals(key.subkeys[0].getKeyID())).to.be.true;
|
||||
const decryptedKeys = await key.getDecryptionKeys();
|
||||
expect(decryptedKeys.length).to.equal(1);
|
||||
expect(decryptedKeys[0].getKeyID().equals(key.subkeys[2].getKeyID())).to.be.true;
|
||||
});
|
||||
|
||||
it('Parses V5 sample key', async function() {
|
||||
// sec ed25519 2019-03-20 [SC]
|
||||
// 19347BC9872464025F99DF3EC2E0000ED9884892E1F7B3EA4C94009159569B54
|
||||
@ -3657,7 +3717,7 @@ PzIEeL7UH3trraFmi+Gq8u4kAA==
|
||||
|
||||
it('validate() - throw if all-gnu-dummy key', async function() {
|
||||
const key = await openpgp.readKey({ armoredKey: gnuDummyKey });
|
||||
await expect(key.validate()).to.be.rejectedWith('Cannot validate an all-gnu-dummy key');
|
||||
await expect(key.validate()).to.be.rejectedWith('Cannot validate key without secret key material');
|
||||
});
|
||||
|
||||
it('validate() - gnu-dummy primary key with signing subkey', async function() {
|
||||
@ -3670,6 +3730,11 @@ PzIEeL7UH3trraFmi+Gq8u4kAA==
|
||||
await expect(key.validate()).to.not.be.rejected;
|
||||
});
|
||||
|
||||
it('validate() - key with public key packets', async function() {
|
||||
const key = await openpgp.readKey({ armoredKey: privateKeyWithPublicKeyPackets });
|
||||
await expect(key.validate()).to.not.be.rejected;
|
||||
});
|
||||
|
||||
it('validate() - curve ed25519 (eddsa) cannot be used for ecdsa', async function() {
|
||||
const key = await openpgp.readKey({ armoredKey: eddsaKeyAsEcdsa });
|
||||
await expect(key.validate()).to.be.rejectedWith('Key is invalid');
|
||||
@ -4474,6 +4539,14 @@ VYGdb3eNlV8CfoEC
|
||||
await expect(openpgp.encryptKey({ privateKey: encryptedKey, passphrase })).to.be.eventually.rejectedWith(/Key packet is already encrypted/);
|
||||
});
|
||||
|
||||
it('Should support encrypting a private key which includes public key packets', async function() {
|
||||
const passphrase = 'hello world';
|
||||
const key = await openpgp.readKey({ armoredKey: privateKeyWithPublicKeyPackets });
|
||||
const encryptedKey = await openpgp.encryptKey({ privateKey: key, passphrase });
|
||||
const decryptedKey = await openpgp.decryptKey({ privateKey: encryptedKey, passphrase });
|
||||
await expect(decryptedKey.write()).to.deep.equal(key.write());
|
||||
});
|
||||
|
||||
describe('addSubkey functionality testing', function() {
|
||||
const rsaBits = 1024;
|
||||
let minRSABits;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user