From 9175b768873c068b05b267f4570adaa82d20cbda Mon Sep 17 00:00:00 2001 From: larabr <larabr+github@protonmail.com> Date: Thu, 9 Feb 2023 23:07:27 +0100 Subject: [PATCH] Docs: clarify `Key.clone()` behaviour (#1589) --- src/key/key.js | 8 ++++---- test/general/key.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/key/key.js b/src/key/key.js index 130ff3d4..773fd0e2 100644 --- a/src/key/key.js +++ b/src/key/key.js @@ -170,13 +170,13 @@ class Key { } /** - * Clones the key object - * @param {Boolean} [deep=false] Whether to return a deep clone + * Clones the key object. The copy is shallow, as it references the same packet objects as the original. However, if the top-level API is used, the two key instances are effectively independent. + * @param {Boolean} [clonePrivateParams=false] Only relevant for private keys: whether the secret key paramenters should be deeply copied. This is needed if e.g. `encrypt()` is to be called either on the clone or the original key. * @returns {Promise<Key>} Clone of the key. */ - clone(deep = false) { + clone(clonePrivateParams = false) { const key = new this.constructor(this.toPacketList()); - if (deep) { + if (clonePrivateParams) { key.getKeys().forEach(k => { // shallow clone the key packets k.keyPacket = Object.create( diff --git a/test/general/key.js b/test/general/key.js index c22a75a4..e6e60a74 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -3236,6 +3236,26 @@ module.exports = () => describe('Key', function() { }); }); + it('clone() - removing users or their signatures does not affect the original key', async function() { + const key = await openpgp.readKey({ armoredKey: priv_key_rsa }); + const keyClone = key.clone(); + expect(key.users[0].selfCertifications.length > 0).to.be.true; + expect(keyClone.users[0].selfCertifications.length > 0).to.be.true; + keyClone.users[0].selfCertifications = []; + expect(key.users[0].selfCertifications.length > 0).to.be.true; + expect(keyClone.users[0].selfCertifications.length > 0).to.be.false; + }); + + it('clone() - removing subkeys or their signatures does not affect the original key', async function() { + const key = await openpgp.readKey({ armoredKey: priv_key_rsa }); + const keyClone = key.clone(true); + expect(key.subkeys[0].bindingSignatures.length > 0).to.be.true; + expect(keyClone.subkeys[0].bindingSignatures.length > 0).to.be.true; + keyClone.subkeys[0].bindingSignatures = []; + expect(key.subkeys[0].bindingSignatures.length > 0).to.be.true; + expect(keyClone.subkeys[0].bindingSignatures.length > 0).to.be.false; + }); + it('revoke() - primary key', async function() { const privKey = await openpgp.decryptKey({ privateKey: await openpgp.readKey({ armoredKey: priv_key_arm2 }),