Skip to content

Commit

Permalink
feat: Cert signing with node-forge - fix: another signing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
mkg20001 committed Oct 29, 2017
1 parent c0e2361 commit fcac6d1
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 26 deletions.
3 changes: 3 additions & 0 deletions server/genca.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

openssl req -subj '/' -new -nodes -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
1 change: 1 addition & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"libp2p-secio": "^0.8.1",
"libp2p-spdy": "^0.11.0",
"libp2p-tcp": "^0.11.1",
"node-forge": "^0.7.1",
"protons": "^1.0.0"
}
}
48 changes: 45 additions & 3 deletions server/src/ca/forge.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,53 @@
'use strict'

const fs = require('fs')
const read = (file, desc) => {
if (!fs.existsSync(file))
throw new Error("Unable to find " + desc + " file " + JSON.stringify(file))
return fs.readFileSync(file).toString()
}
const forge = require('node-forge')
const pki = forge.pki
const debug = require('debug')
const log = debug('nodetrust:ca:forge')

module.exports = class ForgeCA {
constructor(swarm, config) {
this.swarm = swarm
this.config = config

this.cert = read(config.ca, 'Certificate Authority Certification')
this.key = read(config.key, 'Certificate Authority Private Key')
this.caKey = pki.privateKeyFromPem(this.key)
this.caCert = pki.certificateFromPem(this.cert)
}

doCertRequest(csr, sig, cb) {

doCertRequest(pem, id, cn, sig, cb) {
log('reading csr')
const csr = pki.certificationRequestFromPem(pem.toString())
if (!csr.verify()) return cb(new Error("Certification request invalid"))
// const ext = csr.getAttribute({name: 'extensionRequest'})
const cn_req = csr.subject.getField({
name: 'commonName'
}).value
if (cn != cn_req) return cb(new Error("Rejecting request: commonName (" + cn + ") and requested commonName (" + cn_req + ") do not match!"))
const cert = pki.createCertificate()

cert.serialNumber = '02'

cert.validity.notBefore = new Date()
cert.validity.notAfter = new Date()
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1)

cert.setSubject(csr.subject.attributes)

cert.setIssuer(this.caCert.subject.attributes)

cert.publicKey = csr.publicKey

cert.sign(this.caKey)

log('signing csr for %s', cn)

return cb(null, Buffer.from(pki.certificateToPem(cert)))
}
}
5 changes: 4 additions & 1 deletion server/src/ca/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const protos = require('../protos')

const debug = require('debug')
Expand All @@ -24,9 +26,10 @@ module.exports = (swarm, config) => {
conn.getPeerInfo((err, pi) => {
if (err) return cb(err)
const id = pi.id
log('incomming certificate request from', pi.id.toB58String())
id.pubKey.verify(data.certRequest, data.signature, (err, ok) => {
if (err || !ok) return cb(err)
ca.doCertRequest(data.certRequest, data.signature, (err, certificate) => {
ca.doCertRequest(data.certRequest, id, pi.id.toB58String() + "." + swarm.zone, data.signature, (err, certificate) => {
if (err) return cb(err)
return respond({
success: true,
Expand Down
4 changes: 2 additions & 2 deletions server/src/config.dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
},
"ca": {
"provider": "forge",
"key": "key.pem",
"ca": "ca.pem"
"key": "cakey.pem",
"ca": "cacert.pem"
},
"dns": {
"provider": "bind9"
Expand Down
41 changes: 30 additions & 11 deletions server/src/discovery/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
'use strict'

const protos = require('../protos')

const debug = require('debug')
const log = debug('nodetrust:discovery')

module.exports = (swarm, config) => {
let discoveryDB = {}
let peerIDs = []
let lastUpdate = {}

const expire = config.expire || 5 * 60 * 1000

function updateDB() {
const time = new Date().getTime()
let deleteId = []
for (const id in lastUpdate) {
const expireTime = lastUpdate[id]
if (expireTime < time) {
log('%s has expired, removing', id)
delete discoveryDB[id]
deleteId.push(id)
}
}
peerIDs = peerIDs.filter(id => deleteId.indexOf(id) == -1)
}

setInterval(updateDB, 5000)

swarm.handle('/nodetrust/discovery/1.0.0', (protocol, conn) => {
protos.server(conn, protos.discovery, (data, respond) => {
const cb = err => {
Expand All @@ -14,17 +38,12 @@ module.exports = (swarm, config) => {
}
conn.getPeerInfo((err, pi) => {
if (err) return cb(err)
const id = pi.id
id.verify(data.certRequest, data.signature, (err, ok) => {
if (err || !ok) return cb(err)
ca.doCertRequest(data.certRequest, data.signature, (err, certificate) => {
if (err) return cb(err)
return respond({
success: true,
certificate
})
})
})
const id = pi.id.toB58String()
if (peerIDs.indexOf(id) == -1) {
log('adding %s', id)
peerIDs.push(id)
}
lastUpdate[id] = new Date().getTime() + expire
})
})
})
Expand Down
12 changes: 4 additions & 8 deletions server/src/dns/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const protos = require('../protos')

const debug = require('debug')
Expand All @@ -24,15 +26,9 @@ module.exports = (swarm, config) => {
conn.getPeerInfo((err, pi) => {
if (err) return cb(err)
const id = pi.id
id.verify(data.certRequest, data.signature, (err, ok) => {
id.pubKey.verify(data.time.toString(), data.signature, (err, ok) => {
if (err || !ok) return cb(err)
ca.doCertRequest(data.certRequest, data.signature, (err, certificate) => {
if (err) return cb(err)
return respond({
success: true,
certificate
})
})

})
})
})
Expand Down
3 changes: 3 additions & 0 deletions server/src/protos.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const protobuf = require('protons')
const pull = require('pull-stream')
const debug = require('debug')
const log = debug('error')
const once = require('once')

module.exports = {
info: protobuf('message Request { } message Result { required string zone = 1; }'),
Expand All @@ -29,6 +30,8 @@ module.exports = {
)
},
client: (conn, def, data, cb) => {
cb = once(cb)
setTimeout(() => cb(new Error('Timeout')), 10 * 1000)
pull(
pull.values([def.Request.encode(data)]),
conn,
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ module.exports = class NodeTrust {
renewDNS(cb) {
log('renewing dns')
const time = new Date().getTime()
this.id.sign(time.toString(), (err, signature) => {
this.id.privKey.sign(time.toString(), (err, signature) => {
if (err) return cb(err)

this.swarm.dial(this.node, '/nodetrust/dns/1.0.0', (err, conn) => {
Expand Down

0 comments on commit fcac6d1

Please sign in to comment.