UNPKG

10.9 kBJavaScriptView Raw
1/*!
2 * Copyright 2016 Amazon.com,
3 * Inc. or its affiliates. All Rights Reserved.
4 *
5 * Licensed under the Amazon Software License (the "License").
6 * You may not use this file except in compliance with the
7 * License. A copy of the License is located at
8 *
9 * http://aws.amazon.com/asl/
10 *
11 * or in the "license" file accompanying this file. This file is
12 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13 * CONDITIONS OF ANY KIND, express or implied. See the License
14 * for the specific language governing permissions and
15 * limitations under the License.
16 */
17import { Buffer } from 'buffer';
18import CryptoJS from 'crypto-js/core';
19import 'crypto-js/lib-typedarrays'; // necessary for crypto js
20
21import SHA256 from 'crypto-js/sha256';
22import HmacSHA256 from 'crypto-js/hmac-sha256';
23
24var randomBytes = function randomBytes(nBytes) {
25 return Buffer.from(CryptoJS.lib.WordArray.random(nBytes).toString(), 'hex');
26};
27
28import BigInteger from './BigInteger';
29var initN = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1' + '29024E088A67CC74020BBEA63B139B22514A08798E3404DD' + 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245' + 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D' + 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F' + '83655D23DCA3AD961C62F356208552BB9ED529077096966D' + '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' + 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9' + 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510' + '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64' + 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' + 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B' + 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C' + 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31' + '43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';
30var newPasswordRequiredChallengeUserAttributePrefix = 'userAttributes.';
31/** @class */
32
33var AuthenticationHelper = /*#__PURE__*/function () {
34 /**
35 * Constructs a new AuthenticationHelper object
36 * @param {string} PoolName Cognito user pool name.
37 */
38 function AuthenticationHelper(PoolName) {
39 this.N = new BigInteger(initN, 16);
40 this.g = new BigInteger('2', 16);
41 this.k = new BigInteger(this.hexHash("00" + this.N.toString(16) + "0" + this.g.toString(16)), 16);
42 this.smallAValue = this.generateRandomSmallA();
43 this.getLargeAValue(function () {});
44 this.infoBits = Buffer.from('Caldera Derived Key', 'utf8');
45 this.poolName = PoolName;
46 }
47 /**
48 * @returns {BigInteger} small A, a random number
49 */
50
51
52 var _proto = AuthenticationHelper.prototype;
53
54 _proto.getSmallAValue = function getSmallAValue() {
55 return this.smallAValue;
56 }
57 /**
58 * @param {nodeCallback<BigInteger>} callback Called with (err, largeAValue)
59 * @returns {void}
60 */
61 ;
62
63 _proto.getLargeAValue = function getLargeAValue(callback) {
64 var _this = this;
65
66 if (this.largeAValue) {
67 callback(null, this.largeAValue);
68 } else {
69 this.calculateA(this.smallAValue, function (err, largeAValue) {
70 if (err) {
71 callback(err, null);
72 }
73
74 _this.largeAValue = largeAValue;
75 callback(null, _this.largeAValue);
76 });
77 }
78 }
79 /**
80 * helper function to generate a random big integer
81 * @returns {BigInteger} a random value.
82 * @private
83 */
84 ;
85
86 _proto.generateRandomSmallA = function generateRandomSmallA() {
87 var hexRandom = randomBytes(128).toString('hex');
88 var randomBigInt = new BigInteger(hexRandom, 16);
89 var smallABigInt = randomBigInt.mod(this.N);
90 return smallABigInt;
91 }
92 /**
93 * helper function to generate a random string
94 * @returns {string} a random value.
95 * @private
96 */
97 ;
98
99 _proto.generateRandomString = function generateRandomString() {
100 return randomBytes(40).toString('base64');
101 }
102 /**
103 * @returns {string} Generated random value included in password hash.
104 */
105 ;
106
107 _proto.getRandomPassword = function getRandomPassword() {
108 return this.randomPassword;
109 }
110 /**
111 * @returns {string} Generated random value included in devices hash.
112 */
113 ;
114
115 _proto.getSaltDevices = function getSaltDevices() {
116 return this.SaltToHashDevices;
117 }
118 /**
119 * @returns {string} Value used to verify devices.
120 */
121 ;
122
123 _proto.getVerifierDevices = function getVerifierDevices() {
124 return this.verifierDevices;
125 }
126 /**
127 * Generate salts and compute verifier.
128 * @param {string} deviceGroupKey Devices to generate verifier for.
129 * @param {string} username User to generate verifier for.
130 * @param {nodeCallback<null>} callback Called with (err, null)
131 * @returns {void}
132 */
133 ;
134
135 _proto.generateHashDevice = function generateHashDevice(deviceGroupKey, username, callback) {
136 var _this2 = this;
137
138 this.randomPassword = this.generateRandomString();
139 var combinedString = "" + deviceGroupKey + username + ":" + this.randomPassword;
140 var hashedString = this.hash(combinedString);
141 var hexRandom = randomBytes(16).toString('hex');
142 this.SaltToHashDevices = this.padHex(new BigInteger(hexRandom, 16));
143 this.g.modPow(new BigInteger(this.hexHash(this.SaltToHashDevices + hashedString), 16), this.N, function (err, verifierDevicesNotPadded) {
144 if (err) {
145 callback(err, null);
146 }
147
148 _this2.verifierDevices = _this2.padHex(verifierDevicesNotPadded);
149 callback(null, null);
150 });
151 }
152 /**
153 * Calculate the client's public value A = g^a%N
154 * with the generated random number a
155 * @param {BigInteger} a Randomly generated small A.
156 * @param {nodeCallback<BigInteger>} callback Called with (err, largeAValue)
157 * @returns {void}
158 * @private
159 */
160 ;
161
162 _proto.calculateA = function calculateA(a, callback) {
163 var _this3 = this;
164
165 this.g.modPow(a, this.N, function (err, A) {
166 if (err) {
167 callback(err, null);
168 }
169
170 if (A.mod(_this3.N).equals(BigInteger.ZERO)) {
171 callback(new Error('Illegal paramater. A mod N cannot be 0.'), null);
172 }
173
174 callback(null, A);
175 });
176 }
177 /**
178 * Calculate the client's value U which is the hash of A and B
179 * @param {BigInteger} A Large A value.
180 * @param {BigInteger} B Server B value.
181 * @returns {BigInteger} Computed U value.
182 * @private
183 */
184 ;
185
186 _proto.calculateU = function calculateU(A, B) {
187 this.UHexHash = this.hexHash(this.padHex(A) + this.padHex(B));
188 var finalU = new BigInteger(this.UHexHash, 16);
189 return finalU;
190 }
191 /**
192 * Calculate a hash from a bitArray
193 * @param {Buffer} buf Value to hash.
194 * @returns {String} Hex-encoded hash.
195 * @private
196 */
197 ;
198
199 _proto.hash = function hash(buf) {
200 var str = buf instanceof Buffer ? CryptoJS.lib.WordArray.create(buf) : buf;
201 var hashHex = SHA256(str).toString();
202 return new Array(64 - hashHex.length).join('0') + hashHex;
203 }
204 /**
205 * Calculate a hash from a hex string
206 * @param {String} hexStr Value to hash.
207 * @returns {String} Hex-encoded hash.
208 * @private
209 */
210 ;
211
212 _proto.hexHash = function hexHash(hexStr) {
213 return this.hash(Buffer.from(hexStr, 'hex'));
214 }
215 /**
216 * Standard hkdf algorithm
217 * @param {Buffer} ikm Input key material.
218 * @param {Buffer} salt Salt value.
219 * @returns {Buffer} Strong key material.
220 * @private
221 */
222 ;
223
224 _proto.computehkdf = function computehkdf(ikm, salt) {
225 var infoBitsWordArray = CryptoJS.lib.WordArray.create(Buffer.concat([this.infoBits, Buffer.from(String.fromCharCode(1), 'utf8')]));
226 var ikmWordArray = ikm instanceof Buffer ? CryptoJS.lib.WordArray.create(ikm) : ikm;
227 var saltWordArray = salt instanceof Buffer ? CryptoJS.lib.WordArray.create(salt) : salt;
228 var prk = HmacSHA256(ikmWordArray, saltWordArray);
229 var hmac = HmacSHA256(infoBitsWordArray, prk);
230 return Buffer.from(hmac.toString(), 'hex').slice(0, 16);
231 }
232 /**
233 * Calculates the final hkdf based on computed S value, and computed U value and the key
234 * @param {String} username Username.
235 * @param {String} password Password.
236 * @param {BigInteger} serverBValue Server B value.
237 * @param {BigInteger} salt Generated salt.
238 * @param {nodeCallback<Buffer>} callback Called with (err, hkdfValue)
239 * @returns {void}
240 */
241 ;
242
243 _proto.getPasswordAuthenticationKey = function getPasswordAuthenticationKey(username, password, serverBValue, salt, callback) {
244 var _this4 = this;
245
246 if (serverBValue.mod(this.N).equals(BigInteger.ZERO)) {
247 throw new Error('B cannot be zero.');
248 }
249
250 this.UValue = this.calculateU(this.largeAValue, serverBValue);
251
252 if (this.UValue.equals(BigInteger.ZERO)) {
253 throw new Error('U cannot be zero.');
254 }
255
256 var usernamePassword = "" + this.poolName + username + ":" + password;
257 var usernamePasswordHash = this.hash(usernamePassword);
258 var xValue = new BigInteger(this.hexHash(this.padHex(salt) + usernamePasswordHash), 16);
259 this.calculateS(xValue, serverBValue, function (err, sValue) {
260 if (err) {
261 callback(err, null);
262 }
263
264 var hkdf = _this4.computehkdf(Buffer.from(_this4.padHex(sValue), 'hex'), Buffer.from(_this4.padHex(_this4.UValue.toString(16)), 'hex'));
265
266 callback(null, hkdf);
267 });
268 }
269 /**
270 * Calculates the S value used in getPasswordAuthenticationKey
271 * @param {BigInteger} xValue Salted password hash value.
272 * @param {BigInteger} serverBValue Server B value.
273 * @param {nodeCallback<string>} callback Called on success or error.
274 * @returns {void}
275 */
276 ;
277
278 _proto.calculateS = function calculateS(xValue, serverBValue, callback) {
279 var _this5 = this;
280
281 this.g.modPow(xValue, this.N, function (err, gModPowXN) {
282 if (err) {
283 callback(err, null);
284 }
285
286 var intValue2 = serverBValue.subtract(_this5.k.multiply(gModPowXN));
287 intValue2.modPow(_this5.smallAValue.add(_this5.UValue.multiply(xValue)), _this5.N, function (err2, result) {
288 if (err2) {
289 callback(err2, null);
290 }
291
292 callback(null, result.mod(_this5.N));
293 });
294 });
295 }
296 /**
297 * Return constant newPasswordRequiredChallengeUserAttributePrefix
298 * @return {newPasswordRequiredChallengeUserAttributePrefix} constant prefix value
299 */
300 ;
301
302 _proto.getNewPasswordRequiredChallengeUserAttributePrefix = function getNewPasswordRequiredChallengeUserAttributePrefix() {
303 return newPasswordRequiredChallengeUserAttributePrefix;
304 }
305 /**
306 * Converts a BigInteger (or hex string) to hex format padded with zeroes for hashing
307 * @param {BigInteger|String} bigInt Number or string to pad.
308 * @returns {String} Padded hex string.
309 */
310 ;
311
312 _proto.padHex = function padHex(bigInt) {
313 var hashStr = bigInt.toString(16);
314
315 if (hashStr.length % 2 === 1) {
316 hashStr = "0" + hashStr;
317 } else if ('89ABCDEFabcdef'.indexOf(hashStr[0]) !== -1) {
318 hashStr = "00" + hashStr;
319 }
320
321 return hashStr;
322 };
323
324 return AuthenticationHelper;
325}();
326
327export { AuthenticationHelper as default };
\No newline at end of file