【Delphi】Base64加解密模块

支持D2007之前的版本。

  1 {*******************************************************}
  2 {                                                       }
  3 {       YxdInclude Base64加解密模块                     }
  4 {                                                       }
  5 {       版权所有 (C) 2013 GXT  YangYxd                  }
  6 {                                                       }
  7 {*******************************************************}
  8 
  9 unit uBase64;
 10 
 11 interface
 12 
 13 uses SysUtils, Classes;
 14 
 15 type
 16 {$IFDEF UNICODE}
 17   Base64String = AnsiString;
 18 {$ELSE}
 19   Base64String = string;
 20 {$ENDIF}
 21 
 22 // 按源长度SourceSize返回Base64编码所需缓冲区字节数
 23 function Base64EncodeBufSize(SourceSize: Integer): Integer;
 24 // 获取Sourec的Base64编码,Base64Buf必须有足够长度。返回实际编码字节数
 25 function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer; overload;
 26 // 将Source编码为Base64字符串返回
 27 function Base64Encode(const Source; SourceSize: Integer): Base64String; overload;
 28 // 将Source从StartPos开始的Size长度的内容源编码为Base64,写入流Dest。
 29 // Size=0 表示一直编码到文件尾
 30 procedure Base64Encode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;
 31 // 把字符串Str编码为Base64字符串返回
 32 {$IFDEF UNICODE}
 33 function StrToBase64(const Str: AnsiString): Base64String; overload;
 34 function StrToBase64(const Str: string): Base64String; overload;
 35 {$ELSE}
 36 function StrToBase64(const Str: string): Base64String;
 37 {$ENDIF}
 38 
 39 // 按给定的编码源Source和长度SourceSize计算并返回解码缓冲区所需字节数
 40 function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
 41 // 将Base64编码源Base64Source解码,Buf必须有足够长度。返回实际解码字节数
 42 function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer; overload;
 43 // 将Source从StartPos开始的Size长度的Base64编码内容解码,写入流Dest。
 44 // Size=0 表示一直解码到文件尾
 45 procedure Base64Decode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;
 46 // 将Base64编码源Base64Source解码为字符串返回
 47 function Base64Decode(const Base64Source; SourceSize: Integer): string; overload;
 48 // 把Base64字符串Base64Str解码为字符串返回
 49 function Base64ToStr(const Base64Str: Base64String): string;
 50 // 把字符串转为Unicode再编码成Base64字符串
 51 function StrToUnicodeBase64(const Value: string): string;
 52 function UnicodeBase64ToStr(const Value: string): string;
 53 
 54 function StrBase64ToUNICODE(const Value: string): string;
 55 
 56 implementation
 57 
 58 const
 59   Base64_Chars: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 60   Base64_Bytes: array[0..79] of Byte =
 61   (
 62     62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
 63     0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 64     10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
 65     0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
 66     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
 67   );
 68   
 69 type
 70   Base64Proc = function(const Source; SourceSize: Integer; var Buf): Integer;
 71 
 72 
 73 function StrToUnicodeBase64(const Value: string): string;
 74 var
 75   cSize: Integer;
 76   tmp: Byte;
 77   i: Integer;
 78   ppszW: array of Byte;
 79   ww: WideString;
 80 begin
 81   ww := Value;
 82   cSize := length(ww) * 2;
 83   SetLength(ppszW, cSize);
 84   try
 85     Move(ww[1], ppszW[0], cSize);
 86     i := 0;
 87     while i < cSize do begin
 88       tmp := ppszw[i];
 89       ppszw[i] := ppszw[i + 1];
 90       ppszw[i + 1] := tmp;
 91       inc(i, 2);
 92     end;
 93     Result := Base64Encode(ppszW[0], High(ppszW)+1);
 94   finally
 95     SetLength(ppszW, 0);
 96   end;
 97 end;
 98       
 99 function StrBase64ToUNICODE(const Value: string): string;
100 begin
101   Result := UnicodeBase64ToStr(Value);
102 end;
103 
104 function UnicodeBase64ToStr(const Value: string): string;
105 var
106   cSize: Integer;
107   tmp: Byte;
108   i: Integer;
109   ppszW: array of Byte;
110   ww: WideString;
111 begin
112   ww := Value;
113   cSize := length(ww);
114   SetLength(ppszW, cSize);
115   Base64Decode(Value[1], Length(ww), ppszW[0]);
116   try
117     i := 0;
118     while i < High(ppszW) do begin
119       tmp := ppszw[i];
120       ppszw[i] := ppszw[i + 1];
121       ppszw[i + 1] := tmp;
122       inc(i, 2);
123     end;
124     Result := Trim(WideString(ppszW));
125   finally
126     SetLength(ppszW, 0);
127   end;
128 end;
129 
130 procedure Base64Stream(Source, Dest: TStream; Proc: Base64Proc;
131   StartPos, Size: Int64; RBufSize, WBufSize: Integer);
132 var
133   RBuf: array of Byte;
134   WBuf: array of Byte;
135   RSize, WSize: Integer;
136 begin
137   if (StartPos < 0) or (StartPos >= Source.Size) then Exit;
138   Source.Position := StartPos;
139   if (Size <= 0) or (Size > Source.Size - Source.Position) then
140     Size := Source.Size
141   else
142     Size := Size + Source.Position;
143   SetLength(RBuf, RBufSize);
144   SetLength(WBuf, WBufSize);
145   while Size <> Source.Position do
146   begin
147     if RBufSize > Size - Source.Position then
148        RBufSize := Size - Source.Position;
149     RSize := Source.Read(RBuf[0], RBufSize);
150     WSize := Proc(RBuf[0],  RSize, WBuf[0]);
151     Dest.Write(WBuf[0], WSize);
152   end;
153 end;
154 
155 function Base64EncodeBufSize(SourceSize: Integer): Integer;
156 begin
157   Result := ((SourceSize + 2) div 3) shl 2;
158 end;
159 
160 (****************************************************************************
161 *                                                                           *
162 * BASE64 Encode hint:                                                       *
163 *                                                                           *
164 * addr:            (high) 4 byte     3 byte     2 byte     1 byte (low)     *
165 * sourec ASCII(3 bytes):            33333333   22222222   11111111          *
166 * bswap:                 11111111   22222222   33333333   00000000          *
167 * b4 = Base64_Chars[(source >> 8) & 63]:      [00333333]->44444444          *
168 * b3 = Base64_Chars[(source >> 14) & 63]:     [00222233]->33333333          *
169 * b2 = Base64_Chars[(source >> 20) & 63]:     [00112222]->22222222          *
170 * b1 = Base64_Chars[source >> 26]:            [00111111]->11111111          *
171 *                        b4 << 24   b3 << 16   b2 << 8    b1                *
172 * dest BASE64(4 bytes)   44444444   33333333   22222222   11111111          *
173 *                                                                           *
174 ****************************************************************************)
175 
176 function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer;
177 asm
178     push    ebp
179     push    esi
180     push    edi
181     push    ebx
182     mov     esi, eax         // esi = Source
183     mov     edi, ecx         // edi = Buf
184     mov     eax, edx
185     cdq
186     mov     ecx, 3
187     div     ecx              // edx = SourceSize % 3
188     mov     ecx, eax         // ecx = SourceSize / 3
189     test    edx, edx         
190     jz      @@1
191     inc     eax              // eax = (SourceSize + 2) / 3
192   @@1:
193     push    eax
194     push    edx
195     lea     ebp, Base64_Chars
196     jecxz   @Last
197     cld
198   @EncodeLoop:               //  while (ecx > 0){
199     mov     edx, [esi]       //   edx = 00000000 33333333 22222222 11111111
200     bswap   edx              //   edx = 11111111 22222222 33333333 00000000
201     push    edx
202     push    edx
203     push    edx
204     pop     ebx              //   ebx = edx
205     shr     edx, 20
206     shr     ebx, 26          //   ebx = 00111111
207     and     edx, 63          //   edx = 00112222
208     mov     ah, [ebp + edx]  //   *(word*)edi = (Base64_Chars[edx] << 8) |
209     mov     al, [ebp + ebx]  //     Base64_Chars[ebx]
210     stosw                    //   edi += 2
211     pop     edx              //   edx = 11111111 22222222 33333333 00000000
212     pop     ebx              //   ebx = edx
213     shr     edx, 8
214     shr     ebx, 14
215     and     edx, 63          //   edx = 00333333
216     and     ebx, 63          //   ebx = 00222233
217     mov     ah, [ebp + edx]  //   *(word*)edi = (Base64_Chars[edx] << 8) |
218     mov     al, [ebp + ebx]  //     Base64_Chars[ebx]
219     stosw                    //   edi += 2
220     add     esi, 3           //   esi += 3
221     loop    @EncodeLoop      // }
222   @Last:
223     pop     ecx              // ecx = SourceSize % 3
224     jecxz   @end             // if (ecx == 0) return
225     mov     eax, 3d3d0000h   // preset 2 bytes '='
226     mov     [edi], eax
227     test    ecx, 2
228     jnz     @@3
229     mov     al, [esi]        // if (ecx == 1)
230     shl     eax, 4           //   eax = *esi << 4
231     jmp     @@4
232   @@3:
233     mov     ax, [esi]        // else
234     xchg    al, ah           //   eax = ((*esi << 8) or *(esi + 1)) << 2
235     shl     eax, 2
236   @@4:
237     add     edi, ecx         // edi += ecx
238     inc     ecx              // ecx = last encode bytes
239   @LastLoop:
240     mov     edx, eax         // for (; cex > 0; ecx --, edi --)
241     and     edx, 63          // {
242     mov     dl, [ebp + edx]  //   edx = eax & 63
243     mov     [edi], dl        //   *edi = Base64_Chars[edx]
244     shr     eax, 6           //   eax >>= 6
245     dec     edi              // }
246     loop    @LastLoop
247   @end:
248     pop     eax
249     shl     eax, 2           // return  encode bytes
250     pop     ebx
251     pop     edi
252     pop     esi
253     pop     ebp
254 end;
255 
256 function Base64Encode(const Source; SourceSize: Integer): Base64String;
257 begin
258   SetLength(Result, Base64EncodeBufSize(SourceSize));
259   Base64Encode(Source, SourceSize, Result[1]);
260 end;
261 
262 procedure Base64Encode(Source, Dest: TStream; StartPos: Int64; Size: Int64);
263 begin
264   Base64Stream(Source, Dest, Base64Encode, StartPos, Size, 6144, 8192);
265 end;
266 
267 {$IFDEF UNICODE}
268 function StrToBase64(const Str: AnsiString): Base64String;
269 begin
270   Result := Base64Encode(Str[1], Length(Str));
271 end;
272 
273 function StrToBase64(const Str: string): Base64String;
274 begin
275   Result := StrToBase64(AnsiString(Str));
276 end;
277 {$ELSE}
278 function StrToBase64(const Str: string): Base64String;
279 begin
280   Result := Base64Encode(Str[1], Length(Str));
281 end;
282 {$ENDIF}
283 
284 function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
285 asm
286     mov     ecx, eax    // ecx = Source + Size
287     add     ecx, edx
288     mov     eax, edx    // eax = Size / 4 * 3
289     shr     edx, 2
290     shr     eax, 1
291     add     eax, edx
292     mov     edx, eax
293     jz      @@2
294   @@1:
295     dec     ecx
296     cmp     byte ptr [ecx], 61
297     jne     @@2         // if (*--ecx == '=')
298     dec     eax         //   eax --
299     jmp     @@1
300   @@2:                  // return eax: BufSize;  edx: Size / 4 * 3
301 end;
302 
303 function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer;
304 asm
305     push    ebp
306     push    esi
307     push    edi
308     push    ebx
309     mov     esi, eax       // esi = Source
310     mov     edi, ecx       // edi = Buf
311     mov     ebx, edx
312     call    Base64DecodeBufSize
313     push    eax            // eax = Base64DecodeBufSize(Source, SourceSize)
314     sub     edx, eax       // edx -= eax  // edx: '=' count
315     lea     ebp, Base64_Bytes
316     shr     ebx, 2         // ebx = SourceSize / 4
317     test    ebx, ebx
318     jz      @end
319     push    edx
320     cld
321   @DecodeLoop:             // for (; ebx > 0; ebx --; edi += 3)
322     mov     ecx, 4         // {
323     xor     eax, eax
324   @xchgLoop:               //   for (ecx = 4, eax = 0; ecx > 0; ecx --)
325     movzx   edx, [esi]     //   {
326     sub     edx, 43        //      edx = *(int*)esi - 43
327     shl     eax, 6         //      eax <<= 6
328     or      al, [ebp + edx]//      al |= Base64_Bytes[edx]
329     inc     esi            //      esi ++
330     loop    @xchgLoop      //   }
331     bswap   eax            //   bswap(eax)
332     dec     ebx            //   if (ebx == 1) break
333     jz      @Last
334     shr     eax, 8         //   eax >>= 8
335     stosw                  //   *edi = ax; edi += 2
336     shr     eax, 16        //   eax >>= 16
337     stosb                  //   *edi++ = al
338     jmp     @DecodeLoop    // }
339   @Last:
340     pop     ecx            
341     xor     ecx, 3         // ecx = last bytes
342   @LastLoop:               // for (; ecx > 0; ecx --)
343     shr     eax, 8         // {
344     stosb                  //   eax >>= 8; *edi ++ = al
345     loop    @LastLoop      // }
346   @end:
347     pop     eax            // return eax
348     pop     ebx
349     pop     edi
350     pop     esi
351     pop     ebp
352 end;
353 
354 procedure Base64Decode(Source, Dest: TStream; StartPos: Int64; Size: Int64);
355 begin
356   Base64Stream(Source, Dest, Base64Decode, StartPos, Size, 8192, 6144);
357 end;
358 
359 {$IFDEF UNICODE}
360 function Base64Decode(const Base64Source; SourceSize: Integer): string;
361 var
362   s: AnsiString;
363 begin
364   SetLength(s, Base64DecodeBufSize(Base64Source, SourceSize));
365   Base64Decode(Base64Source, SourceSize, s[1]);
366   Result := string(s);
367 end;
368 {$ELSE}
369 function Base64Decode(const Base64Source; SourceSize: Integer): string;
370 begin
371   SetLength(Result, Base64DecodeBufSize(Base64Source, SourceSize));
372   Base64Decode(Base64Source, SourceSize, Result[1]);
373 end;
374 {$ENDIF}
375 
376 function Base64ToStr(const Base64Str: Base64String): string;
377 begin
378   Result := Base64Decode(Base64Str[1], Length(Base64Str));
379 end;
380 
381 
382 end.

转载注明出处,谢谢。

 

posted @ 2014-08-23 09:40  我爱我家喵喵  阅读(1463)  评论(0编辑  收藏  举报