XXTEA.pas 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. {
  2. /**********************************************************\
  3. | |
  4. | The implementation of PHPRPC Protocol 3.0 |
  5. | |
  6. | XXTEA.pas |
  7. | |
  8. | Release 3.0.0 |
  9. | Copyright (c) 2005-2008 by Team-PHPRPC |
  10. | |
  11. | WebSite: http://www.phprpc.org/ |
  12. | http://www.phprpc.net/ |
  13. | http://www.phprpc.com/ |
  14. | http://sourceforge.net/projects/php-rpc/ |
  15. | |
  16. | Authors: Ma Bingyao <andot@ujn.edu.cn> |
  17. | |
  18. | This file may be distributed and/or modified under the |
  19. | terms of the GNU Lesser General Public License (LGPL) |
  20. | version 3.0 as published by the Free Software Foundation |
  21. | and appearing in the included file LICENSE. |
  22. | |
  23. \**********************************************************/
  24. /* XXTEA encryption arithmetic library.
  25. *
  26. * Copyright (C) 2005-2008 Ma Bingyao <andot@ujn.edu.cn>
  27. * Version: 3.0.0
  28. * LastModified: Jan 17, 2008
  29. * This library is free. You can redistribute it and/or modify it.
  30. */
  31. }
  32. unit XXTEA;
  33. interface
  34. uses
  35. SysUtils,Windows;
  36. function Encrypt(const data:AnsiString; const key:AnsiString):AnsiString;
  37. function Decrypt(const data:AnsiString; const key:AnsiString):AnsiString;
  38. function DecryptNoHex(const data:AnsiString; const key:AnsiString):AnsiString;
  39. function HexToStr(const Str: AnsiString): AnsiString;
  40. implementation
  41. type
  42. TLongWordDynArray = array of LongWord;
  43. const
  44. delta:Longword = $9e3779b9;
  45. function HexToStr(const Str: AnsiString): AnsiString;
  46. asm
  47. push ebx
  48. push edi
  49. push esi
  50. test eax,eax //为空串
  51. jz @@Exit
  52. mov edi,eax
  53. mov esi,edx
  54. mov edx,[eax-4]
  55. test edx,edx
  56. je @@Exit
  57. mov ecx,edx
  58. push ecx
  59. shr edx,1
  60. mov eax,esi //开始构造字符串
  61. {$IFDEF VER210}
  62. movzx ecx, word ptr [edi-12] {需要设置CodePage}
  63. {$ENDIF}
  64. call System.@LStrSetLength //设置新串长度
  65. mov eax,esi //新字符串地址
  66. Call UniqueString //产生一个唯一的新字符串,串位置在eax中
  67. Pop ecx
  68. xor ebx,ebx
  69. xor esi,esi
  70. @@CharFromHex:
  71. xor edx,edx
  72. mov dl, [edi] //Str字符串字符
  73. cmp dl, '0' //查看是否在0到f之间的字符
  74. JB @@Exit //小于0,退出
  75. cmp dl,'9' //小于=9
  76. ja @@DoChar//CompOkNum
  77. sub dl,'0'
  78. jmp @@DoConvert
  79. @@DoChar:
  80. //先转成大写字符
  81. and dl,$DF
  82. cmp dl,'F'
  83. ja @@Exit //大于F退出
  84. add dl,10
  85. sub dl,'A'
  86. @@DoConvert: //转化
  87. inc ebx
  88. cmp ebx,2
  89. je @@Num1
  90. xor esi,esi
  91. shl edx,4
  92. mov esi,edx
  93. jmp @@Num2
  94. @@Num1:
  95. add esi,edx
  96. mov edx,esi
  97. mov [eax],dl
  98. xor ebx,ebx
  99. inc eax
  100. @@Num2:
  101. dec ecx
  102. inc edi
  103. test ecx,ecx
  104. jnz @@CharFromHex
  105. @@Exit:
  106. pop esi
  107. pop edi
  108. pop ebx
  109. end;
  110. function StrToHex(Const str: Ansistring): Ansistring;
  111. asm
  112. push ebx
  113. push esi
  114. push edi
  115. test eax,eax
  116. jz @@Exit
  117. mov esi,edx //保存edx值,用来产生新字符串的地址
  118. mov edi,eax //保存原字符串
  119. mov edx,[eax-4] //获得字符串长度
  120. test edx,edx //检查长度
  121. je @@Exit {Length(S) = 0}
  122. mov ecx,edx //保存长度
  123. Push ecx
  124. shl edx,1
  125. mov eax,esi
  126. movzx ecx, word ptr [edi-12] {需要设置CodePage}
  127. call System.@LStrSetLength //设置新串长度
  128. mov eax,esi //新字符串地址
  129. Call UniqueString //产生一个唯一的新字符串,串位置在eax中
  130. Pop ecx
  131. @@SetHex:
  132. xor edx,edx //清空edx
  133. mov dl, [edi] //Str字符串字符
  134. mov ebx,edx //保存当前的字符
  135. shr edx,4 //右移4字节,得到高8位
  136. mov dl,byte ptr[edx+@@HexChar] //转换成字符
  137. mov [eax],dl //将字符串输入到新建串中存放
  138. and ebx,$0F //获得低8位
  139. mov dl,byte ptr[ebx+@@HexChar] //转换成字符
  140. inc eax //移动一个字节,存放低位
  141. mov [eax],dl
  142. inc edi
  143. inc eax
  144. loop @@SetHex
  145. @@Exit:
  146. pop edi
  147. pop esi
  148. pop ebx
  149. ret
  150. @@HexChar: db '0123456789ABCDEF'
  151. end;
  152. function StrToArray(const data:AnsiString; includeLength:Boolean):TLongWordDynArray;
  153. var
  154. n, i:LongWord;
  155. begin
  156. n := Length(data);
  157. if ((n and 3) = 0) then n := n shr 2 else n := (n shr 2) + 1;
  158. if (includeLength) then begin
  159. setLength(result, n + 1);
  160. result[n] := Length(data);
  161. end else begin
  162. setLength(result, n);
  163. end;
  164. n := Length(data);
  165. for i := 0 to n - 1 do begin
  166. result[i shr 2] := result[i shr 2] or (($000000ff and ord(data[i + 1])) shl ((i and 3) shl 3));
  167. end;
  168. end;
  169. function ArrayToStr(const data:TLongWordDynArray; includeLength:Boolean):AnsiString;
  170. var
  171. n, m, i:LongWord;
  172. begin
  173. n := Length(data) shl 2;
  174. if (includeLength) then
  175. begin
  176. m := data[Length(data) - 1];
  177. if (m > n) then
  178. begin
  179. result := '';
  180. exit;
  181. end
  182. else
  183. begin
  184. n := m;
  185. end;
  186. end;
  187. SetLength(result, n);
  188. for i := 0 to n - 1 do
  189. begin
  190. result[i + 1] := AnsiChar(chr((data[i shr 2] shr ((i and 3) shl 3)) and $ff));
  191. end;
  192. end;
  193. function XXTeaEncrypt(const v:TLongWordDynArray; var k:TLongWordDynArray):TLongWordDynArray;
  194. var
  195. n, z, y, sum, e, p, q:LongWord;
  196. function MX:LongWord;
  197. begin
  198. result := (((z shr 5) xor (y shl 2)) + ((y shr 3) xor (z shl 4))) xor ((sum xor y) + (k[p and 3 xor e] xor z));
  199. end;
  200. begin
  201. n := Length(v) - 1;
  202. if (n < 1) then
  203. begin
  204. result := v;
  205. exit;
  206. end;
  207. if Length(k) < 4 then
  208. setLength(k, 4);
  209. z := v[n];
  210. y := v[0];
  211. sum := 0;
  212. q := 6 + 52 div (n + 1);
  213. repeat
  214. inc(sum, delta);
  215. e := (sum shr 2) and 3;
  216. for p := 0 to n - 1 do
  217. begin
  218. y := v[p + 1];
  219. inc(v[p], mx());
  220. z := v[p];
  221. end;
  222. p := n;
  223. y := v[0];
  224. inc(v[p], mx());
  225. z := v[p];
  226. dec(q);
  227. until q = 0;
  228. result := v;
  229. end;
  230. function XXTeaDecrypt(const v:TLongWordDynArray; var k:TLongWordDynArray):TLongWordDynArray;
  231. var
  232. n, z, y, sum, e, p, q:LongWord;
  233. function MX:LongWord;
  234. begin
  235. result := (((z shr 5) xor (y shl 2)) + ((y shr 3) xor (z shl 4))) xor ((sum xor y) + (k[p and 3 xor e] xor z));
  236. end;
  237. begin
  238. n := Length(v) - 1;
  239. if (n < 1) then begin
  240. result := v;
  241. exit;
  242. end;
  243. if Length(k) < 4 then setLength(k, 4);
  244. z := v[n];
  245. y := v[0];
  246. q := 6 + 52 div (n + 1);
  247. sum := q * delta;
  248. while (sum <> 0) do begin
  249. e := (sum shr 2) and 3;
  250. for p := n downto 1 do begin
  251. z := v[p - 1];
  252. dec(v[p], mx());
  253. y := v[p];
  254. end;
  255. p := 0;
  256. z := v[n];
  257. dec(v[0], mx());
  258. y := v[0];
  259. dec(sum, delta);
  260. end;
  261. result := v;
  262. end;
  263. //9E 40 C2 51 867F 35 64 2A 6D B1 9C 91 48 9715
  264. //9E 40 C2 51 3F 35 64 2A 6D B1 9C 91 48 3F
  265. function Encrypt(const data:AnsiString; const key:AnsiString):AnsiString;
  266. var
  267. v, k,c:TLongWordDynArray;
  268. s : AnsiString;
  269. begin
  270. if (Length(data) = 0) then exit;
  271. v := StrToArray(data, true);
  272. k := StrToArray(key, false);
  273. s := ArrayToStr(XXTeaEncrypt(v, k), False);
  274. Result := StrToHex(s);
  275. end;
  276. function Decrypt(const data:AnsiString; const key:AnsiString):AnsiString;
  277. var
  278. v, k,c:TLongWordDynArray;
  279. s :AnsiString;
  280. begin
  281. if (Length(data) = 0) then exit;
  282. v := StrToArray(data, false);
  283. k := StrToArray(key, false);
  284. Result := ArrayToStr(XXTeaDecrypt(v, k), False);
  285. Result := StrToHex(Result);
  286. end;
  287. function DecryptNoHex(const data:AnsiString; const key:AnsiString):AnsiString;
  288. var
  289. v, k,c:TLongWordDynArray;
  290. s :AnsiString;
  291. begin
  292. if (Length(data) = 0) then exit;
  293. v := StrToArray(data, false);
  294. k := StrToArray(key, false);
  295. Result := ArrayToStr(XXTeaDecrypt(v, k), False);
  296. // Result := StrToHex(Result);
  297. end;
  298. end.