-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
152 lines (133 loc) · 4.31 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
var sha256 = require('fast-sha256')
var scrypt = require('scrypt-async')
var nacl = require('tweetnacl')
var base64 = require('base64-js')
// Code inspired by:
// https://github.com/kaepora/miniLock/blob/master/src/js/miniLock.js
// https://github.com/jo/session25519
// Extracted from tweetnacl-util-js
// https://github.com/dchest/tweetnacl-util-js/blob/master/nacl-util.js#L16
function decodeUTF8 (s) {
var i, d, b
d = unescape(encodeURIComponent(s))
b = new Uint8Array(d.length)
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i)
return b
}
// Convert a decimal to hex with proper padding
// Input:
// d // A decimal number between 0-255
//
// Result:
// Returns a padded hex string representing the decimal arg
//
function decToHex (d) {
var hex = Number(d).toString(16)
while (hex.length < 2) {
hex = '0' + hex
}
return hex
}
// Convert Uint8Array of bytes to hex
// Input:
// arr // Uint8Array of bytes to convert to hex
//
// Result:
// Returns a Base16 hex encoded version of arr
//
function byteArrayToHex (arr) {
var hex, i
hex = ''
for (i = 0; i < arr.length; ++i) {
hex += decToHex(arr[i])
}
return hex
}
// Input:
// key // User key hash (Uint8Array)
// salt // Salt (username or email) (Uint8Array)
// callback function
//
// Result:
// Returns 256 bytes of scrypt derived key material in a Uint8Array,
// which is then passed to the callback.
//
function getScryptKey (key, salt, callback) {
'use strict'
scrypt(key, salt, {
N: 16384,
r: 8,
p: 1,
dkLen: 256,
encoding: 'binary'
}, function (derivedKey) {
return callback(derivedKey)
})
}
// Input:
// id // A UTF-8 username or email
// password // A UTF-8 passphrase
// callback // A callback function
//
// Result:
// An object literal with all key material
//
exports.generate = function (id, password, callback) {
'use strict'
var idSha256Bbytes, idSha256Hex, scryptKey, scryptSalt, byteKeys,
hexKeys, naclEncryptionKeyPairs, naclEncryptionKeyPairsBase64,
naclSigningKeyPairs, naclSigningKeyPairsBase64, out
idSha256Bbytes = sha256(decodeUTF8(id))
idSha256Hex = byteArrayToHex(idSha256Bbytes)
scryptKey = sha256(decodeUTF8(password))
scryptSalt = sha256(decodeUTF8([idSha256Hex, idSha256Hex.length, 'session_keys'].join('')))
getScryptKey(scryptKey, scryptSalt, function (scryptByteArray) {
try {
byteKeys = []
hexKeys = []
naclEncryptionKeyPairs = []
naclEncryptionKeyPairsBase64 = []
naclSigningKeyPairs = []
naclSigningKeyPairsBase64 = []
// Generate 8 pairs of all types of keys. The key types
// at each Array index are all derived from the same key
// bytes. Use different Array index values for each to ensure
// they don't share common key bytes. For example:
//
// uuid : output.hexKeys[0]
// encryption keypair : output.naclEncryptionKeyPairs[1]
// signing keypair : output.naclSigningKeyPairs[2]
//
var b = 0
for (var i = 0; i < 8; ++i) {
var byteArr = scryptByteArray.subarray(b, b + 32)
byteKeys.push(byteArr)
hexKeys.push(byteArrayToHex(byteArr))
var naclEncryptionKeyPair = nacl.box.keyPair.fromSecretKey(byteArr)
var naclSigningKeyPair = nacl.sign.keyPair.fromSeed(byteArr)
naclEncryptionKeyPairs.push(naclEncryptionKeyPair)
naclEncryptionKeyPairsBase64.push({
secretKey: base64.fromByteArray(naclEncryptionKeyPair.secretKey),
publicKey: base64.fromByteArray(naclEncryptionKeyPair.publicKey)
})
naclSigningKeyPairs.push(naclSigningKeyPair)
naclSigningKeyPairsBase64.push({
secretKey: base64.fromByteArray(naclSigningKeyPair.secretKey),
publicKey: base64.fromByteArray(naclSigningKeyPair.publicKey)
})
b += 32
}
out = {}
out.id = idSha256Hex
out.byteKeys = byteKeys
out.hexKeys = hexKeys
out.naclEncryptionKeyPairs = naclEncryptionKeyPairs
out.naclEncryptionKeyPairsBase64 = naclEncryptionKeyPairsBase64
out.naclSigningKeyPairs = naclSigningKeyPairs
out.naclSigningKeyPairsBase64 = naclSigningKeyPairsBase64
return callback(null, out)
} catch (err) {
return callback(err)
}
})
}