-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathprf.js
86 lines (61 loc) · 2.15 KB
/
prf.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
"use strict";
var crypto = require( 'crypto' );
var createPrf = function( algorithm, func ) {
var prf_func = func;
prf_func.createHash = function() { return crypto.createHash( algorithm ); };
return prf_func;
};
var hash = function( algo, text ) {
var sum = crypto.createHash( algo );
sum.update( text );
return sum.digest ();
};
var hmac_hash = function( algo, secret, text ) {
var sum = crypto.createHmac( algo, secret );
sum.update( text );
return sum.digest();
};
var p = function( hashName, secret, seed, length ) {
var hash_x = hmac_hash.bind( null, hashName );
length = length || 32;
var a = function(n) {
if( n === 0 )
return seed;
return hash_x( secret, a( n-1 ) );
};
var hashes = [];
var hashLength = 0;
for( var i = 1; hashLength < length; i++ ) {
var hashBytes = hash_x( secret, Buffer.concat([ a(i), seed ]));
hashLength += hashBytes.length;
hashes.push( hashBytes );
}
return Buffer.concat( hashes, length ).slice( 0, length );
};
var p_md5 = p.bind( null, 'md5' );
var p_sha1 = p.bind( null, 'sha1' );
var p_sha256 = p.bind( null, 'sha256' );
var prf = {};
prf[ ~0 ] = prf[ ~1 ] = createPrf( 'sha256', function( secret, label, seed, length ) {
var splitLength = Math.ceil( secret.length / 2 );
var md5Secret = secret.slice( 0, splitLength );
var shaSecret = secret.slice( secret.length - splitLength, secret.length );
var labelSeed = Buffer.concat([ new Buffer( label ), seed ]);
var md5Bytes = p_md5( md5Secret, labelSeed, length );
var shaBytes = p_sha1( shaSecret, labelSeed, length );
for( var i = 0; i < length; i++ )
md5Bytes[i] = md5Bytes[i] ^ shaBytes[i];
return md5Bytes;
});
prf[ ~2 ] = createPrf( 'sha256', function( secret, label, seed, length ) {
return p_sha256(
secret,
Buffer.concat([ new Buffer( label ), seed ]),
length );
});
module.exports = function( version ) {
if( version.major !== ~1 )
throw new Error( 'Unsupported version: ' +
[ ~version.major, ~version.minor ].join('.') );
return prf[ version.minor ];
};