2016-12-23 08:52:40 -05:00
|
|
|
'use strict'
|
|
|
|
|
|
|
|
const multihashing = require('multihashing-async')
|
|
|
|
const protobuf = require('protocol-buffers')
|
2017-01-16 05:17:50 +01:00
|
|
|
const Buffer = require('safe-buffer').Buffer
|
2016-12-23 08:52:40 -05:00
|
|
|
|
|
|
|
const crypto = require('../crypto').ed25519
|
|
|
|
const pbm = protobuf(require('../crypto.proto'))
|
|
|
|
|
|
|
|
class Ed25519PublicKey {
|
|
|
|
constructor (key) {
|
|
|
|
this._key = ensureKey(key, crypto.publicKeyLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
verify (data, sig, callback) {
|
|
|
|
ensure(callback)
|
|
|
|
crypto.hashAndVerify(this._key, sig, data, callback)
|
|
|
|
}
|
|
|
|
|
|
|
|
marshal () {
|
|
|
|
return Buffer.from(this._key)
|
|
|
|
}
|
|
|
|
|
|
|
|
get bytes () {
|
|
|
|
return pbm.PublicKey.encode({
|
|
|
|
Type: pbm.KeyType.Ed25519,
|
|
|
|
Data: this.marshal()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
equals (key) {
|
|
|
|
return this.bytes.equals(key.bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
hash (callback) {
|
|
|
|
ensure(callback)
|
|
|
|
multihashing(this.bytes, 'sha2-256', callback)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Ed25519PrivateKey {
|
|
|
|
// key - 64 byte Uint8Array or Buffer containing private key
|
|
|
|
// publicKey - 32 byte Uint8Array or Buffer containing public key
|
|
|
|
constructor (key, publicKey) {
|
|
|
|
this._key = ensureKey(key, crypto.privateKeyLength)
|
|
|
|
this._publicKey = ensureKey(publicKey, crypto.publicKeyLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
sign (message, callback) {
|
|
|
|
ensure(callback)
|
|
|
|
crypto.hashAndSign(this._key, message, callback)
|
|
|
|
}
|
|
|
|
|
|
|
|
get public () {
|
|
|
|
if (!this._publicKey) {
|
|
|
|
throw new Error('public key not provided')
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Ed25519PublicKey(this._publicKey)
|
|
|
|
}
|
|
|
|
|
|
|
|
marshal () {
|
|
|
|
return Buffer.concat([Buffer.from(this._key), Buffer.from(this._publicKey)])
|
|
|
|
}
|
|
|
|
|
|
|
|
get bytes () {
|
|
|
|
return pbm.PrivateKey.encode({
|
|
|
|
Type: pbm.KeyType.Ed25519,
|
|
|
|
Data: this.marshal()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
equals (key) {
|
|
|
|
return this.bytes.equals(key.bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
hash (callback) {
|
|
|
|
ensure(callback)
|
|
|
|
multihashing(this.bytes, 'sha2-256', callback)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function unmarshalEd25519PrivateKey (bytes, callback) {
|
|
|
|
try {
|
|
|
|
bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength)
|
|
|
|
} catch (err) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
|
|
|
|
const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length)
|
|
|
|
callback(null, new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes))
|
|
|
|
}
|
|
|
|
|
|
|
|
function unmarshalEd25519PublicKey (bytes) {
|
|
|
|
bytes = ensureKey(bytes, crypto.publicKeyLength)
|
|
|
|
return new Ed25519PublicKey(bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
function generateKeyPair (_bits, cb) {
|
|
|
|
if (cb === undefined && typeof _bits === 'function') {
|
|
|
|
cb = _bits
|
|
|
|
}
|
|
|
|
|
|
|
|
crypto.generateKey((err, keys) => {
|
|
|
|
if (err) {
|
|
|
|
return cb(err)
|
|
|
|
}
|
|
|
|
let privkey
|
|
|
|
try {
|
|
|
|
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
|
|
|
} catch (err) {
|
|
|
|
cb(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cb(null, privkey)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-03 20:38:51 +00:00
|
|
|
function generateKeyPairFromSeed (seed, _bits, cb) {
|
|
|
|
if (cb === undefined && typeof _bits === 'function') {
|
|
|
|
cb = _bits
|
|
|
|
}
|
|
|
|
|
|
|
|
crypto.generateKeyFromSeed(seed, (err, keys) => {
|
|
|
|
if (err) {
|
|
|
|
return cb(err)
|
|
|
|
}
|
|
|
|
let privkey
|
|
|
|
try {
|
|
|
|
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
|
|
|
} catch (err) {
|
|
|
|
cb(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cb(null, privkey)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-23 08:52:40 -05:00
|
|
|
function ensure (cb) {
|
|
|
|
if (typeof cb !== 'function') {
|
|
|
|
throw new Error('callback is required')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function ensureKey (key, length) {
|
|
|
|
if (Buffer.isBuffer(key)) {
|
|
|
|
key = new Uint8Array(key)
|
|
|
|
}
|
|
|
|
if (!(key instanceof Uint8Array) || key.length !== length) {
|
|
|
|
throw new Error('Key must be a Uint8Array or Buffer of length ' + length)
|
|
|
|
}
|
|
|
|
return key
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
Ed25519PublicKey,
|
|
|
|
Ed25519PrivateKey,
|
|
|
|
unmarshalEd25519PrivateKey,
|
|
|
|
unmarshalEd25519PublicKey,
|
2017-03-03 20:38:51 +00:00
|
|
|
generateKeyPair,
|
|
|
|
generateKeyPairFromSeed
|
2016-12-23 08:52:40 -05:00
|
|
|
}
|