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