mirror of
https://codeberg.org/keyoxide/doipjs.git
synced 2024-12-22 22:49: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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- doip.keys.fetch function (with tests)
|
||||||
|
|
||||||
## [0.15.5] - 2022-03-25
|
## [0.15.5] - 2022-03-25
|
||||||
### Fixed
|
### 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 key1 = doip.keys.fetchHKP('alice@domain.tld');
|
||||||
* const key2 = doip.keys.fetchHKP('123abc123abc');
|
* const key2 = doip.keys.fetchHKP('123abc123abc');
|
||||||
*/
|
*/
|
||||||
exports.fetchHKP = async (identifier, keyserverDomain) => {
|
const fetchHKP = async (identifier, keyserverDomain) => {
|
||||||
const keyserverBaseUrl = keyserverDomain
|
const keyserverBaseUrl = keyserverDomain
|
||||||
? `https://${keyserverDomain}`
|
? `https://${keyserverDomain}`
|
||||||
: 'https://keys.openpgp.org'
|
: 'https://keys.openpgp.org'
|
||||||
|
@ -71,7 +71,7 @@ exports.fetchHKP = async (identifier, keyserverDomain) => {
|
||||||
* @example
|
* @example
|
||||||
* const key = doip.keys.fetchWKD('alice@domain.tld');
|
* const key = doip.keys.fetchWKD('alice@domain.tld');
|
||||||
*/
|
*/
|
||||||
exports.fetchWKD = async (identifier) => {
|
const fetchWKD = async (identifier) => {
|
||||||
const wkd = new WKD()
|
const wkd = new WKD()
|
||||||
const lookupOpts = {
|
const lookupOpts = {
|
||||||
email: identifier
|
email: identifier
|
||||||
|
@ -104,7 +104,7 @@ exports.fetchWKD = async (identifier) => {
|
||||||
* @example
|
* @example
|
||||||
* const key = doip.keys.fetchKeybase('alice', '123abc123abc');
|
* 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}`
|
const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
|
||||||
let rawKeyContent
|
let rawKeyContent
|
||||||
try {
|
try {
|
||||||
|
@ -146,7 +146,7 @@ exports.fetchKeybase = async (username, fingerprint) => {
|
||||||
* -----END PGP PUBLIC KEY BLOCK-----`
|
* -----END PGP PUBLIC KEY BLOCK-----`
|
||||||
* const key = doip.keys.fetchPlaintext(plainkey);
|
* const key = doip.keys.fetchPlaintext(plainkey);
|
||||||
*/
|
*/
|
||||||
exports.fetchPlaintext = async (rawKeyContent) => {
|
const fetchPlaintext = async (rawKeyContent) => {
|
||||||
const publicKey = await openpgp.readKey({
|
const publicKey = await openpgp.readKey({
|
||||||
armoredKey: rawKeyContent
|
armoredKey: rawKeyContent
|
||||||
})
|
})
|
||||||
|
@ -167,7 +167,7 @@ exports.fetchPlaintext = async (rawKeyContent) => {
|
||||||
* const key2 = doip.keys.fetchURI('hkp:123abc123abc');
|
* const key2 = doip.keys.fetchURI('hkp:123abc123abc');
|
||||||
* const key3 = doip.keys.fetchURI('wkd:alice@domain.tld');
|
* const key3 = doip.keys.fetchURI('wkd:alice@domain.tld');
|
||||||
*/
|
*/
|
||||||
exports.fetchURI = async (uri) => {
|
const fetchURI = async (uri) => {
|
||||||
if (!validUrl.isUri(uri)) {
|
if (!validUrl.isUri(uri)) {
|
||||||
throw new Error('Invalid URI')
|
throw new Error('Invalid URI')
|
||||||
}
|
}
|
||||||
|
@ -181,22 +181,72 @@ exports.fetchURI = async (uri) => {
|
||||||
|
|
||||||
switch (match[1]) {
|
switch (match[1]) {
|
||||||
case 'hkp':
|
case 'hkp':
|
||||||
return exports.fetchHKP(
|
return await fetchHKP(
|
||||||
match[3] ? match[3] : match[2],
|
match[3] ? match[3] : match[2],
|
||||||
match[3] ? match[2] : null
|
match[3] ? match[2] : null
|
||||||
)
|
)
|
||||||
|
|
||||||
case 'wkd':
|
case 'wkd':
|
||||||
return exports.fetchWKD(match[2])
|
return await fetchWKD(match[2])
|
||||||
|
|
||||||
case 'kb':
|
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:
|
default:
|
||||||
throw new Error('Invalid URI protocol')
|
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
|
* Process a public key to get user data and claims
|
||||||
* @function
|
* @function
|
||||||
|
@ -209,7 +259,7 @@ exports.fetchURI = async (uri) => {
|
||||||
* console.log(claim.uri);
|
* console.log(claim.uri);
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
exports.process = async (publicKey) => {
|
const process = async (publicKey) => {
|
||||||
if (!publicKey || !(publicKey instanceof openpgp.PublicKey)) {
|
if (!publicKey || !(publicKey instanceof openpgp.PublicKey)) {
|
||||||
throw new Error('Invalid public key')
|
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
|
=tVW7
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`
|
-----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', () => {
|
describe('keys.fetchURI', () => {
|
||||||
it('should be a function (1 argument)', () => {
|
it('should be a function (1 argument)', () => {
|
||||||
expect(doipjs.keys.fetchURI).to.be.a('function')
|
expect(doipjs.keys.fetchURI).to.be.a('function')
|
||||||
|
|
Loading…
Reference in a new issue