diff --git a/src/keys.js b/src/keys.js index a3adb33..989daff 100644 --- a/src/keys.js +++ b/src/keys.js @@ -16,6 +16,8 @@ limitations under the License. const axios = require('axios') const validUrl = require('valid-url') const openpgp = require('openpgp') +const HKP = require('@openpgp/hkp-client') +const WKD = require('@openpgp/wkd-client') const Claim = require('./claim') /** @@ -28,7 +30,7 @@ const Claim = require('./claim') * @function * @param {string} identifier - Fingerprint or email address * @param {string} [keyserverDomain=keys.openpgp.org] - Domain of the keyserver - * @returns {openpgp.key.Key} + * @returns {openpgp.PublicKey} * @example * const key1 = doip.keys.fetchHKP('alice@domain.tld'); * const key2 = doip.keys.fetchHKP('123abc123abc'); @@ -38,26 +40,26 @@ exports.fetchHKP = async (identifier, keyserverDomain) => { ? `https://${keyserverDomain}` : 'https://keys.openpgp.org' - const hkp = new openpgp.HKP(keyserverBaseUrl) + const hkp = new HKP(keyserverBaseUrl) const lookupOpts = { query: identifier } - const publicKey = await hkp.lookup(lookupOpts).catch((error) => { - throw new Error(`Key does not exist or could not be fetched (${error})`) - }) + const publicKey = await hkp + .lookup(lookupOpts) + .catch((error) => { + throw new Error(`Key does not exist or could not be fetched (${error})`) + }) if (!publicKey) { throw new Error('Key does not exist or could not be fetched') } - return await openpgp.key - .readArmored(publicKey) - .then((result) => { - return result.keys[0] - }) + return await openpgp.readKey({ + armoredKey: publicKey + }) .catch((error) => { - throw new Error(`Key does not exist or could not be fetched (${error})`) + throw new Error(`Key could not be read (${error})`) }) } @@ -65,24 +67,32 @@ exports.fetchHKP = async (identifier, keyserverDomain) => { * Fetch a public key using Web Key Directory * @function * @param {string} identifier - Identifier of format 'username@domain.tld` - * @returns {openpgp.key.Key} + * @returns {openpgp.PublicKey} * @example * const key = doip.keys.fetchWKD('alice@domain.tld'); */ exports.fetchWKD = async (identifier) => { - const wkd = new openpgp.WKD() + const wkd = new WKD() const lookupOpts = { email: identifier } - return await wkd + const publicKey = await wkd .lookup(lookupOpts) - .then((result) => { - return result.keys[0] - }) .catch((error) => { throw new Error(`Key does not exist or could not be fetched (${error})`) }) + + if (!publicKey) { + throw new Error('Key does not exist or could not be fetched') + } + + return await openpgp.readKey({ + binaryKey: publicKey + }) + .catch((error) => { + throw new Error(`Key could not be read (${error})`) + }) } /** @@ -90,7 +100,7 @@ exports.fetchWKD = async (identifier) => { * @function * @param {string} username - Keybase username * @param {string} fingerprint - Fingerprint of key - * @returns {openpgp.key.Key} + * @returns {openpgp.PublicKey} * @example * const key = doip.keys.fetchKeybase('alice', '123abc123abc'); */ @@ -114,11 +124,9 @@ exports.fetchKeybase = async (username, fingerprint) => { throw new Error(`Error fetching Keybase key: ${e.message}`) } - return await openpgp.key - .readArmored(rawKeyContent) - .then((result) => { - return result.keys[0] - }) + return await openpgp.readKey({ + armoredKey: rawKeyContent + }) .catch((error) => { throw new Error(`Key does not exist or could not be fetched (${error})`) }) @@ -128,7 +136,7 @@ exports.fetchKeybase = async (username, fingerprint) => { * Get a public key from plaintext data * @function * @param {string} rawKeyContent - Plaintext ASCII-formatted public key data - * @returns {openpgp.key.Key} + * @returns {openpgp.PublicKey} * @example * const plainkey = `-----BEGIN PGP PUBLIC KEY BLOCK----- * @@ -139,7 +147,13 @@ exports.fetchKeybase = async (username, fingerprint) => { * const key = doip.keys.fetchPlaintext(plainkey); */ exports.fetchPlaintext = async (rawKeyContent) => { - const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0] + const publicKey = await openpgp.readKey({ + armoredKey: rawKeyContent + }) + .catch((error) => { + throw new Error(`Key could not be read (${error})`) + }) + return publicKey } @@ -147,7 +161,7 @@ exports.fetchPlaintext = async (rawKeyContent) => { * Fetch a public key using an URI * @function * @param {string} uri - URI that defines the location of the key - * @returns {openpgp.key.Key} + * @returns {openpgp.PublicKey} * @example * const key1 = doip.keys.fetchURI('hkp:alice@domain.tld'); * const key2 = doip.keys.fetchURI('hkp:123abc123abc'); @@ -186,7 +200,7 @@ exports.fetchURI = async (uri) => { /** * Process a public key to get user data and claims * @function - * @param {openpgp.key.Key} publicKey - The public key to process + * @param {openpgp.PublicKey} publicKey - The public key to process * @returns {object} * @example * const key = doip.keys.fetchURI('hkp:alice@domain.tld'); @@ -196,11 +210,11 @@ exports.fetchURI = async (uri) => { * }); */ exports.process = async (publicKey) => { - if (!publicKey || !(publicKey instanceof openpgp.key.Key)) { + if (!publicKey || !(publicKey instanceof openpgp.PublicKey)) { throw new Error('Invalid public key') } - const fingerprint = await publicKey.primaryKey.getFingerprint() + const fingerprint = publicKey.getFingerprint() const primaryUser = await publicKey.getPrimaryUser() const users = publicKey.users const usersOutput = [] @@ -229,7 +243,7 @@ exports.process = async (publicKey) => { ) .map( ({ value }) => - new Claim(openpgp.util.decode_utf8(value), fingerprint) + new Claim(new TextDecoder().decode(value), fingerprint) ) usersOutput[i].userData.isRevoked = selfCertification.revoked diff --git a/src/signatures.js b/src/signatures.js index 9cefe96..14527e2 100644 --- a/src/signatures.js +++ b/src/signatures.js @@ -46,13 +46,14 @@ const process = async (signature) => { } try { - sigData = await openpgp.cleartext.readArmored(signature) + sigData = await openpgp.readCleartextMessage({ + cleartextMessage: signature + }) } catch (error) { - throw new Error('invalid_signature') + throw new Error(`Signature could not be read (${error})`) } - - const issuerKeyId = sigData.signature.packets[0].issuerKeyId.toHex() - const signersUserId = sigData.signature.packets[0].signersUserId + const issuerKeyID = sigData.signature.packets[0].issuerKeyID.toHex() + const signersUserID = sigData.signature.packets[0].signersUserID const preferredKeyServer = sigData.signature.packets[0].preferredKeyServer || 'https://keys.openpgp.org/' @@ -87,9 +88,9 @@ const process = async (signature) => { } catch (e) {} } // Try WKD - if (!result.key.data && signersUserId) { + if (!result.key.data && signersUserID) { try { - result.key.uri = `wkd:${signersUserId}` + result.key.uri = `wkd:${signersUserID}` result.key.data = await keys.fetchURI(result.key.uri) result.key.fetchMethod = 'wkd' } catch (e) {} @@ -98,7 +99,7 @@ const process = async (signature) => { if (!result.key.data) { try { const match = preferredKeyServer.match(/^(.*:\/\/)?([^/]*)(?:\/)?$/i) - result.key.uri = `hkp:${match[2]}:${issuerKeyId || signersUserId}` + result.key.uri = `hkp:${match[2]}:${issuerKeyID || signersUserID}` result.key.data = await keys.fetchURI(result.key.uri) result.key.fetchMethod = 'hkp' } catch (e) { @@ -115,9 +116,9 @@ const process = async (signature) => { const primaryUserData = await result.key.data.getPrimaryUser() let userData - if (signersUserId) { + if (signersUserID) { result.key.data.users.forEach((user) => { - if (user.userId.email === signersUserId) { + if (user.userID.email === signersUserID) { userData = user } }) @@ -127,11 +128,11 @@ const process = async (signature) => { } result.users[0].userData = { - id: userData.userId ? userData.userId.userid : null, - name: userData.userId ? userData.userId.name : null, - email: userData.userId ? userData.userId.email : null, - comment: userData.userId ? userData.userId.comment : null, - isPrimary: primaryUserData.user.userId.userid === userData.userId.userid + id: userData.userID ? userData.userID.userid : null, + name: userData.userID ? userData.userID.name : null, + email: userData.userID ? userData.userID.email : null, + comment: userData.userID ? userData.userID.comment : null, + isPrimary: primaryUserData.user.userID.userid === userData.userID.userid } result.primaryUserIndex = result.users[0].userData.isPrimary ? 0 : null diff --git a/test/keys.test.js b/test/keys.test.js index ff5aeac..bc98ee8 100644 --- a/test/keys.test.js +++ b/test/keys.test.js @@ -99,7 +99,7 @@ describe('keys.fetchURI', () => { it('should return a Key object when provided a hkp: uri', async () => { expect( await doipjs.keys.fetchURI(`hkp:${pubKeyFingerprint}`) - ).to.be.instanceOf(openpgp.key.Key) + ).to.be.instanceOf(openpgp.PublicKey) }).timeout('12s') it('should reject when provided an invalid uri', () => { return expect( @@ -115,12 +115,12 @@ describe('keys.fetchHKP', () => { }) it('should return a Key object when provided a valid fingerprint', async () => { expect(await doipjs.keys.fetchHKP(pubKeyFingerprint)).to.be.instanceOf( - openpgp.key.Key + openpgp.PublicKey ) }) it('should return a Key object when provided a valid email address', async () => { expect(await doipjs.keys.fetchHKP(pubKeyEmail)).to.be.instanceOf( - openpgp.key.Key + openpgp.PublicKey ) }) it('should reject when provided an invalid fingerprint', async () => { @@ -146,7 +146,7 @@ describe('keys.fetchPlaintext', () => { }) it('should return a Key object', async () => { expect(await doipjs.keys.fetchPlaintext(pubKeyPlaintext)).to.be.instanceOf( - openpgp.key.Key + openpgp.PublicKey ) }) })