git ssb

1+

Dominic / ssb-keys



Tree: 89171dfc684b68a1ec0741e78b5c882a9e2be86a

Files: 89171dfc684b68a1ec0741e78b5c882a9e2be86a / index.js

3619 bytesRaw
1var sodium = require('chloride')
2
3var pb = require('private-box')
4
5var u = require('./util')
6
7var isBuffer = Buffer.isBuffer
8
9//UTILS
10
11function clone (obj) {
12 var _obj = {}
13 for(var k in obj) {
14 if(Object.hasOwnProperty.call(obj, k))
15 _obj[k] = obj[k]
16 }
17 return _obj
18}
19
20var hmac = sodium.crypto_auth
21
22exports.hash = u.hash
23
24exports.getTag = u.getTag
25
26function isObject (o) {
27 return 'object' === typeof o
28}
29
30function isFunction (f) {
31 return 'function' === typeof f
32}
33
34function isString(s) {
35 return 'string' === typeof s
36}
37
38var curves = {}
39curves.ed25519 = require('./sodium')
40
41function getCurve(keys) {
42 var curve = keys.curve
43
44 if(!keys.curve && isString(keys.public))
45 keys = keys.public
46
47 if(!curve && isString(keys))
48 curve = u.getTag(keys)
49
50 if(!curves[curve]) {
51 throw new Error(
52 'unkown curve:' + curve +
53 ' expected: '+Object.keys(curves)
54 )
55 }
56
57 return curve
58}
59
60//this should return a key pair:
61// {curve: curve, public: Buffer, private: Buffer}
62
63exports.generate = function (curve, seed) {
64 curve = curve || 'ed25519'
65
66 if(!curves[curve])
67 throw new Error('unknown curve:'+curve)
68
69 return u.keysToJSON(curves[curve].generate(seed), curve)
70}
71
72//import functions for loading/saving keys from storage
73var storage = require('./storage')(exports.generate)
74for(var key in storage) exports[key] = storage[key]
75
76
77exports.loadOrCreate = function (filename, cb) {
78 exports.load(filename, function (err, keys) {
79 if(!err) return cb(null, keys)
80 exports.create(filename, cb)
81 })
82}
83
84exports.loadOrCreateSync = function (filename) {
85 try {
86 return exports.loadSync(filename)
87 } catch (err) {
88 return exports.createSync(filename)
89 }
90}
91
92
93//takes a public key and a hash and returns a signature.
94//(a signature must be a node buffer)
95
96function sign (keys, msg) {
97 if(isString(msg))
98 msg = new Buffer(msg)
99 if(!isBuffer(msg))
100 throw new Error('msg should be buffer')
101 var curve = getCurve(keys)
102
103 return curves[curve]
104 .sign(u.toBuffer(keys.private || keys), msg)
105 .toString('base64')+'.sig.'+curve
106
107}
108
109//takes a public key, signature, and a hash
110//and returns true if the signature was valid.
111function verify (keys, sig, msg) {
112 if(isObject(sig))
113 throw new Error('signature should be base64 string, did you mean verifyObj(public, signed_obj)')
114 return curves[getCurve(keys)].verify(
115 u.toBuffer(keys.public || keys),
116 u.toBuffer(sig),
117 isBuffer(msg) ? msg : new Buffer(msg)
118 )
119}
120
121// OTHER CRYTPO FUNCTIONS
122
123exports.signObj = function (keys, hmac_key, obj) {
124 if(!obj) obj = hmac_key, hmac_key = null
125 var _obj = clone(obj)
126 var b = new Buffer(JSON.stringify(_obj, null, 2))
127 if(hmac_key) b = hmac(b, hmac_key)
128 _obj.signature = sign(keys, b)
129 return _obj
130}
131
132exports.verifyObj = function (keys, hmac_key, obj) {
133 if(!obj) obj = hmac_key, hmac_key = null
134 obj = clone(obj)
135 var sig = obj.signature
136 delete obj.signature
137 var b = new Buffer(JSON.stringify(obj, null, 2))
138 if(hmac_key) b = hmac(b, hmac_key)
139 return verify(keys, sig, b)
140}
141
142exports.box = function (msg, recipients) {
143 msg = new Buffer(JSON.stringify(msg))
144
145 recipients = recipients.map(function (keys) {
146 var public = keys.public || keys
147 return sodium.crypto_sign_ed25519_pk_to_curve25519(u.toBuffer(public))
148 })
149
150 return pb.multibox(msg, recipients).toString('base64')+'.box'
151}
152
153exports.unbox = function (boxed, keys) {
154 boxed = u.toBuffer(boxed)
155 var sk = sodium.crypto_sign_ed25519_sk_to_curve25519(u.toBuffer(keys.private || keys))
156
157 var msg = pb.multibox_open(boxed, sk)
158 if(msg) return JSON.parse(''+msg)
159}
160

Built with git-ssb-web