mirror of
https://codeberg.org/keyoxide/doipjs.git
synced 2024-12-22 22:49:28 -07:00
Add signature verification
This commit is contained in:
parent
ff8d496a15
commit
9db48d627d
3 changed files with 138 additions and 0 deletions
|
@ -15,10 +15,12 @@ limitations under the License.
|
|||
*/
|
||||
const claims = require('./claims')
|
||||
const keys = require('./keys')
|
||||
const signatures = require('./signatures')
|
||||
const serviceproviders = require('./serviceproviders')
|
||||
const utils = require('./utils')
|
||||
|
||||
exports.claims = claims
|
||||
exports.keys = keys
|
||||
exports.signatures = signatures
|
||||
exports.serviceproviders = serviceproviders
|
||||
exports.utils = utils
|
||||
|
|
80
src/signatures.js
Normal file
80
src/signatures.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
Copyright 2020 Yarmo Mackenbach
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
const openpgp = require('openpgp')
|
||||
const mergeOptions = require('merge-options')
|
||||
const claims = require('./claims')
|
||||
const keys = require('./keys')
|
||||
|
||||
const verify = (signature, opts) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let errors = [], sigData
|
||||
try {
|
||||
sigData = await openpgp.cleartext.readArmored(signature)
|
||||
} catch (error) {
|
||||
errors.push('invalid_signature')
|
||||
reject({ errors: errors })
|
||||
}
|
||||
|
||||
const text = sigData.getText()
|
||||
let sigKeys = []
|
||||
let sigClaims = []
|
||||
text.split('\n').forEach((line, i) => {
|
||||
const match = line.match(/^(.*)\=(.*)$/i)
|
||||
if (!match) {
|
||||
return
|
||||
}
|
||||
switch (match[1].toLowerCase()) {
|
||||
case 'key':
|
||||
sigKeys.push(match[2])
|
||||
break
|
||||
|
||||
case 'proof':
|
||||
sigClaims.push(match[2])
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
if (sigKeys.length === 0) {
|
||||
errors.push('no_linked_keys')
|
||||
reject({ errors: errors })
|
||||
}
|
||||
|
||||
const keyData = await keys.fetch.uri(sigKeys[0])
|
||||
const fingerprint = keyData.keyPacket.getFingerprint()
|
||||
|
||||
try {
|
||||
const sigVerification = await sigData.verify([keyData])
|
||||
await sigVerification[0].verified
|
||||
} catch (e) {
|
||||
errors.push('invalid_signature_verification')
|
||||
reject({ errors: errors })
|
||||
}
|
||||
|
||||
const claimVerifications = await claims.verify(sigClaims, fingerprint, opts)
|
||||
|
||||
resolve({
|
||||
errors: errors,
|
||||
publicKey: keyData,
|
||||
fingerprint: fingerprint,
|
||||
claims: claimVerifications
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exports.verify = verify
|
56
test/signatures.test.js
Normal file
56
test/signatures.test.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2020 Yarmo Mackenbach
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
const chai = require('chai')
|
||||
const expect = chai.expect
|
||||
|
||||
const doipjs = require('../src')
|
||||
|
||||
const sigProfile = `-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
Hey there! Here's a signature profile with doip-related proofs.
|
||||
|
||||
openpgp4fpr:3637202523e7c1309ab79e99ef2dc5827b445f4b
|
||||
key=hkp:test@doip.rocks
|
||||
proof=dns:doip.rocks
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQHEBAEBCgAuFiEENjcgJSPnwTCat56Z7y3FgntEX0sFAl/3JBMQHHRlc3RAZG9p
|
||||
cC5yb2NrcwAKCRDvLcWCe0RfS7XvC/wN9F/0ef/w1yXJqApgSNfc8WJxKS232g7L
|
||||
prb3EMhNI9JV13yfZObb664WahkrMOiiIeN2vyofpU1h80cucQwmTcsBav/TX7HI
|
||||
aBtXYtC6XvAhNUsctfA7C/uTSL3+St8G6ahbP7RLmal0r8vfIRgLMco1LtNpQM1v
|
||||
gjkjNpceKkl10cJgx7UiT1RWIIvisnEGNgK31XaN8oRwAMSySjl2n4fRjDRlJPVd
|
||||
cK+WvS4GJS24jRqGqZASTusPVRAOxtY+uEwX0HepUicgaHdFSFZ4iHByyrKEMi9L
|
||||
sS5Z7/ZvHXgmS1BUV9++vtChi6zaFwMJZnkMci3C0xwoQ3MECNN2OrPExFFcqk/z
|
||||
CgC81QrXNjGMZrBmSzPDgsibGe5G1VlQ73h1VhMjdcBZ1EjN0trEm3Ka8TDhJysS
|
||||
cXbjvHSGniZ7M3S9S8knAfIquPvTp7+L7wWgSSB5VObPp1r+96n87hyFZUp7PCvl
|
||||
3XkJV2l34fePSR73Ka7jmX86ARn4+HM=
|
||||
=ADl+
|
||||
-----END PGP SIGNATURE-----`
|
||||
|
||||
describe('signatures.verify', () => {
|
||||
it('should be a function (2 arguments)', () => {
|
||||
expect(doipjs.signatures.verify).to.be.a('function')
|
||||
expect(doipjs.signatures.verify).to.have.length(2)
|
||||
})
|
||||
it('should verify the demonstration signature', async () => {
|
||||
const verification = await doipjs.signatures.verify(sigProfile)
|
||||
expect(verification.errors).to.be.length(0)
|
||||
expect(verification.fingerprint).to.be.equal('3637202523e7c1309ab79e99ef2dc5827b445f4b')
|
||||
expect(verification.claims).to.be.length(1)
|
||||
expect(verification.claims[0].isVerified).to.be.true
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue