-
Notifications
You must be signed in to change notification settings - Fork 3
/
nosodig.crypto.pas
168 lines (141 loc) · 3.25 KB
/
nosodig.crypto.pas
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
unit NosoDig.Crypto;
{$ifdef FPC}
{$mode DELPHI}{$H+}
{$endif}
{$ifopt D+}
{$define DEBUG}
{$endif}
//Includes optimizations for 32/64 bits
interface
uses
Classes,
SysUtils;
type
THash32 = array[0..31] of Char; { 256 bits }
function NosoHash(S: String): THash32;
function GetHashDiff(const HashA, HashB: THash32): THash32;
implementation
uses
MD5;
type
PByteHash128 = ^TByteHash128;
TByteHash128 = packed array[0..127] of Byte; { 1024 bits }
PAsciiLookup = ^TAsciiLookup;
TAsciiLookup = packed array[0..511] of Byte;
const
MAX_DIFF = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
var
AsciiLookupTable: TAsciiLookup;
function BinToHexFast(const B: Byte): Char;{$ifndef DEBUG}inline;{$endif}
const
bin2hex_lookup: array[0..15] of Char =
('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
begin
if (B > 15) then
Exit(#0);
Result := bin2hex_lookup[B]
end;
function HexToBinFast(const C: Char): Byte;{$ifndef DEBUG}inline;{$endif}
const
hex2bin_lookup: array['0'..'F'] of Byte =
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15);
begin
Assert( ((C>='0') and (C<='9')) or ((C>='A') and (C<='F')));
Result := hex2bin_lookup[C];
end;
function NosoHash(S: String): THash32;
{$ifdef CPUX86}
function Mutate(pHash: Pointer): Pointer;
var
i, n, LFirst: UInt8;
p: PByte;
begin
Result := pHash;
for n:=127 downto 0 do
begin
p := Result;
LFirst := p^;
for i:=126 downto 0 do
begin
p^ := AsciiLookupTable[ (p^ + PByte(p+1)^) ];
Inc(p);
end;
p^ := AsciiLookupTable[ (p^ + LFirst) ];
end;
end;
{$endif}
var
i, n, LFirst: Byte;
{$ifdef CPUX86}
p : PByte;
tab: TAsciiLookup absolute AsciiLookupTable;
{$else}
p, tab: PByte;
{$endif}
const
NOSOHASH_FILLER = '%)+/5;=CGIOSYaegk';
begin
Result := '';
if Length(S) > 63 then
SetLength(S, 0);
for i := 1 to Length(S) do
if (Ord(S[i]) < 33) or (Ord(S[i]) > 126) then
begin
SetLength(S, 0);
Break;
end;
repeat
S := S + NOSOHASH_FILLER;
until Length(S) >= 128;
{$ifdef CPUX86}
p := Mutate(PAnsiChar(S));
{$else}
tab := @AsciiLookupTable;
for n:=1 to 128 do
begin
p := Pointer(S);
LFirst := p^;
for i:=0 to 126 do
begin
p^ := PByte(tab + (p^ + PByte(p+1)^) )^;
Inc(p);
end;
p^ := PByte(tab + (p^ + LFirst) )^;
end;
p := Pointer(S);
{$ifend}
for i:=0 to 31 do
begin
{$ifdef CPUX86}
Result[i] := BinToHexFast(tab[ p[i*4] + p[i*4+1] + p[i*4+2] + p[i*4+3] ] mod 16);
{$else}
Result[i] := BinToHexFast(PByte(tab + (p^ + PByte(p+1)^ + PByte(p+2)^ + PByte(p+3)^))^ mod 16);
Inc(p, 4);
{$endif}
end;
Result := MD5Print(MDBuffer(Result, SizeOf(THash32), MD_VERSION_5)).ToUpper;
end;
function GetHashDiff(const HashA, HashB: THash32): THash32;
var
i: Integer;
begin
Result := MAX_DIFF;
for i := 0 to 31 do
Result[i] := HexStr(Abs(HexToBinFast(HashB[i]) - HexToBinFast(HashA[i])), 1)[1];
end;
procedure FillLookupTables;
var
i, n: Word;
begin
for i:=Low(AsciiLookupTable) to High(AsciiLookupTable) do
begin
if (i < 32) or (i > 504) then
continue;
n := i;
while n > 126 do Dec(n, 95);
AsciiLookupTable[i] := n;
end;
end;
initialization
FillLookupTables;
end.