-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.js
100 lines (97 loc) · 2.84 KB
/
auth.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
var crypto = require('./crypto')
var Int64 = require('./Int64')
var assert = require('assert')
function memcmp(a, b) {
if (a.length != b.length) return false
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false
}
return true
}
module.exports.makeUserAuth = function(myboxing, theirboxing) {
var nonce = crypto.random_nonce()
var boxed_S = crypto.boxWithKeys(theirboxing, nonce,
theirboxing, myboxing.private)
return Buffer.concat([nonce, boxed_S])
}
module.exports.verifyUserAuth = function(msg, myboxing, theirboxing) {
var nonce = msg.slice(0, 24), unboxed_S
try {
unboxed_S = crypto.unboxWithKeys(msg.slice(24), nonce, theirboxing, myboxing.private)
} catch(e) {
return false
}
return memcmp(unboxed_S, myboxing.public)
}
module.exports.makePuzzle = function(serverKey, clientKey, k, TID, w) {
var p = module.exports.makePuzzleDecoded(serverKey, clientKey, k, TID, w)
return Buffer.concat([p[0], p[1], new Buffer([p[2]]), p[3].getBuffer()])
}
module.exports.makePuzzleDecoded = function(serverKey, clientKey, k, TID, w) {
var n = new Int64(Date.now())
var nonce = crypto.make_nonce(TID, n)
var r = crypto.secretBox(Buffer.concat([serverKey, clientKey]), nonce, k)
var q = new Buffer(r)
// zero the rightmost w bits
//q[q.length - 1] = (q[q.length - 1] >> w) << w
zero_bits(q, w, 0)
var H_r = crypto.hashPuzzle(r)
return [q, H_r, w, n]
}
module.exports.checkPuzzleDecoded = function(serverKey, clientKey, k, TID, r, n_) {
if (Date.now() - n_ > 3e5) {
// too long in the past
return false
}
var nonce = crypto.make_nonce(TID, n_)
var r_unb
try {
r_unb = crypto.secretUnbox(r, nonce, k)
} catch(e) {
return false
}
if (r_unb.length != 64) return false
var S_ = r_unb.slice(0, 32)
var C_ = r_unb.slice(32, 64)
if (!memcmp(C_, clientKey) || !memcmp(S_, serverKey)) {
return false
}
return true
}
module.exports.checkPuzzle = function(serverKey, clientKey, k, TID, puzzleResp) {
var r = puzzleResp.slice(0, puzzleResp.length - 8)
var n_ = new Int64(puzzleResp, puzzleResp.length - 8)
return module.exports.checkPuzzleDecoded(serverKey, clientKey, k, TID, r, n_)
}
module.exports.solvePuzzle = function(TID, puzzle) {
if (puzzle.length != 121) return null
// puzzles should be 121 bytes, really
var q = puzzle.slice(0, 80)
var H_r = puzzle.slice(80, 112)
var w = puzzle[112]
var n_ = new Int64(puzzle, 113)
return Buffer.concat([
module.exports.solvePuzzleDecoded(TID, q, H_r, w, n_),
n_.getBuffer()])
}
module.exports.solvePuzzleDecoded = function(TID, q, H_r, w, n_) {
for(var x = 0; x < Math.pow(2, w); x++) {
zero_bits(q, w, x)
if (memcmp(crypto.hashPuzzle(q), H_r)) {
return q
}
}
// not found for some reason
return null
}
function zero_bits(b, w, add) {
var o = b.length - 1
if (!add) add = 0
while(w >= 8) {
b[o] = add & 0xFF
add >>= 8
w -= 8
o--
}
b[o] = ((b[o] >> w) << w) | (add & 0xFF)
}