2015-07-08 14:51:49 -07:00
|
|
|
/*
|
|
|
|
* Id is an object representation of a peer Id. a peer Id is a multihash
|
|
|
|
*/
|
|
|
|
|
2016-03-03 17:31:33 +00:00
|
|
|
const fs = require('fs')
|
|
|
|
const multihashing = require('multihashing')
|
|
|
|
const base58 = require('bs58')
|
|
|
|
const forge = require('node-forge')
|
|
|
|
const protobuf = require('protocol-buffers')
|
|
|
|
const path = require('path')
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-03-03 17:31:33 +00:00
|
|
|
const isNode = !global.window
|
2016-02-10 13:55:59 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// protobuf read from file
|
2016-03-10 10:32:48 -08:00
|
|
|
const messages = isNode ? protobuf(fs.readFileSync(path.resolve(__dirname, 'pb/crypto.proto'))) : protobuf(require('buffer!./pb/crypto.proto'))
|
2016-02-10 13:55:59 -08:00
|
|
|
|
2015-07-08 14:51:49 -07:00
|
|
|
exports = module.exports = Id
|
|
|
|
|
2015-11-05 17:47:44 +00:00
|
|
|
exports.Buffer = Buffer
|
|
|
|
|
2015-07-17 08:14:44 -07:00
|
|
|
function Id (id, privKey, pubKey) {
|
2016-03-03 17:31:33 +00:00
|
|
|
const self = this
|
2015-07-08 14:51:49 -07:00
|
|
|
|
|
|
|
if (!(self instanceof Id)) {
|
|
|
|
throw new Error('Id must be called with new')
|
|
|
|
}
|
|
|
|
|
|
|
|
self.privKey = privKey
|
|
|
|
self.pubKey = pubKey
|
|
|
|
self.id = id // multihash - sha256 - buffer
|
|
|
|
|
|
|
|
// pretty print
|
|
|
|
self.toPrint = function () {
|
|
|
|
return {
|
2016-02-02 15:50:45 -08:00
|
|
|
id: self.toB58String(),
|
2015-07-08 14:51:49 -07:00
|
|
|
privKey: privKey.toString('hex'),
|
|
|
|
pubKey: pubKey.toString('hex')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// encode/decode functions
|
|
|
|
self.toHexString = function () {
|
|
|
|
return self.id.toString('hex')
|
|
|
|
}
|
|
|
|
|
|
|
|
self.toBytes = function () {
|
|
|
|
return self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
self.toB58String = function () {
|
|
|
|
return base58.encode(self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-14 07:32:09 +00:00
|
|
|
// unwrap the private key protobuf
|
2016-02-02 15:50:45 -08:00
|
|
|
function unmarshal (key) {
|
2016-03-03 17:31:33 +00:00
|
|
|
return messages.PrivateKey.decode(key)
|
2015-11-05 18:51:53 +00:00
|
|
|
}
|
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// create a public key protobuf to be base64 string stored in config
|
2016-02-02 15:50:45 -08:00
|
|
|
function marshal (data, type) {
|
2016-02-12 16:13:09 -08:00
|
|
|
var epb
|
|
|
|
if (type === 'Public') {
|
|
|
|
epb = messages.PublicKey.encode({
|
2016-02-02 15:50:45 -08:00
|
|
|
Type: 0,
|
|
|
|
Data: data
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
if (type === 'Private') {
|
|
|
|
epb = messages.PrivateKey.encode({
|
2016-02-02 15:50:45 -08:00
|
|
|
Type: 0,
|
|
|
|
Data: data
|
|
|
|
})
|
|
|
|
}
|
2015-07-08 14:51:49 -07:00
|
|
|
|
2016-02-02 15:50:45 -08:00
|
|
|
return epb
|
|
|
|
}
|
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// this returns a base64 encoded protobuf of the public key
|
|
|
|
function formatKey (key, type) {
|
|
|
|
// create der buffer of public key asn.1 object
|
2016-03-03 17:31:33 +00:00
|
|
|
const der = forge.asn1.toDer(key)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// create forge buffer of der public key buffer
|
2016-03-03 17:31:33 +00:00
|
|
|
const fDerBuf = forge.util.createBuffer(der.data, 'binary')
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// convert forge buffer to node buffer public key
|
2016-03-03 17:31:33 +00:00
|
|
|
const nDerBuf = new Buffer(fDerBuf.getBytes(), 'binary')
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// protobuf the new DER bytes to the PublicKey Data: field
|
2016-03-03 17:31:33 +00:00
|
|
|
const marshalKey = marshal(nDerBuf, type)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// encode the protobuf public key to base64 string
|
2016-03-03 17:31:33 +00:00
|
|
|
const b64 = marshalKey.toString('base64')
|
2016-02-10 13:55:59 -08:00
|
|
|
return b64
|
|
|
|
}
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-10 13:55:59 -08:00
|
|
|
// generation
|
|
|
|
exports.create = function () {
|
2016-02-12 16:13:09 -08:00
|
|
|
// generate keys
|
2016-03-03 17:31:33 +00:00
|
|
|
const pair = forge.rsa.generateKeyPair({ bits: 2048, e: 0x10001 })
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// return the RSA public/private key to asn1 object
|
2016-03-03 17:31:33 +00:00
|
|
|
const asnPub = forge.pki.publicKeyToAsn1(pair.publicKey)
|
|
|
|
const asnPriv = forge.pki.privateKeyToAsn1(pair.privateKey)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// format the keys to protobuf base64 encoded string
|
2016-03-03 17:31:33 +00:00
|
|
|
const protoPublic64 = formatKey(asnPub, 'Public')
|
|
|
|
const protoPrivate64 = formatKey(asnPriv, 'Private')
|
2016-02-12 14:55:05 -08:00
|
|
|
|
2016-03-10 11:25:59 -08:00
|
|
|
// store the keys as a buffer
|
|
|
|
const bufProtoPub64 = new Buffer(protoPublic64, 'base64')
|
|
|
|
const bufProtoPriv64 = new Buffer(protoPrivate64, 'base64')
|
2016-03-10 19:43:23 +00:00
|
|
|
|
2016-03-03 17:31:33 +00:00
|
|
|
const mhId = multihashing(new Buffer(protoPublic64, 'base64'), 'sha2-256')
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-03-10 11:25:59 -08:00
|
|
|
return new Id(mhId, bufProtoPriv64, bufProtoPub64)
|
2015-07-08 14:51:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.createFromHexString = function (str) {
|
2016-02-12 14:55:05 -08:00
|
|
|
return new Id(new Buffer(str, 'hex'))
|
2015-07-08 14:51:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.createFromBytes = function (buf) {
|
|
|
|
return new Id(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.createFromB58String = function (str) {
|
|
|
|
return new Id(new Buffer(base58.decode(str)))
|
|
|
|
}
|
|
|
|
|
2016-03-10 10:32:48 -08:00
|
|
|
// Public Key input will be a buffer
|
2015-07-08 14:51:49 -07:00
|
|
|
exports.createFromPubKey = function (pubKey) {
|
2016-03-03 17:31:33 +00:00
|
|
|
const buf = new Buffer(pubKey, 'base64')
|
|
|
|
const mhId = multihashing(buf, 'sha2-256')
|
2015-07-08 14:51:49 -07:00
|
|
|
return new Id(mhId, null, pubKey)
|
|
|
|
}
|
|
|
|
|
2016-03-10 10:32:48 -08:00
|
|
|
// Private key input will be a string
|
2015-11-05 18:51:53 +00:00
|
|
|
exports.createFromPrivKey = function (privKey) {
|
2016-02-12 16:13:09 -08:00
|
|
|
// create a buffer from the base64 encoded string
|
2016-03-03 17:31:33 +00:00
|
|
|
const buf = new Buffer(privKey, 'base64')
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// get the private key data from the protobuf
|
2016-03-03 17:31:33 +00:00
|
|
|
const mpk = unmarshal(buf)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// create a forge buffer
|
2016-03-03 17:31:33 +00:00
|
|
|
const fbuf = forge.util.createBuffer(mpk.Data.toString('binary'))
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// create an asn1 object from the private key bytes saved in the protobuf Data: field
|
2016-03-03 17:31:33 +00:00
|
|
|
const asnPriv = forge.asn1.fromDer(fbuf)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// get the RSA privatekey data from the asn1 object
|
2016-03-03 17:31:33 +00:00
|
|
|
const privateKey = forge.pki.privateKeyFromAsn1(asnPriv)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// set the RSA public key to the modulus and exponent of the private key
|
2016-03-03 17:31:33 +00:00
|
|
|
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// return the RSA public key to asn1 object
|
2016-03-03 17:31:33 +00:00
|
|
|
const asnPub = forge.pki.publicKeyToAsn1(publicKey)
|
2016-02-02 15:50:45 -08:00
|
|
|
|
2016-02-12 16:13:09 -08:00
|
|
|
// format the public key
|
2016-03-03 17:31:33 +00:00
|
|
|
const protoPublic64 = formatKey(asnPub, 'Public')
|
2016-03-10 10:32:48 -08:00
|
|
|
|
|
|
|
// buffer the public key for consistency before storing
|
|
|
|
const bufProtoPub64 = new Buffer(protoPublic64, 'base64')
|
2016-03-03 17:31:33 +00:00
|
|
|
const mhId = multihashing(new Buffer(protoPublic64, 'base64'), 'sha2-256')
|
2016-03-10 10:32:48 -08:00
|
|
|
return new Id(mhId, privKey, bufProtoPub64)
|
2015-07-08 14:51:49 -07:00
|
|
|
}
|