-
Notifications
You must be signed in to change notification settings - Fork 3
/
nosodig.crypto68b.pas
131 lines (109 loc) · 2.53 KB
/
nosodig.crypto68b.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
unit NosoDig.Crypto68b;
{$ifdef FPC}
{$mode DELPHI}{$H+}
{$endif}
{$ifopt D+}
{$define DEBUG}
{$endif}
interface
uses
Classes,
SysUtils;
type
THash32 = array[0..31] of Char; { 256 bits }
function NosoHash68b(S: String): THash32;
function GetHashDiff68b(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..504] 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 NosoHash68b(S: String): THash32;
var
i, n, LFirst: Byte;
p, tab: PByte;
const
NOSOHASH_FILLER = '%)+/5;=CGIOSYaegk';
begin
Result := '';
tab := @AsciiLookupTable;
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;
{+20us}
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;
{+2us}
p := Pointer(S);
for i:=0 to 31 do
begin
Result[i] := BinToHexFast(PByte(tab + (p^ + PByte(p+1)^ + PByte(p+2)^ + PByte(p+3)^))^ mod 16);
Inc(p, 4);
end;
{+10us}
Result := MD5Print(MDBuffer(Result, SizeOf(THash32), MD_VERSION_5)).ToUpper;
end;
function GetHashDiff68b(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
n := i;
while n > 126 do Dec(n, 95);
AsciiLookupTable[i] := n;
end;
end;
initialization
FillLookupTables;
end.
end.