forked from bcoin-org/bcrypto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsafe.js
136 lines (107 loc) · 2.75 KB
/
safe.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
/*!
* safe.js - constant-time equals for bcrypto
* Copyright (c) 2016-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on golang/go:
* Copyright (c) 2009 The Go Authors. All rights reserved.
* https://github.com/golang/go
*
* Resources:
* https://github.com/golang/go/blob/master/src/crypto/subtle/constant_time.go
*/
'use strict';
const assert = require('./internal/assert');
/*
* Safe
*/
function safeCompare(x, y) {
assert(Buffer.isBuffer(x));
assert(Buffer.isBuffer(y));
if (safeEqualInt(x.length, 0))
return safeEqualInt(y.length, 0);
// Assumes `y` is the "constant size"
// parameter. Note that constant size
// doesn't necessarily mean secret.
// Assuming we have a constant-size
// secret key or passphrase. This
// function should be called as:
//
// if (!safeCompare(input, key))
// throw new Error('Bad passphrase.');
let v = x.length ^ y.length;
for (let i = 0; i < y.length; i++)
v |= x[i % x.length] ^ y[i];
return (v - 1) >>> 31;
}
function safeEqual(x, y) {
assert(Buffer.isBuffer(x));
assert(Buffer.isBuffer(y));
// Assumes the lengths of both
// `x` and `y` are not secret.
if (!safeEqualInt(x.length, y.length))
return 0;
let v = 0;
for (let i = 0; i < x.length; i++)
v |= x[i] ^ y[i];
return (v - 1) >>> 31;
}
function safeEqualByte(x, y) {
return safeEqualInt(x & 0xff, y & 0xff);
}
function safeEqualInt(x, y) {
return ((x ^ y) - 1) >>> 31;
}
function safeSelect(x, y, v) {
return (x & (v - 1)) | (y & ~(v - 1));
}
function safeLT(x, y) {
return (x - y) >>> 31;
}
function safeLTE(x, y) {
return (x - y - 1) >>> 31;
}
function safeGT(x, y) {
return (y - x) >>> 31;
}
function safeGTE(x, y) {
return (y - x - 1) >>> 31;
}
function safeMin(x, y) {
return safeSelect(x, y, safeLT(y, x));
}
function safeMax(x, y) {
return safeSelect(x, y, safeGT(y, x));
}
function safeAbs(x) {
return (x | 0) * ((x >> 31) | 1);
}
function safeBool(x) {
return ((x >> 31) | (-x >> 31)) & 1;
}
function safeCopy(x, y, v) {
assert(Buffer.isBuffer(x));
assert(Buffer.isBuffer(y));
assert(safeEqualInt(x.length, y.length));
const xmask = (v - 1) & 0xff;
const ymask = ~(v - 1) & 0xff;
for (let i = 0; i < x.length; i++)
x[i] = (x[i] & xmask) | (y[i] & ymask);
}
/*
* Expose
*/
exports.safeCompare = safeCompare;
exports.safeEqual = safeEqual;
exports.safeEqualByte = safeEqualByte;
exports.safeEqualInt = safeEqualInt;
exports.safeSelect = safeSelect;
exports.safeLT = safeLT;
exports.safeLTE = safeLTE;
exports.safeGT = safeGT;
exports.safeGTE = safeGTE;
exports.safeMin = safeMin;
exports.safeMax = safeMax;
exports.safeAbs = safeAbs;
exports.safeBool = safeBool;
exports.safeCopy = safeCopy;