forked from wendelb/DelphiOTP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBase32U.pas
177 lines (155 loc) · 4.64 KB
/
Base32U.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
168
169
170
171
172
173
174
175
176
177
unit Base32U;
interface
uses
System.SysUtils; // For UpperCase (Base32Decode)
type
Base32 = class
public
/// <param name="inString">
/// Base32-String (Attention: No validity checks)
/// </param>
/// <summary>
/// Decodes a Base32-String
/// </summary>
/// <returns>
/// Unicode String containing the ANSI-Data from that Base32-Input
/// </returns>
class function Decode(const inString: String): String;
/// <param name="inString">
/// Input
/// </param>
/// <summary>
/// Encodes data into a Base32-String
/// </summary>
/// <returns>
/// Unicode String containing the Base32-String
/// </returns>
class function Encode(const inString: String): String;
end;
implementation
{$REGION 'Base32Functions'}
// Delphi functions for Base32
// Somewhere from Embarcadero.
// My Source is http://www.delphipraxis.net/995124-post9.html
const
ValidChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
function FromBase32String(const inString : string) : string;
var
outString : string;
aByte : byte;
bit_buffer,
inIndex,
bits_in_buffer,
outSize,
pos1, pos2,
i : integer;
begin
outSize := (length(inString) * 5 div 8) + 1;
outString := StringOfChar(' ',outSize);
pos1 := Pos(inString[1],ValidChars) - 1;
pos2 := Pos(inString[2],ValidChars) - 1;
bit_buffer := pos1 or (pos2 shl 5);
if length(inString) < 3 then begin
aByte := bit_buffer;
outString[1] := Chr(aByte);
result := outString;
exit;
end;
bits_in_buffer := 10;
inIndex := 3;
for i := 1 to outSize + 1 do begin
aByte := bit_buffer;
outString[i] := Chr(aByte);
bit_buffer := bit_buffer shr 8;
bits_in_buffer := bits_in_buffer - 8;
while (bits_in_buffer < 8) and (inIndex <= length(inString)) do begin
pos1 := (Pos(inString[inIndex],ValidChars) - 1);
Inc(inIndex);
bit_buffer := bit_buffer or (pos1 shl bits_in_buffer);
bits_in_buffer := bits_in_buffer + 5;
end;
end;
result := outString;
end;
function ToBase32String(const inString : string) : string;
var
currentChar,
outString : string;
inIndex,
validIndex,
high : integer;
aByte,
currentByte : byte;
begin
high := 5;
inIndex := 1;
while inIndex <= Length(inString) do begin
currentChar := inString[inIndex];
currentByte := Ord(currentChar[1]);
if (high > 8) then begin
// get the last piece from the current byte, shift it to the right
// and increment the byte counter
validIndex := (currentByte shr (high - 5)) mod 256;
Inc(inIndex);
currentChar := inString[inIndex];
currentByte := Ord(currentChar[1]);
if (inIndex <> Length(inString) + 1) then begin
// if we are not at the end, get the first piece from
// the next byte, clear it and shift it to the left
aByte := (currentByte shl (16 - high)) mod 256;
validIndex := ((aByte shr 3 ) or validIndex) mod 256;
end;
high := high - 3;
end else if(high = 8) then begin
Inc(inIndex);
validIndex := currentByte shr 3;
high := high - 3;
end else begin
// simply get the stuff from the current byte
aByte := currentByte shl (8 - high) mod 256;
validIndex := aByte shr 3;
high := high + 5;
end;
currentChar := ValidChars[validIndex + 1];
outString := outString + currentChar;
end;
result := outString;
end;
// As the FromBase32String Function doesn't has the result I'm looking for, here
// is my version of that function. This is converted from a PHP function, which
// can be found here: https://www.idontplaydarts.com/2011/07/google-totp-two-factor-authentication-for-php/
function Base32Decode(const source: String): String;
var
UpperSource: String;
p, i, l, n, j: Integer;
begin
UpperSource := UpperCase(source);
l := Length(source);
n := 0; j := 0;
Result := '';
for i := 1 to l do
begin
n := n shl 5; // Move buffer left by 5 to make room
p := Pos(UpperSource[i], ValidChars);
if p >= 0 then
n := n + (p - 1); // Add value into buffer
j := j + 5; // Keep track of number of bits in buffer
if (j >= 8) then
begin
j := j - 8;
Result := Result + chr((n AND ($FF shl j)) shr j);
end;
end;
end;
{$ENDREGION}
{ Base32 }
class function Base32.Decode(const inString: String): String;
begin
// Result := FromBase32String(inString);
Result := Base32Decode(inString);
end;
class function Base32.Encode(const inString: String): String;
begin
Result := ToBase32String(inString);
end;
end.