mirror of
https://codeberg.org/keyoxide/doipjs.git
synced 2024-12-22 14:39:28 -07:00
Add doip.keys.fetch
This commit is contained in:
parent
a67b825fae
commit
65e8210ffa
3 changed files with 91 additions and 9 deletions
|
@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- doip.keys.fetch function (with tests)
|
||||
|
||||
## [0.15.5] - 2022-03-25
|
||||
### Fixed
|
||||
|
|
76
src/keys.js
76
src/keys.js
|
@ -35,7 +35,7 @@ const Claim = require('./claim')
|
|||
* const key1 = doip.keys.fetchHKP('alice@domain.tld');
|
||||
* const key2 = doip.keys.fetchHKP('123abc123abc');
|
||||
*/
|
||||
exports.fetchHKP = async (identifier, keyserverDomain) => {
|
||||
const fetchHKP = async (identifier, keyserverDomain) => {
|
||||
const keyserverBaseUrl = keyserverDomain
|
||||
? `https://${keyserverDomain}`
|
||||
: 'https://keys.openpgp.org'
|
||||
|
@ -71,7 +71,7 @@ exports.fetchHKP = async (identifier, keyserverDomain) => {
|
|||
* @example
|
||||
* const key = doip.keys.fetchWKD('alice@domain.tld');
|
||||
*/
|
||||
exports.fetchWKD = async (identifier) => {
|
||||
const fetchWKD = async (identifier) => {
|
||||
const wkd = new WKD()
|
||||
const lookupOpts = {
|
||||
email: identifier
|
||||
|
@ -104,7 +104,7 @@ exports.fetchWKD = async (identifier) => {
|
|||
* @example
|
||||
* const key = doip.keys.fetchKeybase('alice', '123abc123abc');
|
||||
*/
|
||||
exports.fetchKeybase = async (username, fingerprint) => {
|
||||
const fetchKeybase = async (username, fingerprint) => {
|
||||
const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
|
||||
let rawKeyContent
|
||||
try {
|
||||
|
@ -146,7 +146,7 @@ exports.fetchKeybase = async (username, fingerprint) => {
|
|||
* -----END PGP PUBLIC KEY BLOCK-----`
|
||||
* const key = doip.keys.fetchPlaintext(plainkey);
|
||||
*/
|
||||
exports.fetchPlaintext = async (rawKeyContent) => {
|
||||
const fetchPlaintext = async (rawKeyContent) => {
|
||||
const publicKey = await openpgp.readKey({
|
||||
armoredKey: rawKeyContent
|
||||
})
|
||||
|
@ -167,7 +167,7 @@ exports.fetchPlaintext = async (rawKeyContent) => {
|
|||
* const key2 = doip.keys.fetchURI('hkp:123abc123abc');
|
||||
* const key3 = doip.keys.fetchURI('wkd:alice@domain.tld');
|
||||
*/
|
||||
exports.fetchURI = async (uri) => {
|
||||
const fetchURI = async (uri) => {
|
||||
if (!validUrl.isUri(uri)) {
|
||||
throw new Error('Invalid URI')
|
||||
}
|
||||
|
@ -181,22 +181,72 @@ exports.fetchURI = async (uri) => {
|
|||
|
||||
switch (match[1]) {
|
||||
case 'hkp':
|
||||
return exports.fetchHKP(
|
||||
return await fetchHKP(
|
||||
match[3] ? match[3] : match[2],
|
||||
match[3] ? match[2] : null
|
||||
)
|
||||
|
||||
case 'wkd':
|
||||
return exports.fetchWKD(match[2])
|
||||
return await fetchWKD(match[2])
|
||||
|
||||
case 'kb':
|
||||
return exports.fetchKeybase(match[2], match.length >= 4 ? match[3] : null)
|
||||
return await fetchKeybase(match[2], match.length >= 4 ? match[3] : null)
|
||||
|
||||
default:
|
||||
throw new Error('Invalid URI protocol')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a public key
|
||||
*
|
||||
* This function will attempt to detect the identifier and fetch the key
|
||||
* accordingly. If the identifier is an email address, it will first try and
|
||||
* fetch the key using WKD and then HKP. Otherwise, it will try HKP only.
|
||||
*
|
||||
* This function will also try and parse the input as a plaintext key
|
||||
* @function
|
||||
* @param {string} identifier - URI that defines the location of the key
|
||||
* @returns {openpgp.PublicKey}
|
||||
* @example
|
||||
* const key1 = doip.keys.fetch('alice@domain.tld');
|
||||
* const key2 = doip.keys.fetch('123abc123abc');
|
||||
*/
|
||||
const fetch = async (identifier) => {
|
||||
const re = /([a-zA-Z0-9@._=+-]*)(?::([a-zA-Z0-9@._=+-]*))?/
|
||||
const match = identifier.match(re)
|
||||
|
||||
let pubKey = null
|
||||
|
||||
// Attempt plaintext
|
||||
if (!pubKey) {
|
||||
try {
|
||||
pubKey = await fetchPlaintext(identifier)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Attempt WKD
|
||||
if (!pubKey && identifier.includes('@')) {
|
||||
try {
|
||||
pubKey = await fetchWKD(match[1])
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Attempt HKP
|
||||
if (!pubKey) {
|
||||
pubKey = await fetchHKP(
|
||||
match[2] ? match[2] : match[1],
|
||||
match[2] ? match[1] : null
|
||||
)
|
||||
}
|
||||
|
||||
if (!pubKey) {
|
||||
throw new Error('Key does not exist or could not be fetched')
|
||||
}
|
||||
|
||||
return pubKey
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a public key to get user data and claims
|
||||
* @function
|
||||
|
@ -209,7 +259,7 @@ exports.fetchURI = async (uri) => {
|
|||
* console.log(claim.uri);
|
||||
* });
|
||||
*/
|
||||
exports.process = async (publicKey) => {
|
||||
const process = async (publicKey) => {
|
||||
if (!publicKey || !(publicKey instanceof openpgp.PublicKey)) {
|
||||
throw new Error('Invalid public key')
|
||||
}
|
||||
|
@ -261,3 +311,11 @@ exports.process = async (publicKey) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.fetchHKP = fetchHKP
|
||||
exports.fetchWKD = fetchWKD
|
||||
exports.fetchKeybase = fetchKeybase
|
||||
exports.fetchPlaintext = fetchPlaintext
|
||||
exports.fetchURI = fetchURI
|
||||
exports.fetch = fetch
|
||||
exports.process = process
|
||||
|
|
|
@ -91,6 +91,28 @@ Q+AZdYCbM0hdBjP4xdKZcpqak8ksb+aQFXjGacDL/XN4VrP+tBGxkqIqreoDcgIb
|
|||
=tVW7
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
describe('keys.fetch', () => {
|
||||
it('should be a function (1 argument)', () => {
|
||||
expect(doipjs.keys.fetch).to.be.a('function')
|
||||
expect(doipjs.keys.fetch).to.have.length(1)
|
||||
})
|
||||
it('should return a Key object when provided a valid fingerprint', async () => {
|
||||
expect(
|
||||
await doipjs.keys.fetch(pubKeyFingerprint)
|
||||
).to.be.instanceOf(openpgp.PublicKey)
|
||||
}).timeout('12s')
|
||||
it('should return a Key object when provided a valid email address', async () => {
|
||||
expect(
|
||||
await doipjs.keys.fetch(pubKeyEmail)
|
||||
).to.be.instanceOf(openpgp.PublicKey)
|
||||
}).timeout('12s')
|
||||
it('should reject when provided an invalid email address', () => {
|
||||
return expect(
|
||||
doipjs.keys.fetch('invalid@doip.rocks')
|
||||
).to.eventually.be.rejectedWith('Key does not exist or could not be fetched')
|
||||
}).timeout('12s')
|
||||
})
|
||||
|
||||
describe('keys.fetchURI', () => {
|
||||
it('should be a function (1 argument)', () => {
|
||||
expect(doipjs.keys.fetchURI).to.be.a('function')
|
||||
|
|
Loading…
Reference in a new issue