UNPKG

2.54 kBJavaScriptView Raw
1var md5 = require('create-hash/md5')
2var rmd160 = require('ripemd160')
3var sha = require('sha.js')
4
5var checkParameters = require('./precondition')
6var defaultEncoding = require('./default-encoding')
7var Buffer = require('safe-buffer').Buffer
8var ZEROS = Buffer.alloc(128)
9var sizes = {
10 md5: 16,
11 sha1: 20,
12 sha224: 28,
13 sha256: 32,
14 sha384: 48,
15 sha512: 64,
16 rmd160: 20,
17 ripemd160: 20
18}
19function Hmac (alg, key, saltLen) {
20 var hash = getDigest(alg)
21 var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
22
23 if (key.length > blocksize) {
24 key = hash(key)
25 } else if (key.length < blocksize) {
26 key = Buffer.concat([key, ZEROS], blocksize)
27 }
28
29 var ipad = Buffer.allocUnsafe(blocksize + sizes[alg])
30 var opad = Buffer.allocUnsafe(blocksize + sizes[alg])
31 for (var i = 0; i < blocksize; i++) {
32 ipad[i] = key[i] ^ 0x36
33 opad[i] = key[i] ^ 0x5C
34 }
35
36 var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4)
37 ipad.copy(ipad1, 0, 0, blocksize)
38 this.ipad1 = ipad1
39 this.ipad2 = ipad
40 this.opad = opad
41 this.alg = alg
42 this.blocksize = blocksize
43 this.hash = hash
44 this.size = sizes[alg]
45}
46
47Hmac.prototype.run = function (data, ipad) {
48 data.copy(ipad, this.blocksize)
49 var h = this.hash(ipad)
50 h.copy(this.opad, this.blocksize)
51 return this.hash(this.opad)
52}
53
54function getDigest (alg) {
55 if (alg === 'rmd160' || alg === 'ripemd160') return rmd160
56 if (alg === 'md5') return md5
57 return shaFunc
58
59 function shaFunc (data) {
60 return sha(alg).update(data).digest()
61 }
62}
63
64module.exports = function (password, salt, iterations, keylen, digest) {
65 if (!Buffer.isBuffer(password)) password = Buffer.from(password, defaultEncoding)
66 if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, defaultEncoding)
67
68 checkParameters(iterations, keylen)
69
70 digest = digest || 'sha1'
71
72 var hmac = new Hmac(digest, password, salt.length)
73
74 var DK = Buffer.allocUnsafe(keylen)
75 var block1 = Buffer.allocUnsafe(salt.length + 4)
76 salt.copy(block1, 0, 0, salt.length)
77
78 var U, j, destPos, len
79
80 var hLen = hmac.size
81 var T = Buffer.allocUnsafe(hLen)
82 var l = Math.ceil(keylen / hLen)
83 var r = keylen - (l - 1) * hLen
84
85 for (var i = 1; i <= l; i++) {
86 block1.writeUInt32BE(i, salt.length)
87 U = hmac.run(block1, hmac.ipad1)
88
89 U.copy(T, 0, 0, hLen)
90
91 for (j = 1; j < iterations; j++) {
92 U = hmac.run(U, hmac.ipad2)
93 for (var k = 0; k < hLen; k++) T[k] ^= U[k]
94 }
95
96 destPos = (i - 1) * hLen
97 len = (i === l ? r : hLen)
98 T.copy(DK, destPos, 0, len)
99 }
100
101 return DK
102}