forked from Mirrors/doipjs
Release 0.7.0
This commit is contained in:
parent
f5e1c07be2
commit
514ba3c4b4
7 changed files with 169 additions and 128 deletions
|
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.7.0] - 2020-12-05
|
||||||
|
### Changed
|
||||||
|
- Properly reject promises
|
||||||
|
|
||||||
## [0.6.0] - 2020-11-20
|
## [0.6.0] - 2020-11-20
|
||||||
### Changed
|
### Changed
|
||||||
- Handle multiple users in key
|
- Handle multiple users in key
|
||||||
|
|
278
dist/doip.js
vendored
278
dist/doip.js
vendored
|
@ -1193,7 +1193,7 @@ process.umask = function() { return 0; };
|
||||||
},{}],9:[function(require,module,exports){
|
},{}],9:[function(require,module,exports){
|
||||||
module.exports={
|
module.exports={
|
||||||
"name": "doipjs",
|
"name": "doipjs",
|
||||||
"version": "0.5.1",
|
"version": "0.6.0",
|
||||||
"description": "Decentralized OpenPGP Identity Proofs library in Node.js",
|
"description": "Decentralized OpenPGP Identity Proofs library in Node.js",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1259,7 +1259,11 @@ limitations under the License.
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
const validUrl = require('valid-url')
|
const validUrl = require('valid-url')
|
||||||
const openpgp = require(path.join(require.resolve('openpgp'), '..', 'openpgp.min.js'))
|
const openpgp = require(path.join(
|
||||||
|
require.resolve('openpgp'),
|
||||||
|
'..',
|
||||||
|
'openpgp.min.js'
|
||||||
|
))
|
||||||
const serviceproviders = require('./serviceproviders')
|
const serviceproviders = require('./serviceproviders')
|
||||||
const keys = require('./keys')
|
const keys = require('./keys')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
@ -1288,15 +1292,12 @@ const runVerificationJson = (
|
||||||
switch (checkRelation) {
|
switch (checkRelation) {
|
||||||
default:
|
default:
|
||||||
case 'contains':
|
case 'contains':
|
||||||
re = new RegExp(
|
re = new RegExp(checkClaim, 'gi')
|
||||||
checkClaim.replace('[', '\\[').replace(']', '\\]'),
|
res.isVerified = re.test(proofData.replace(/\r?\n|\r|\\/g, ''))
|
||||||
'gi'
|
|
||||||
)
|
|
||||||
res.isVerified = re.test(proofData.replace(/\r?\n|\r/, ''))
|
|
||||||
break
|
break
|
||||||
case 'equals':
|
case 'equals':
|
||||||
res.isVerified =
|
res.isVerified =
|
||||||
proofData.replace(/\r?\n|\r/, '').toLowerCase() ==
|
proofData.replace(/\r?\n|\r|\\/g, '').toLowerCase() ==
|
||||||
checkClaim.toLowerCase()
|
checkClaim.toLowerCase()
|
||||||
break
|
break
|
||||||
case 'oneOf':
|
case 'oneOf':
|
||||||
|
@ -1354,9 +1355,24 @@ const runVerification = (proofData, spData) => {
|
||||||
|
|
||||||
const verify = async (input, fingerprint, opts) => {
|
const verify = async (input, fingerprint, opts) => {
|
||||||
if (input instanceof openpgp.key.Key) {
|
if (input instanceof openpgp.key.Key) {
|
||||||
const fingerprintLocal = await keys.getFingerprint(input)
|
const fingerprintFromKey = await keys.getFingerprint(input)
|
||||||
const claims = await keys.getClaims(input)
|
const userData = await keys.getUserData(input)
|
||||||
return await verify(claims, fingerprintLocal, opts)
|
|
||||||
|
const promises = userData.map(async (user, i) => {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const res = await verify(user.notations, fingerprintFromKey, opts)
|
||||||
|
resolve(res)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Claim verification failed: ${user.userData.id}`, e)
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Promise.all(promises).then((values) => {
|
||||||
|
return values
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if (input instanceof Array) {
|
if (input instanceof Array) {
|
||||||
const promises = input.map(async (uri, i) => {
|
const promises = input.map(async (uri, i) => {
|
||||||
|
@ -1390,7 +1406,7 @@ const verify = async (input, fingerprint, opts) => {
|
||||||
opts = mergeOptions(defaultOpts, opts ? opts : {})
|
opts = mergeOptions(defaultOpts, opts ? opts : {})
|
||||||
|
|
||||||
if (!validUrl.isUri(uri)) {
|
if (!validUrl.isUri(uri)) {
|
||||||
throw new Error('Not a valid URI')
|
throw new Error('Invalid URI')
|
||||||
}
|
}
|
||||||
|
|
||||||
const spMatches = serviceproviders.match(uri, opts)
|
const spMatches = serviceproviders.match(uri, opts)
|
||||||
|
@ -1493,11 +1509,15 @@ const path = require('path')
|
||||||
const bent = require('bent')
|
const bent = require('bent')
|
||||||
const req = bent('GET')
|
const req = bent('GET')
|
||||||
const validUrl = require('valid-url')
|
const validUrl = require('valid-url')
|
||||||
const openpgp = require(path.join(require.resolve('openpgp'), '..', 'openpgp.min.js'))
|
const openpgp = require(path.join(
|
||||||
|
require.resolve('openpgp'),
|
||||||
|
'..',
|
||||||
|
'openpgp.min.js'
|
||||||
|
))
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
|
|
||||||
const fetchHKP = async (identifier, keyserverBaseUrl) => {
|
const fetchHKP = (identifier, keyserverBaseUrl) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
keyserverBaseUrl = keyserverBaseUrl
|
keyserverBaseUrl = keyserverBaseUrl
|
||||||
? keyserverBaseUrl
|
? keyserverBaseUrl
|
||||||
: 'https://keys.openpgp.org/'
|
: 'https://keys.openpgp.org/'
|
||||||
|
@ -1509,64 +1529,64 @@ const fetchHKP = async (identifier, keyserverBaseUrl) => {
|
||||||
let publicKey = await hkp.lookup(lookupOpts)
|
let publicKey = await hkp.lookup(lookupOpts)
|
||||||
publicKey = (await openpgp.key.readArmored(publicKey)).keys[0]
|
publicKey = (await openpgp.key.readArmored(publicKey)).keys[0]
|
||||||
|
|
||||||
return publicKey
|
if (publicKey == undefined) {
|
||||||
} catch (e) {
|
reject('Key does not exist or could not be fetched')
|
||||||
console.error(e)
|
}
|
||||||
return undefined
|
|
||||||
}
|
resolve(publicKey)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchWKD = async (identifier) => {
|
const fetchWKD = (identifier) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const wkd = new openpgp.WKD()
|
const wkd = new openpgp.WKD()
|
||||||
const lookupOpts = {
|
const lookupOpts = {
|
||||||
email: identifier,
|
email: identifier,
|
||||||
}
|
}
|
||||||
const publicKey = (await wkd.lookup(lookupOpts)).keys[0]
|
const publicKey = (await wkd.lookup(lookupOpts)).keys[0]
|
||||||
|
|
||||||
return publicKey
|
if (publicKey == undefined) {
|
||||||
} catch (e) {
|
reject('Key does not exist or could not be fetched')
|
||||||
console.error(e)
|
}
|
||||||
return undefined
|
|
||||||
}
|
resolve(publicKey)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchKeybase = async (username, fingerprint) => {
|
const fetchKeybase = (username, fingerprint) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
|
const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
|
||||||
try {
|
try {
|
||||||
const rawKeyContent = await req(opts.keyLink)
|
const rawKeyContent = await req(opts.keyLink)
|
||||||
.then(function (response) {
|
.then((response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return undefined
|
reject(`Error fetching Keybase key: ${e.message}`)
|
||||||
}
|
}
|
||||||
const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0]
|
const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0]
|
||||||
|
|
||||||
return publicKey
|
if (publicKey == undefined) {
|
||||||
} catch (e) {
|
reject('Key does not exist or could not be fetched')
|
||||||
console.error(e)
|
}
|
||||||
return undefined
|
|
||||||
}
|
resolve(publicKey)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchPlaintext = async (rawKeyContent) => {
|
const fetchPlaintext = (rawKeyContent) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0]
|
const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0]
|
||||||
|
|
||||||
return publicKey
|
resolve(publicKey)
|
||||||
} catch (e) {
|
})
|
||||||
console.error(e)
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchSignature = async (rawSignatureContent, keyserverBaseUrl) => {
|
const fetchSignature = (rawSignatureContent, keyserverBaseUrl) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
let sig = await openpgp.signature.readArmored(rawSignatureContent)
|
let sig = await openpgp.signature.readArmored(rawSignatureContent)
|
||||||
if ('compressed' in sig.packets[0]) {
|
if ('compressed' in sig.packets[0]) {
|
||||||
sig = sig.packets[0]
|
sig = sig.packets[0]
|
||||||
|
@ -1577,88 +1597,94 @@ const fetchSignature = async (rawSignatureContent, keyserverBaseUrl) => {
|
||||||
const sigUserId = sig.packets[0].signersUserId
|
const sigUserId = sig.packets[0].signersUserId
|
||||||
const sigKeyId = await sig.packets[0].issuerKeyId.toHex()
|
const sigKeyId = await sig.packets[0].issuerKeyId.toHex()
|
||||||
|
|
||||||
return fetchHKP(sigUserId ? sigUserId : sigKeyId, keyserverBaseUrl)
|
resolve(fetchHKP(sigUserId ? sigUserId : sigKeyId, keyserverBaseUrl))
|
||||||
} catch (e) {
|
})
|
||||||
console.error(e)
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchURI = async (uri) => {
|
const fetchURI = (uri) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
if (!validUrl.isUri(uri)) {
|
if (!validUrl.isUri(uri)) {
|
||||||
throw new Error('Invalid URI')
|
reject('Invalid URI')
|
||||||
}
|
}
|
||||||
|
|
||||||
const re = /([a-zA-Z0-9]*):([a-zA-Z0-9@._=+\-]*)(\:[a-zA-Z0-9@._=+\-]*)?/
|
const re = /([a-zA-Z0-9]*):([a-zA-Z0-9@._=+\-]*)(\:[a-zA-Z0-9@._=+\-]*)?/
|
||||||
const match = uri.match(re)
|
const match = uri.match(re)
|
||||||
|
|
||||||
if (!match[1]) {
|
if (!match[1]) {
|
||||||
throw new Error('Invalid URI')
|
reject('Invalid URI')
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (match[1]) {
|
switch (match[1]) {
|
||||||
case 'hkp':
|
case 'hkp':
|
||||||
return fetchHKP(match[2], match.length >= 4 ? match[3] : null)
|
resolve(fetchHKP(match[2], match.length >= 4 ? match[3] : null))
|
||||||
break
|
break
|
||||||
case 'wkd':
|
case 'wkd':
|
||||||
return fetchWKD(match[2])
|
resolve(fetchWKD(match[2]))
|
||||||
break
|
break
|
||||||
case 'kb':
|
case 'kb':
|
||||||
return fetchKeybase(match[2], match.length >= 4 ? match[3] : null)
|
resolve(fetchKeybase(match[2], match.length >= 4 ? match[3] : null))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid URI protocol')
|
reject('Invalid URI protocol')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} catch (e) {
|
})
|
||||||
console.error(e)
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const process = async (publicKey) => {
|
const process = (publicKey) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const fingerprint = await publicKey.primaryKey.getFingerprint()
|
if (!publicKey) {
|
||||||
const user = await publicKey.getPrimaryUser()
|
reject('Invalid public key')
|
||||||
|
|
||||||
return {
|
|
||||||
fingerprint: fingerprint,
|
|
||||||
user: user,
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
const fingerprint = await publicKey.primaryKey.getFingerprint()
|
||||||
console.error(e)
|
const primaryUser = await publicKey.getPrimaryUser()
|
||||||
return undefined
|
const users = publicKey.users
|
||||||
}
|
let primaryUserIndex,
|
||||||
}
|
usersOutput = []
|
||||||
|
|
||||||
const getClaims = async (publicKey) => {
|
users.forEach((user, i) => {
|
||||||
try {
|
usersOutput[i] = {
|
||||||
const keyData = await process(publicKey)
|
userData: {
|
||||||
let notations = keyData.user.selfCertification.rawNotations
|
id: user.userId.userid,
|
||||||
|
name: user.userId.name,
|
||||||
notations = notations.map(({ name, value, humanReadable }) => {
|
email: user.userId.email,
|
||||||
if (humanReadable && name === 'proof@metacode.biz') {
|
comment: user.userId.comment,
|
||||||
return openpgp.util.decode_utf8(value)
|
isPrimary: primaryUser.index === i,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const notations = user.selfCertifications[0].rawNotations
|
||||||
|
usersOutput[i].notations = notations.map(
|
||||||
|
({ name, value, humanReadable }) => {
|
||||||
|
if (humanReadable && name === 'proof@metacode.biz') {
|
||||||
|
return openpgp.util.decode_utf8(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return notations
|
resolve({
|
||||||
} catch (e) {
|
fingerprint: fingerprint,
|
||||||
console.error(e)
|
users: usersOutput,
|
||||||
return undefined
|
primaryUserIndex: primaryUser.index,
|
||||||
}
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFingerprint = async (publicKey) => {
|
const getUserData = (publicKey) => {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const keyData = await process(publicKey)
|
const keyData = await process(publicKey)
|
||||||
|
|
||||||
return keyData.fingerprint
|
resolve(keyData.users)
|
||||||
} catch (e) {
|
})
|
||||||
console.error(e)
|
}
|
||||||
return undefined
|
|
||||||
}
|
const getFingerprint = (publicKey) => {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const keyData = await process(publicKey)
|
||||||
|
|
||||||
|
resolve(keyData.fingerprint)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetch = {
|
exports.fetch = {
|
||||||
|
@ -1670,7 +1696,7 @@ exports.fetch = {
|
||||||
signature: fetchSignature,
|
signature: fetchSignature,
|
||||||
}
|
}
|
||||||
exports.process = process
|
exports.process = process
|
||||||
exports.getClaims = getClaims
|
exports.getUserData = getUserData
|
||||||
exports.getFingerprint = getFingerprint
|
exports.getFingerprint = getFingerprint
|
||||||
|
|
||||||
},{"bent":1,"merge-options":5,"path":6,"valid-url":8}],13:[function(require,module,exports){
|
},{"bent":1,"merge-options":5,"path":6,"valid-url":8}],13:[function(require,module,exports){
|
||||||
|
@ -1741,37 +1767,41 @@ const match = (uri, opts) => {
|
||||||
return matches
|
return matches
|
||||||
}
|
}
|
||||||
|
|
||||||
const directRequestHandler = async (spData, opts) => {
|
const directRequestHandler = (spData, opts) => {
|
||||||
const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri
|
return new Promise(async (resolve, reject) => {
|
||||||
let res
|
const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri
|
||||||
|
let res
|
||||||
|
|
||||||
switch (spData.proof.format) {
|
switch (spData.proof.format) {
|
||||||
case 'json':
|
case 'json':
|
||||||
res = await req(url, null, {
|
res = await req(url, null, {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'User-Agent': `doipjs/${require('../package.json').version}`,
|
'User-Agent': `doipjs/${require('../package.json').version}`,
|
||||||
})
|
})
|
||||||
return await res.json()
|
resolve(await res.json())
|
||||||
break
|
break
|
||||||
case 'text':
|
case 'text':
|
||||||
res = await req(url)
|
res = await req(url)
|
||||||
return await res.text()
|
resolve(await res.text())
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error('No specified proof data format')
|
reject('No specified proof data format')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyRequestHandler = async (spData, opts) => {
|
const proxyRequestHandler = (spData, opts) => {
|
||||||
const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri
|
return new Promise(async (resolve, reject) => {
|
||||||
const res = await req(
|
const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri
|
||||||
utils.generateProxyURL(spData.proof.format, url, opts),
|
const res = await req(
|
||||||
null,
|
utils.generateProxyURL(spData.proof.format, url, opts),
|
||||||
{ Accept: 'application/json' }
|
null,
|
||||||
)
|
{ Accept: 'application/json' }
|
||||||
const json = await res.json()
|
)
|
||||||
return json.content
|
const json = await res.json()
|
||||||
|
resolve(json.content)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.list = list
|
exports.list = list
|
||||||
|
|
2
dist/doip.min.js
vendored
2
dist/doip.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
||||||
# doip.js <small>0.6.0</small>
|
# doip.js <small>0.7.0</small>
|
||||||
|
|
||||||
<img src="doip.png" width="120">
|
<img src="doip.png" width="120">
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.7.0]
|
||||||
|
|
||||||
|
[2020-12-05](https://codeberg.org/keyoxide/doipjs/releases/tag/0.7.0)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Properly reject promises
|
||||||
|
|
||||||
## [0.6.0]
|
## [0.6.0]
|
||||||
|
|
||||||
[2020-11-20](https://codeberg.org/keyoxide/doipjs/releases/tag/0.6.0)
|
[2020-11-20](https://codeberg.org/keyoxide/doipjs/releases/tag/0.6.0)
|
||||||
|
|
|
@ -15,7 +15,7 @@ npm install --save doipjs
|
||||||
Install on website by including the following HTML snippet:
|
Install on website by including the following HTML snippet:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.jsdelivr.net/npm/doipjs@0.6.0/dist/doip.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/doipjs@0.7.0/dist/doip.min.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
Next step: [quick start (Node.js)](quickstart-nodejs.md) and [quick start (browser)](quickstart-browser.md)
|
Next step: [quick start (Node.js)](quickstart-nodejs.md) and [quick start (browser)](quickstart-browser.md)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "doipjs",
|
"name": "doipjs",
|
||||||
"version": "0.6.0",
|
"version": "0.7.0",
|
||||||
"description": "Decentralized OpenPGP Identity Proofs library in Node.js",
|
"description": "Decentralized OpenPGP Identity Proofs library in Node.js",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
Loading…
Reference in a new issue