Last active
January 6, 2023 21:03
-
-
Save Bloodwyn/ff8fd940f064fd321757468b47c5a5ba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Implementaion of the md5 hashing algorithm in sqf | |
en.wikipedia.org/wiki/md5 | |
community.bistudio.com/wiki/SQF_syntax | |
Author: Bastian Kuth | "Bloodwyn" | |
Its rather slow (about 120ms per GUID), but can be used to convert the SteamID64 to the BattleEye GUID without having to use external tools or addons. | |
developer.valvesoftware.com/wiki/SteamID | |
The main challenge developing this was the lack of an Integer datatype in sqf. | |
I used this C implementaion from Tim Caswell as a reference: gist.github.com/creationix/4710780 | |
*/ | |
BW_hash_fnc_calloc = { | |
private _ret = []; | |
_ret set [_this-1,0]; | |
_ret apply {0}; | |
}; | |
BW_hash_fnc_memcpy = { | |
params ["_dst", "_src", "_len"]; | |
for "_i" from 0 to (_len-1) step 1 do { | |
_dst set [_i,_src # _i]; | |
}; | |
_dst; | |
}; | |
BW_hash_fnc_shiftr = { | |
params [ | |
["_a",0,[0]], | |
["_c",0,[0]] | |
]; | |
floor (_a / (2 ^ _c)); | |
}; | |
BW_hash_fnc_shiftl = { | |
params [ | |
["_a",0,[0]], | |
["_c",0,[0]] | |
]; | |
(_a * (2 ^ _c)) mod 256; | |
}; | |
BW_hash_fnc_shiftr32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_c",0,[0]] | |
]; | |
_a = +_a; | |
private ["_r","_a0","_a1","_a2","_a3","_maskForOverflow"]; | |
while {_c>8} do { | |
_c = _c-8; | |
_a deleteAt 3; | |
_a = [0] + _a; | |
}; | |
_maskForOverflow = 2^_c-1; | |
_a0 = [_a#0,_c] call BW_hash_fnc_shiftr; | |
_r = [[_a#0,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftl; | |
_a1 = [[_a#1,_c] call BW_hash_fnc_shiftr,_r] call BIS_fnc_bitwiseOR; | |
_r = [[_a#1,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftl; | |
_a2 = [[_a#2,_c] call BW_hash_fnc_shiftr,_r] call BIS_fnc_bitwiseOR; | |
_r = [[_a#2,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftl; | |
_a3 = [[_a#3,_c] call BW_hash_fnc_shiftr,_r] call BIS_fnc_bitwiseOR; | |
[_a0,_a1,_a2,_a3]; | |
}; | |
BW_hash_fnc_shiftl32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_c",0,[0]] | |
]; | |
_a = +_a; | |
private ["_r","_a0","_a1","_a2","_a3","_maskForOverflow"]; | |
while {_c>8} do { | |
_c = _c-8; | |
_a deleteAt 0; | |
_a pushBack 0; | |
}; | |
_maskForOverflow = [[2^(8-_c)-1] call BIS_fnc_bitwiseNOT,0xFF] call BIS_fnc_bitwiseAND; | |
_a3 = [_a#3,_c] call BW_hash_fnc_shiftl; | |
_r = [[_a#3,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftr; | |
_a2 = [[_a#2,_c] call BW_hash_fnc_shiftl,_r] call BIS_fnc_bitwiseOR; | |
_r = [[_a#2,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftr; | |
_a1 = [[_a#1,_c] call BW_hash_fnc_shiftl,_r] call BIS_fnc_bitwiseOR; | |
_r = [[_a#1,_maskForOverflow] call BIS_fnc_bitwiseAND, 8-_c] call BW_hash_fnc_shiftr; | |
_a0 = [[_a#0,_c] call BW_hash_fnc_shiftl,_r] call BIS_fnc_bitwiseOR; | |
[_a0 mod 256,_a1 mod 256,_a2 mod 256,_a3 mod 256]; | |
}; | |
BW_hash_fnc_and32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_b",[],[[]],4] | |
]; | |
[ | |
[_a#0,_b#0] call BIS_fnc_bitwiseAND, | |
[_a#1,_b#1] call BIS_fnc_bitwiseAND, | |
[_a#2,_b#2] call BIS_fnc_bitwiseAND, | |
[_a#3,_b#3] call BIS_fnc_bitwiseAND | |
]; | |
}; | |
BW_hash_fnc_or32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_b",[],[[]],4] | |
]; | |
[ | |
[_a#0,_b#0] call BIS_fnc_bitwiseOR, | |
[_a#1,_b#1] call BIS_fnc_bitwiseOR, | |
[_a#2,_b#2] call BIS_fnc_bitwiseOR, | |
[_a#3,_b#3] call BIS_fnc_bitwiseOR | |
]; | |
}; | |
BW_hash_fnc_xor32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_b",[],[[]],4] | |
]; | |
[ | |
([_a#0,_b#0] call BIS_fnc_bitwiseXOR) mod 256, | |
([_a#1,_b#1] call BIS_fnc_bitwiseXOR) mod 256, | |
([_a#2,_b#2] call BIS_fnc_bitwiseXOR) mod 256, | |
([_a#3,_b#3] call BIS_fnc_bitwiseXOR) mod 256 | |
]; | |
}; | |
BW_hash_fnc_not32 = { | |
private _a = _this; | |
[ | |
((_a#0) call BIS_fnc_bitwiseNOT) mod 256, | |
((_a#1) call BIS_fnc_bitwiseNOT) mod 256, | |
((_a#2) call BIS_fnc_bitwiseNOT) mod 256, | |
((_a#3) call BIS_fnc_bitwiseNOT) mod 256 | |
]; | |
}; | |
BW_hash_fnc_add32 = { | |
params [ | |
["_a",[],[[]],4], | |
["_b",[],[[]],4] | |
]; | |
private ["_v1","_v2","_v3","_v4","_o"]; | |
_v1 = (_a#3)+(_b#3); | |
_o = floor (_v1 / 256); | |
_v2 = (_a#2)+(_b#2)+_o; | |
_o = floor (_v2 / 256); | |
_v3 = (_a#1)+(_b#1)+_o; | |
_o = floor (_v3 / 256); | |
_v4 = (_a#0)+(_b#0)+_o; | |
_o = floor (_v3 / 256); | |
[_v4 mod 256,_v3 mod 256,_v2 mod 256,_v1 mod 256]; | |
}; | |
BW_hash_fnc_decStrMod = { | |
private _str = param [0,"",[""]]; | |
private ["_r","_e"]; | |
_e = ""; | |
_parsed = parseNumber _str; | |
if(count _str < 3 or (_parsed < 256))exitWith{ | |
[str (floor (_parsed / 256)),_parsed % 256]; | |
}; | |
_part = parseNumber (_str select [0,3]); | |
for "_i" from 3 to ((count _str)) step 1 do { | |
_r = _part % 256; | |
_e = _e + str floor (_part / 256); | |
_part = _r*10 + parseNumber (_str select [_i,1]); | |
}; | |
[_e,_r]; | |
}; | |
BW_hash_fnc_fromDecStr = { | |
private _str = param [0,"",[""]]; | |
_bytes = []; | |
while{!(_str isEqualTo "0")} do { | |
_ret = _str call BW_hash_fnc_decStrMod; | |
_str = _ret#0; | |
_bytes = [_ret#1] + _bytes; | |
}; | |
_bytes; | |
}; | |
BW_hash_fnc_fromHexStr = { | |
private ["_str","_num","_flag","_tn0","_tn1"]; | |
_str = toLower _this; | |
if(_str select [0,2] isEqualTo "0x")then{_str = _str select [2,1e6]}; | |
if((count _str) mod 2 isEqualTo 1)then{_str = "0"+_str}; | |
_num = []; | |
_flag = true; | |
(toArray _str) apply { | |
if(_flag)then{ | |
_flag = false; | |
_tn0 = if(_x >= 96)then{_x-87}else{_x-48}; | |
}else{ | |
_tn1 = if(_x >= 96)then{_x-87}else{_x-48}; | |
_num pushBack (([_tn0,4] call BW_hash_fnc_shiftl) + _tn1); | |
_flag = true; | |
}; | |
}; | |
if(!_flag)then{ | |
_num pushBack([_tn0,4] call BW_hash_fnc_shiftl); | |
}; | |
_num; | |
}; | |
BW_hash_fnc_toHexStr = { | |
if(typeName _this isEqualTo "ARRAY")exitWith{ | |
_str = ""; | |
_this apply {_str = _str + (_x call BW_hash_fnc_toHexStr)}; | |
_str; | |
}; | |
_lkup = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; | |
(_lkup # (floor (_this / 16))) + (_lkup # (_this mod 16)); | |
}; | |
BW_hash_fnc_toNum = { | |
_num = 0; | |
_this apply {_num = _num*256 + _x}; | |
_num; | |
}; | |
BW_hash_fnc_hashToString = { | |
_ui32ar = _this; | |
_str = ""; | |
_ui32ar apply { | |
_bytes = _x; | |
_istr = ""; | |
_bytes apply { | |
_istr = (_x call BW_hash_fnc_toHexStr) + _istr; | |
}; | |
_str = _str + _istr; | |
}; | |
_str | |
}; | |
BW_hash_fnc_md5 = { | |
private ["_r","_k","_ho","_h1","_h2","_h3","_initial_msg","_initial_len","_new_len","_msg","_bits_len","_a","_b","_c","_d","_f","_g","_temp","_shift","_toshift","_selfrom"]; | |
_r = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, | |
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, | |
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, | |
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]; | |
_k = [ | |
[0xd7,0x6a,0xa4,0x78], [0xe8,0xc7,0xb7,0x56], [0x24,0x20,0x70,0xdb], [0xc1,0xbd,0xce,0xee], | |
[0xf5,0x7c,0x0f,0xaf], [0x47,0x87,0xc6,0x2a], [0xa8,0x30,0x46,0x13], [0xfd,0x46,0x95,0x01], | |
[0x69,0x80,0x98,0xd8], [0x8b,0x44,0xf7,0xaf], [0xff,0xff,0x5b,0xb1], [0x89,0x5c,0xd7,0xbe], | |
[0x6b,0x90,0x11,0x22], [0xfd,0x98,0x71,0x93], [0xa6,0x79,0x43,0x8e], [0x49,0xb4,0x08,0x21], | |
[0xf6,0x1e,0x25,0x62], [0xc0,0x40,0xb3,0x40], [0x26,0x5e,0x5a,0x51], [0xe9,0xb6,0xc7,0xaa], | |
[0xd6,0x2f,0x10,0x5d], [0x02,0x44,0x14,0x53], [0xd8,0xa1,0xe6,0x81], [0xe7,0xd3,0xfb,0xc8], | |
[0x21,0xe1,0xcd,0xe6], [0xc3,0x37,0x07,0xd6], [0xf4,0xd5,0x0d,0x87], [0x45,0x5a,0x14,0xed], | |
[0xa9,0xe3,0xe9,0x05], [0xfc,0xef,0xa3,0xf8], [0x67,0x6f,0x02,0xd9], [0x8d,0x2a,0x4c,0x8a], | |
[0xff,0xfa,0x39,0x42], [0x87,0x71,0xf6,0x81], [0x6d,0x9d,0x61,0x22], [0xfd,0xe5,0x38,0x0c], | |
[0xa4,0xbe,0xea,0x44], [0x4b,0xde,0xcf,0xa9], [0xf6,0xbb,0x4b,0x60], [0xbe,0xbf,0xbc,0x70], | |
[0x28,0x9b,0x7e,0xc6], [0xea,0xa1,0x27,0xfa], [0xd4,0xef,0x30,0x85], [0x04,0x88,0x1d,0x05], | |
[0xd9,0xd4,0xd0,0x39], [0xe6,0xdb,0x99,0xe5], [0x1f,0xa2,0x7c,0xf8], [0xc4,0xac,0x56,0x65], | |
[0xf4,0x29,0x22,0x44], [0x43,0x2a,0xff,0x97], [0xab,0x94,0x23,0xa7], [0xfc,0x93,0xa0,0x39], | |
[0x65,0x5b,0x59,0xc3], [0x8f,0x0c,0xcc,0x92], [0xff,0xef,0xf4,0x7d], [0x85,0x84,0x5d,0xd1], | |
[0x6f,0xa8,0x7e,0x4f], [0xfe,0x2c,0xe6,0xe0], [0xa3,0x01,0x43,0x14], [0x4e,0x08,0x11,0xa1], | |
[0xf7,0x53,0x7e,0x82], [0xbd,0x3a,0xf2,0x35], [0x2a,0xd7,0xd2,0xbb], [0xeb,0x86,0xd3,0x91] | |
]; | |
_h0 = [0x67,0x45,0x23,0x01]; | |
_h1 = [0xef,0xcd,0xab,0x89]; | |
_h2 = [0x98,0xba,0xdc,0xfe]; | |
_h3 = [0x10,0x32,0x54,0x76]; | |
_initial_msg = _this; | |
if(typeName _this isEqualTo "STRING")then{ | |
_initial_msg = (toArray _initial_msg); | |
}; | |
_initial_len = (count _initial_msg); | |
_new_len = ((floor ((_initial_len + 8) / 64) + 1) * 64) - 8; | |
_msg = (_new_len + 64) call BW_hash_fnc_calloc; | |
_msg = [_msg, _initial_msg, _initial_len] call BW_hash_fnc_memcpy; | |
_msg set [_initial_len,128]; | |
_bits_len = 8 * _initial_len; | |
_msg set [_new_len+3 ,floor (_bits_len / (2^24)) mod 256]; | |
_msg set [_new_len+2,floor (_bits_len / (2^16)) mod 256]; | |
_msg set [_new_len+1,floor (_bits_len / (2^8)) mod 256]; | |
_msg set [_new_len+0,floor (_bits_len) mod 256]; | |
for "_offset" from 0 to (_new_len-1) step (512 / 8) do { | |
_a = _h0; | |
_b = _h1; | |
_c = _h2; | |
_d = _h3; | |
for "_i" from 0 to (64-1) step 1 do { | |
switch (true) do { | |
case (_i < 16) : { | |
_f = [ | |
[_b,_c] call BW_hash_fnc_and32, | |
[_b call BW_hash_fnc_not32,_d] call BW_hash_fnc_and32 | |
] call BW_hash_fnc_or32; | |
_g = [0,0,0,_i]; | |
}; | |
case (_i < 32) : { | |
_f = [ | |
[_d,_b] call BW_hash_fnc_and32, | |
[_d call BW_hash_fnc_not32,_c] call BW_hash_fnc_and32 | |
] call BW_hash_fnc_or32; | |
_g = [0,0,0,(5 * _i + 1) % 16]; | |
}; | |
case (_i < 48) : { | |
_f = [[_b,_c] call BW_hash_fnc_xor32,_d] call BW_hash_fnc_xor32; | |
_g = [0,0,0,(3 * _i + 5) % 16]; | |
}; | |
default { | |
_f = [_c,[_b,_d call BW_hash_fnc_not32] call BW_hash_fnc_or32] call BW_hash_fnc_xor32; | |
_g = [0,0,0,(7 * _i) % 16]; | |
}; | |
}; | |
_temp = _d; | |
_d = _c; | |
_c = _b; | |
_shift = _r#_i; | |
_selfrom = _offset + ((_g call BW_hash_fnc_toNum)*4); | |
_toshift = [[[_a, _f] call BW_hash_fnc_add32,_k#_i] call BW_hash_fnc_add32,[_msg # (_selfrom+3), _msg # (_selfrom+2), _msg # (_selfrom+1), _msg # _selfrom]] call BW_hash_fnc_add32; | |
_b = [_b,[[_toshift,_shift] call BW_hash_fnc_shiftl32,[_toshift,32 - _shift] call BW_hash_fnc_shiftr32] call BW_hash_fnc_or32] call BW_hash_fnc_add32; | |
_a = _temp; | |
}; | |
_h0 = [_h0,_a] call BW_hash_fnc_add32; | |
_h1 = [_h1,_b] call BW_hash_fnc_add32; | |
_h2 = [_h2,_c] call BW_hash_fnc_add32; | |
_h3 = [_h3,_d] call BW_hash_fnc_add32; | |
}; | |
[_h0,_h1,_h2,_h3] call BW_hash_fnc_hashToString; | |
}; | |
BW_hash_fnc_steamIdToGUID = { | |
private _steamid = param [0, "",[""]]; | |
private _bytes = _steamid call BW_hash_fnc_fromDecStr; | |
reverse _bytes; | |
_tohash = (toArray "BE") + _bytes; | |
((toArray "BE") + _bytes) call BW_hash_fnc_md5; | |
}; | |
["76561198055205907"] call BW_hash_fnc_steamidToGUID; // returns "861211889e6b3e4c3a584c5d42cb4825" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment