git ssb

1+

Dominic / ssb-keys



Tree: f49ed9d612208d9cfa2e456cbbdc329ddf133cdf

Files: f49ed9d612208d9cfa2e456cbbdc329ddf133cdf / index.js

4278 bytesRaw
1var fs = require('fs')
2var crypto = require('crypto')
3var ecc = require('eccjs')
4var k256 = ecc.curves.k256
5var Blake2s = require('blake2s')
6var mkdirp = require('mkdirp')
7var path = require('path')
8var curve = ecc.curves.k256
9var createHmac = require('hmac')
10
11
12function hash (data, enc) {
13 return new Blake2s().update(data, enc).digest('base64') + '.blake2s'
14}
15
16
17function isHash (data) {
18 return isString(data) && /^[A-Za-z0-9\/+]{43}=\.blake2s$/.test(data)
19}
20
21exports.isHash = isHash
22exports.hash = hash
23
24function isString(s) {
25 return 'string' === typeof s
26}
27
28function empty(v) { return !!v }
29
30function constructKeys() {
31 var privateKey = crypto.randomBytes(32)
32 var k = keysToBase64(ecc.restore(k256, privateKey))
33 k.keyfile = [
34 '# this is your SECRET name.',
35 '# this name gives you magical powers.',
36 '# with it you can mark your messages so that your friends can verify',
37 '# that they really did come from you.',
38 '#',
39 '# if any one learns this name, they can use it to destroy your identity',
40 '# NEVER show this to anyone!!!',
41 '',
42 k.private.toString('hex'),
43 '',
44 '# WARNING! It\'s vital that you DO NOT edit OR share your secret name',
45 '# instead, share your public name',
46 '# your public name: ' + k.id.toString('hex')
47 ].join('\n')
48 return k
49}
50
51
52function toBuffer(buf) {
53 if(buf == null) return buf
54 return new Buffer(buf.substring(0, buf.indexOf('.')), 'base64')
55}
56
57function keysToBase64 (keys) {
58 var pub = tag(keys.public, 'k256')
59 return {
60 public: pub,
61 private: tag(keys.private, 'k256'),
62 id: hash(pub)
63 }
64}
65
66function hashToBuffer(hash) {
67 if(!isHash(hash)) throw new Error('sign expects a hash')
68 return toBuffer(hash)
69}
70
71function keysToBuffer(key) {
72 return isString(key) ? toBuffer(key) : {
73 public: toBuffer(key.public),
74 private: toBuffer(key.private)
75 }
76}
77
78function reconstructKeys(privateKeyStr) {
79 privateKeyStr = privateKeyStr
80 .replace(/\s*\#[^\n]*/g, '')
81 .split('\n').filter(empty).join('')
82
83 var privateKey = (
84 !/\./.test(privateKeyStr)
85 ? new Buffer(privateKeyStr, 'hex')
86 : toBuffer(privateKeyStr)
87 )
88
89 return keysToBase64(ecc.restore(k256, privateKey))
90}
91
92function tag (key, tag) {
93 return key.toString('base64')+'.' + tag.replace(/^\./, '')
94}
95
96exports.load = function(namefile, cb) {
97 fs.readFile(namefile, 'ascii', function(err, privateKeyStr) {
98 if (err) return cb(err)
99 try { cb(null, reconstructKeys(privateKeyStr)) }
100 catch (e) { cb(err) }
101 })
102}
103
104exports.loadSync = function(namefile) {
105 return reconstructKeys(fs.readFileSync(namefile, 'ascii'))
106}
107
108exports.create = function(namefile, cb) {
109 var k = constructKeys()
110 mkdirp(path.dirname(namefile), function (err) {
111 if(err) return cb(err)
112 fs.writeFile(namefile, k.keyfile, function(err) {
113 if (err) return cb(err)
114 delete k.keyfile
115 cb(null, k)
116 })
117 })
118}
119
120exports.createSync = function(namefile) {
121 var k = constructKeys()
122 mkdirp.sync(path.dirname(namefile))
123 fs.writeFileSync(namefile, k.keyfile)
124 delete k.keyfile
125 return k
126}
127
128exports.loadOrCreate = function (namefile, cb) {
129 exports.load(namefile, function (err, keys) {
130 if(!err) return cb(null, keys)
131 exports.create(namefile, cb)
132 })
133}
134exports.loadOrCreateSync = function (namefile) {
135 try {
136 return exports.loadSync(namefile)
137 } catch (err) {
138 return exports.createSync(namefile)
139 }
140}
141
142//this should return a key pair:
143// {public: Buffer, private: Buffer}
144
145exports.generate = function () {
146 return keysToBase64(ecc.restore(curve, crypto.randomBytes(32)))
147}
148
149//takes a public key and a hash and returns a signature.
150//(a signature must be a node buffer)
151exports.sign = function (keys, hash) {
152 var hashTag = hash.substring(hash.indexOf('.'))
153 return tag(
154 ecc.sign(curve, keysToBuffer(keys), hashToBuffer(hash)),
155 hashTag + '.k256'
156 )
157}
158
159//takes a public key, signature, and a hash
160//and returns true if the signature was valid.
161exports.verify = function (pub, sig, hash) {
162 return ecc.verify(curve, keysToBuffer(pub), toBuffer(sig), hashToBuffer(hash))
163}
164
165function createHash() {
166 return new Blake2s()
167}
168
169exports.hmac = function (data, key) {
170 return createHmac(createHash, 64, key)
171 .update(data).digest('base64')+'.blake2s.hmac'
172}
173
174

Built with git-ssb-web