Vydané zdroje
Stáhnout zdroje ZIP
CH-J Server Manager
Procházejte adresáře a soubory konkrétního vydání aplikace.
Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.
1
/**2
* (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.3
*4
* An implementation of the Tiger hash function. It specifically5
* supports the original PHP implementation that swapped byte order6
* (endianness) of the resulting digest to keep backwards7
* compatibility:8
* https://github.com/facebook/hhvm/blob/281303d/hphp/runtime/ext/hash/ext_hash.cpp#L94-L979
*10
* More on the Tiger algorithm:11
* https://www.cs.technion.ac.il/~biham/Reports/Tiger/tiger/node3.html12
* https://www.cl.cam.ac.uk/~rja14/Papers/tiger.pdf13
* https://www.cl.cam.ac.uk/~rja14/Papers/tigersb.pdf14
*15
* Implementation in C:16
* https://www.cs.technion.ac.il/~biham/Reports/Tiger/tiger/node7.html17
*18
* @emails oncall+i18n_fbt_js19
* Flow does not support BigInt yet20
*21
* @noflow22
*/24
/* eslint-disable no-bitwise */25
/* global BigInt */27
'use strict';29
const {t1, t2, t3, t4} = require('./TigerTables');31
const uint = BigInt.asUintN.bind(BigInt, 64);32
const U64 = 0xffffffffffffffffn;34
// Turn a buffer into a Tiger-padded array of 64-bit words35
function _getMessage(buffer /*: Buffer*/) /*: Array<BigInt>*/ {36
const words = [];37
let word = 0n;38
let byteLen = 0n;39
for (const c of buffer) {40
const b = byteLen++ & 0x7n;41
word |= BigInt(c) << (b << 3n);42
if (byteLen % 8n == 0n) {43
words.push(word);44
word = 0n;45
}46
}47
// Store original size (in bits)48
const bitSize = (byteLen << 3n) & U64;50
// Pad our message with a byte of 0x1 ala MD4 (Tiger1) padding51
const b = byteLen & 0x7n;52
if (b) {53
word |= 0x1n << (b << 3n);54
words.push(word);55
byteLen += 8n - b;56
} else {57
words.push(0x1n);58
byteLen += 8n;59
}61
for (byteLen %= 64n; byteLen < 56n; byteLen += 8n) {62
words.push(0n);63
}64
words.push(bitSize);65
return words;66
}68
// BigInt.toString will naturally elide leading zero's. Add them back69
const ZERO_FILL = '000000000000000';70
function _zeroFill(n /*: {value: BigInt}*/) {71
const str = n.value.toString(16);72
return ZERO_FILL.substr(0, 16 - str.length) + str;73
}75
// The registers a, b, c concatenated as a string yield the inverted byte order.76
// Reverse the byte order of the concatenated digest string with an inversion77
// lookup.78
// prettier-ignore79
const inversion = [80
14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1,81
30, 31, 28, 29, 26, 27, 24, 25, 22, 23, 20, 21, 18, 19, 16, 17,82
46, 47, 44, 45, 42, 43, 40, 41, 38, 39, 36, 37, 34, 35, 32, 3383
];85
class Tiger {86
constructor(87
digestBitLen /*: number*/, // 128, 160, 19288
// For additional passes after the first 3. For 'Tiger,4' we'd pass 1 here89
extraPasses /*: number*/ = 0,90
// PHP originally had the final byte-order of the digest inverted. If this91
// old behavior is desired, set this to true.92
invertByte /*: boolean*/ = false,93
// Encoding to which to convert JS's internal string before hashing.94
// Defaults to encoding the string to UTF-8. To use the string as the95
// native UTF-16, pass Tiger.UTF16 = 'utf16le'.96
encoding /*: string*/ = Tiger.UTF8,97
) {98
this._digestBitLen = digestBitLen;99
this._extraPasses = extraPasses;100
this._invertByte = invertByte;101
this._encoding = encoding;102
}104
// The use of uint(...) and & U64 here are to ensure we maintain unsigned105
// 64-bit behavior. We're ensuring BigInt's implementation doesn't exceed 64106
// bits (when multiplying, adding, or shifting left) and doesn't go negative107
// (when subtracting). Negative numbers aren't a problem for bitwise & and |108
// operations, but BigInt will 1-fill the most-significant bits when shifting109
// right, whereas an unsigned word would have 0-filled.110
_keySchedule() {111
this._x0 = uint(this._x0 - (this._x7 ^ 0xa5a5a5a5a5a5a5a5n));112
this._x1 ^= this._x0;113
this._x2 = (this._x2 + this._x1) & U64;114
this._x3 = uint(this._x3 - (this._x2 ^ ((~this._x1 << 19n) & U64)));115
this._x4 ^= this._x3;116
this._x5 = (this._x5 + this._x4) & U64;117
this._x6 = uint(this._x6 - (this._x5 ^ (uint(~this._x4) >> 23n)));118
this._x7 ^= this._x6;119
this._x0 = (this._x0 + this._x7) & U64;120
this._x1 = uint(this._x1 - (this._x0 ^ (~this._x7 << 19n)));121
this._x2 ^= this._x1;122
this._x3 = (this._x3 + this._x2) & U64;123
this._x4 = uint(this._x4 - (this._x3 ^ (uint(~this._x2) >> 23n)));124
this._x5 ^= this._x4;125
this._x6 = (this._x6 + this._x5) & U64;126
this._x7 = uint(this._x7 - (this._x6 ^ 0x0123456789abcdefn));127
}129
_save() {130
this._aa = this._a.value;131
this._bb = this._b.value;132
this._cc = this._c.value;133
}135
_feedforward() {136
this._a.value ^= this._aa;137
this._b.value = uint(this._b.value - this._bb);138
this._c.value = (this._c.value + this._cc) & U64;139
}141
_compress() {142
this._save();143
this._pass(this._a, this._b, this._c, 5n);144
this._keySchedule();145
this._pass(this._c, this._a, this._b, 7n);146
this._keySchedule();147
this._pass(this._b, this._c, this._a, 9n);148
for (let pass = 0; pass < this._extraPasses; ++pass) {149
this._keySchedule();150
this._pass(this._a, this._b, this._c, 9n);151
const tmpa = this._a;152
this._a = this._c;153
this._c = this._b;154
this._b = tmpa;155
}156
this._feedforward();157
}159
_round(a, b, c, x, mul) {160
c.value ^= x;161
const d = c.value;162
const d_0 = d & 0xffn;163
const d_1 = (d >> 8n) & 0xffn;164
const d_2 = (d >> 16n) & 0xffn;165
const d_3 = (d >> 24n) & 0xffn;166
const d_4 = (d >> 32n) & 0xffn;167
const d_5 = (d >> 40n) & 0xffn;168
const d_6 = (d >> 48n) & 0xffn;169
const d_7 = (d >> 56n) & 0xffn;170
a.value = uint(a.value - (t1[d_0] ^ t2[d_2] ^ t3[d_4] ^ t4[d_6]));171
b.value = (b.value + (t4[d_1] ^ t3[d_3] ^ t2[d_5] ^ t1[d_7])) & U64;172
b.value = (b.value * mul) & U64;173
}175
_pass(a, b, c, mul) {176
this._round(a, b, c, this._x0, mul);177
this._round(b, c, a, this._x1, mul);178
this._round(c, a, b, this._x2, mul);179
this._round(a, b, c, this._x3, mul);180
this._round(b, c, a, this._x4, mul);181
this._round(c, a, b, this._x5, mul);182
this._round(a, b, c, this._x6, mul);183
this._round(b, c, a, this._x7, mul);184
}186
_split(message, block) {187
this._x0 = message[block];188
this._x1 = message[block + 1];189
this._x2 = message[block + 2];190
this._x3 = message[block + 3];191
this._x4 = message[block + 4];192
this._x5 = message[block + 5];193
this._x6 = message[block + 6];194
this._x7 = message[block + 7];195
}197
hash(input /*: string*/) /*: string*/ {198
// Tiger's supplied implementation in C makes heavy use of imperative macros199
// that overwrite the state of old values; specifically the `round` macro.200
// this doesn't map to the lexical scoping and pass-by-value semantics of201
// functions in JavaScript when passing primitives. Here, we mimic "inout"202
// params or "references" with lightweight objects.203
this._a = {value: 0x0123456789abcdefn};204
this._b = {value: 0xfedcba9876543210n};205
this._c = {value: 0xf096a5b4c3b2e187n};206
const words = _getMessage(Buffer.from(input, this._encoding));208
for (let block = 0; block < words.length; block += 8) {209
this._split(words, block);210
this._compress();211
}213
const digest = [this._a, this._b, this._c].map(n => _zeroFill(n)).join('');214
const chars = this._digestBitLen / 4;215
if (!this._invertByte) {216
let inverted = '';217
for (let i = 0; i < digest.length && i < chars; ++i) {218
inverted += digest[inversion[i]];219
}220
return inverted;221
}222
return digest.substr(0, chars);223
}224
}226
Tiger.L128 = 128;227
Tiger.L160 = 160;228
Tiger.L192 = 192;230
Tiger.UTF8 = 'utf8';231
Tiger.UTF16 = 'utf16le';233
module.exports = Tiger;SHA-256: 13dca90f874c4179bff7ab038ca65a28a56a382e36688967c74c159daeea456d
SHA-256 archivu: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0