git ssb

1+

Dominic / ssb-keys



Tree: 10bc2f1aa2531acc90a937ee545a5c5abf197d71

Files: 10bc2f1aa2531acc90a937ee545a5c5abf197d71 / index.js

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

Built with git-ssb-web