1. (**************************************************************)
  2. (* Advanced Encryption Standard (AES) *)
  3. (* Interface Unit v1.3 *)
  4. (* *)
  5. (* Copyright (c) 2002 Jorlen Young *)
  6. (* *)
  7. (* 说明: *)
  8. (* 基于 ElASE.pas 单元封装 *)
  9. (* *)
  10. (* 这是一个 AES 加密算法的标准接口。 *)
  11. (* 调用示例: *)
  12. (* if not EncryptStream(src, key, TStream(Dest), keybit) then *)
  13. (* showmessage('encrypt error'); *)
  14. (* *)
  15. (* if not DecryptStream(src, key, TStream(Dest), keybit) then *)
  16. (* showmessage('encrypt error'); *)
  17. (* *)
  18. (* *** 一定要对Dest进行TStream(Dest) *** *)
  19. (* ========================================================== *)
  20. (* *)
  21. (* 支持 128 / 192 / 256 位的密匙 *)
  22. (* 默认情况下按照 128 位密匙操作 *)
  23. (* *)
  24. (**************************************************************)
  25.  
  26. unit AES;
  27.  
  28. interface
  29.  
  30. {$IFDEF VER210}
  31. {$WARN IMPLICIT_STRING_CAST OFF} //关闭警告
  32. {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
  33. {$ENDIF}
  34. uses
  35. SysUtils, Classes, Math, ElAES;
  36.  
  37. const
  38. SDestStreamNotCreated = 'Dest stream not created.';
  39. SEncryptStreamError = 'Encrypt stream error.';
  40. SDecryptStreamError = 'Decrypt stream error.';
  41.  
  42. type
  43. TKeyBit = (kb128, kb192, kb256);
  44.  
  45. function StrToHex(Const str: AnsiString): AnsiString;
  46. function HexToStr(const Str: AnsiString): AnsiString;
  47.  
  48. function EncryptString(Value: AnsiString; Key: AnsiString;
  49. KeyBit: TKeyBit = kb128): AnsiString;
  50. function DecryptString(Value: AnsiString; Key: AnsiString;
  51. KeyBit: TKeyBit = kb128): AnsiString;
  52.  
  53. function EncryptStream(Src: TStream; Key: AnsiString;
  54. var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
  55. function DecryptStream(Src: TStream; Key: AnsiString;
  56. var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
  57.  
  58. procedure EncryptFile(SourceFile, DestFile: String;
  59. Key: AnsiString; KeyBit: TKeyBit = kb128);
  60. procedure DecryptFile(SourceFile, DestFile: String;
  61. Key: AnsiString; KeyBit: TKeyBit = kb128);
  62.  
  63. implementation
  64.  
  65. function StrToHex(Const str: Ansistring): Ansistring;
  66. asm
  67. push ebx
  68. push esi
  69. push edi
  70. test eax,eax
  71. jz @@Exit
  72. mov esi,edx //保存edx值,用来产生新字符串的地址
  73. mov edi,eax //保存原字符串
  74. mov edx,[eax-] //获得字符串长度
  75. test edx,edx //检查长度
  76. je @@Exit {Length(S) = 0}
  77. mov ecx,edx //保存长度
  78. Push ecx
  79. shl edx,
  80. mov eax,esi
  81. {$IFDEF VER210}
  82. movzx ecx, word ptr [edi-] {需要设置CodePage}
  83. {$ENDIF}
  84. call System.@LStrSetLength //设置新串长度
  85. mov eax,esi //新字符串地址
  86. Call UniqueString //产生一个唯一的新字符串,串位置在eax中
  87. Pop ecx
  88. @@SetHex:
  89. xor edx,edx //清空edx
  90. mov dl, [edi] //Str字符串字符
  91. mov ebx,edx //保存当前的字符
  92. shr edx, //右移4字节,得到高8位
  93. mov dl,byte ptr[edx+@@HexChar] //转换成字符
  94. mov [eax],dl //将字符串输入到新建串中存放
  95. and ebx,$0F //获得低8位
  96. mov dl,byte ptr[ebx+@@HexChar] //转换成字符
  97. inc eax //移动一个字节,存放低位
  98. mov [eax],dl
  99. inc edi
  100. inc eax
  101. loop @@SetHex
  102. @@Exit:
  103. pop edi
  104. pop esi
  105. pop ebx
  106. ret
  107. @@HexChar: db '0123456789ABCDEF'
  108. end;
  109.  
  110. function HexToStr(const Str: AnsiString): AnsiString;
  111. asm
  112. push ebx
  113. push edi
  114. push esi
  115. test eax,eax //为空串
  116. jz @@Exit
  117. mov edi,eax
  118. mov esi,edx
  119. mov edx,[eax-]
  120. test edx,edx
  121. je @@Exit
  122. mov ecx,edx
  123. push ecx
  124. shr edx,
  125. mov eax,esi //开始构造字符串
  126. {$IFDEF VER210}
  127. movzx ecx, word ptr [edi-] {需要设置CodePage}
  128. {$ENDIF}
  129. call System.@LStrSetLength //设置新串长度
  130. mov eax,esi //新字符串地址
  131. Call UniqueString //产生一个唯一的新字符串,串位置在eax中
  132. Pop ecx
  133. xor ebx,ebx
  134. xor esi,esi
  135. @@CharFromHex:
  136. xor edx,edx
  137. mov dl, [edi] //Str字符串字符
  138. cmp dl, '' //查看是否在0到f之间的字符
  139. JB @@Exit //小于0,退出
  140. cmp dl,'' //小于=
  141. ja @@DoChar//CompOkNum
  142. sub dl,''
  143. jmp @@DoConvert
  144. @@DoChar:
  145. //先转成大写字符
  146. and dl,$DF
  147. cmp dl,'F'
  148. ja @@Exit //大于F退出
  149. add dl,
  150. sub dl,'A'
  151. @@DoConvert: //转化
  152. inc ebx
  153. cmp ebx,
  154. je @@Num1
  155. xor esi,esi
  156. shl edx,
  157. mov esi,edx
  158. jmp @@Num2
  159. @@Num1:
  160. add esi,edx
  161. mov edx,esi
  162. mov [eax],dl
  163. xor ebx,ebx
  164. inc eax
  165. @@Num2:
  166. dec ecx
  167. inc edi
  168. test ecx,ecx
  169. jnz @@CharFromHex
  170. @@Exit:
  171. pop esi
  172. pop edi
  173. pop ebx
  174. end;
  175.  
  176. { -- 字符串加密函数 默认按照 128 位密匙加密 -- }
  177. function EncryptString(Value: AnsiString; Key: AnsiString;
  178. KeyBit: TKeyBit = kb128): AnsiString;
  179. var
  180. {$IFDEF VER210}
  181. SS,DS: TMemoryStream;
  182. {$ELSE}
  183. SS, DS: TStringStream;
  184. {$ENDIF}
  185. Size: Int64;
  186. AESKey128: TAESKey128;
  187. AESKey192: TAESKey192;
  188. AESKey256: TAESKey256;
  189. st: AnsiString;
  190. begin
  191. Result := '';
  192. {$IFDEF VER210}
  193. ss := TMemoryStream.Create;
  194. SS.WriteBuffer(PAnsiChar(Value)^,Length(Value));
  195. DS := TMemoryStream.Create;
  196. {$ELSE}
  197. SS := TStringStream.Create(Value);
  198. DS := TStringStream.Create('');
  199. {$ENDIF}
  200. try
  201. Size := SS.Size;
  202. DS.WriteBuffer(Size, SizeOf(Size));
  203. { -- 128 位密匙最大长度为 16 个字符 -- }
  204. if KeyBit = kb128 then
  205. begin
  206. FillChar(AESKey128, SizeOf(AESKey128), );
  207. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  208. EncryptAESStreamECB(SS, , AESKey128, DS);
  209. end;
  210. { -- 192 位密匙最大长度为 24 个字符 -- }
  211. if KeyBit = kb192 then
  212. begin
  213. FillChar(AESKey192, SizeOf(AESKey192), );
  214. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  215. EncryptAESStreamECB(SS, , AESKey192, DS);
  216. end;
  217. { -- 256 位密匙最大长度为 32 个字符 -- }
  218. if KeyBit = kb256 then
  219. begin
  220. FillChar(AESKey256, SizeOf(AESKey256), );
  221. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  222. EncryptAESStreamECB(SS, , AESKey256, DS);
  223. end;
  224. {$IFDEF VER210}
  225. SetLength(st,Ds.Size);
  226. DS.Position := ;
  227. DS.ReadBuffer(PAnsiChar(st)^,DS.Size);
  228. Result := StrToHex(st);
  229. {$ELSE}
  230. Result := StrToHex(DS.DataString);
  231. {$ENDIF}
  232. finally
  233. SS.Free;
  234. DS.Free;
  235. end;
  236. end;
  237.  
  238. { -- 字符串解密函数 默认按照 128 位密匙解密 -- }
  239. function DecryptString(Value: AnsiString; Key: AnsiString;
  240. KeyBit: TKeyBit = kb128): AnsiString;
  241. var
  242. SS, DS: TStringStream;
  243. Size: Int64;
  244. AESKey128: TAESKey128;
  245. AESKey192: TAESKey192;
  246. AESKey256: TAESKey256;
  247. begin
  248. Result := '';
  249. SS := TStringStream.Create(HexToStr(Value));
  250. DS := TStringStream.Create('');
  251. try
  252. Size := SS.Size;
  253. SS.ReadBuffer(Size, SizeOf(Size));
  254. { -- 128 位密匙最大长度为 16 个字符 -- }
  255. if KeyBit = kb128 then
  256. begin
  257. FillChar(AESKey128, SizeOf(AESKey128), );
  258. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  259. DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey128, DS);
  260. end;
  261. { -- 192 位密匙最大长度为 24 个字符 -- }
  262. if KeyBit = kb192 then
  263. begin
  264. FillChar(AESKey192, SizeOf(AESKey192), );
  265. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  266. DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey192, DS);
  267. end;
  268. { -- 256 位密匙最大长度为 32 个字符 -- }
  269. if KeyBit = kb256 then
  270. begin
  271. FillChar(AESKey256, SizeOf(AESKey256), );
  272. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  273. DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey256, DS);
  274. end;
  275. Result := DS.DataString;
  276. finally
  277. SS.Free;
  278. DS.Free;
  279. end;
  280. end;
  281.  
  282. { 流加密函数, default keybit: 128bit }
  283. function EncryptStream(Src: TStream; Key: AnsiString;
  284. var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
  285. var
  286. Count: Int64;
  287. AESKey128: TAESKey128;
  288. AESKey192: TAESKey192;
  289. AESKey256: TAESKey256;
  290. begin
  291. if Dest = nil then
  292. begin
  293. raise Exception.Create(SDestStreamNotCreated);
  294. Result:= False;
  295. Exit;
  296. end;
  297.  
  298. try
  299. Src.Position:= ;
  300. Count:= Src.Size;
  301. Dest.Write(Count, SizeOf(Count));
  302. { -- 128 位密匙最大长度为 16 个字符 -- }
  303. if KeyBit = kb128 then
  304. begin
  305. FillChar(AESKey128, SizeOf(AESKey128), );
  306. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  307. EncryptAESStreamECB(Src, , AESKey128, Dest);
  308. end;
  309. { -- 192 位密匙最大长度为 24 个字符 -- }
  310. if KeyBit = kb192 then
  311. begin
  312. FillChar(AESKey192, SizeOf(AESKey192), );
  313. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  314. EncryptAESStreamECB(Src, , AESKey192, Dest);
  315. end;
  316. { -- 256 位密匙最大长度为 32 个字符 -- }
  317. if KeyBit = kb256 then
  318. begin
  319. FillChar(AESKey256, SizeOf(AESKey256), );
  320. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  321. EncryptAESStreamECB(Src, , AESKey256, Dest);
  322. end;
  323.  
  324. Result := True;
  325. except
  326. raise Exception.Create(SEncryptStreamError);
  327. Result:= False;
  328. end;
  329. end;
  330.  
  331. { 流解密函数, default keybit: 128bit }
  332. function DecryptStream(Src: TStream; Key: AnsiString;
  333. var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
  334. var
  335. Count, OutPos: Int64;
  336. AESKey128: TAESKey128;
  337. AESKey192: TAESKey192;
  338. AESKey256: TAESKey256;
  339. begin
  340. if Dest = nil then
  341. begin
  342. raise Exception.Create(SDestStreamNotCreated);
  343. Result:= False;
  344. Exit;
  345. end;
  346.  
  347. try
  348. Src.Position:= ;
  349. OutPos:= Dest.Position;
  350. Src.ReadBuffer(Count, SizeOf(Count));
  351. { -- 128 位密匙最大长度为 16 个字符 -- }
  352. if KeyBit = kb128 then
  353. begin
  354. FillChar(AESKey128, SizeOf(AESKey128), );
  355. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  356. DecryptAESStreamECB(Src, Src.Size - Src.Position,
  357. AESKey128, Dest);
  358. end;
  359. { -- 192 位密匙最大长度为 24 个字符 -- }
  360. if KeyBit = kb192 then
  361. begin
  362. FillChar(AESKey192, SizeOf(AESKey192), );
  363. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  364. DecryptAESStreamECB(Src, Src.Size - Src.Position,
  365. AESKey192, Dest);
  366. end;
  367. { -- 256 位密匙最大长度为 32 个字符 -- }
  368. if KeyBit = kb256 then
  369. begin
  370. FillChar(AESKey256, SizeOf(AESKey256), );
  371. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  372. DecryptAESStreamECB(Src, Src.Size - Src.Position,
  373. AESKey256, Dest);
  374. end;
  375. Dest.Size := OutPos + Count;
  376. Dest.Position := OutPos;
  377.  
  378. Result := True;
  379. except
  380. raise Exception.Create(SDecryptStreamError);
  381. Result:= False;
  382. end;
  383. end;
  384.  
  385. { -- 文件加密函数 默认按照 128 位密匙解密 -- }
  386. procedure EncryptFile(SourceFile, DestFile: String;
  387. Key: AnsiString; KeyBit: TKeyBit = kb128);
  388. var
  389. SFS, DFS: TFileStream;
  390. Size: Int64;
  391. AESKey128: TAESKey128;
  392. AESKey192: TAESKey192;
  393. AESKey256: TAESKey256;
  394. begin
  395. SFS := TFileStream.Create(SourceFile, fmOpenRead);
  396. try
  397. DFS := TFileStream.Create(DestFile, fmCreate);
  398. try
  399. Size := SFS.Size;
  400. DFS.WriteBuffer(Size, SizeOf(Size));
  401. { -- 128 位密匙最大长度为 16 个字符 -- }
  402. if KeyBit = kb128 then
  403. begin
  404. FillChar(AESKey128, SizeOf(AESKey128), );
  405. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  406. EncryptAESStreamECB(SFS, , AESKey128, DFS);
  407. end;
  408. { -- 192 位密匙最大长度为 24 个字符 -- }
  409. if KeyBit = kb192 then
  410. begin
  411. FillChar(AESKey192, SizeOf(AESKey192), );
  412. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  413. EncryptAESStreamECB(SFS, , AESKey192, DFS);
  414. end;
  415. { -- 256 位密匙最大长度为 32 个字符 -- }
  416. if KeyBit = kb256 then
  417. begin
  418. FillChar(AESKey256, SizeOf(AESKey256), );
  419. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  420. EncryptAESStreamECB(SFS, , AESKey256, DFS);
  421. end;
  422. finally
  423. DFS.Free;
  424. end;
  425. finally
  426. SFS.Free;
  427. end;
  428. end;
  429.  
  430. { -- 文件解密函数 默认按照 128 位密匙解密 -- }
  431. procedure DecryptFile(SourceFile, DestFile: String;
  432. Key: AnsiString; KeyBit: TKeyBit = kb128);
  433. var
  434. SFS, DFS: TFileStream;
  435. Size: Int64;
  436. AESKey128: TAESKey128;
  437. AESKey192: TAESKey192;
  438. AESKey256: TAESKey256;
  439. begin
  440. SFS := TFileStream.Create(SourceFile, fmOpenRead);
  441. try
  442. SFS.ReadBuffer(Size, SizeOf(Size));
  443. DFS := TFileStream.Create(DestFile, fmCreate);
  444. try
  445. { -- 128 位密匙最大长度为 16 个字符 -- }
  446. if KeyBit = kb128 then
  447. begin
  448. FillChar(AESKey128, SizeOf(AESKey128), );
  449. Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
  450. DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey128, DFS);
  451. end;
  452. { -- 192 位密匙最大长度为 24 个字符 -- }
  453. if KeyBit = kb192 then
  454. begin
  455. FillChar(AESKey192, SizeOf(AESKey192), );
  456. Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
  457. DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey192, DFS);
  458. end;
  459. { -- 256 位密匙最大长度为 32 个字符 -- }
  460. if KeyBit = kb256 then
  461. begin
  462. FillChar(AESKey256, SizeOf(AESKey256), );
  463. Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
  464. DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey256, DFS);
  465. end;
  466. DFS.Size := Size;
  467. finally
  468. DFS.Free;
  469. end;
  470. finally
  471. SFS.Free;
  472. end;
  473. end;
  474. end.

Delphi AES加密(转)的更多相关文章

  1. 透过 Delphi 使用二进位金钥做 AES 加密.

    从 1994 年开始,笔者就开始接触加密与网路安全的世界,从鲁立忠老师的指导当中获益良多,后来在台湾的元智大学就读研究所的时候,也以此为研究主题. 在当时,电子商务是显学,Visa跟 Master C ...

  2. 关于CryptoJS中md5加密以及aes加密的随笔

    最近项目中用到了各种加密,其中就包括从没有接触过得aes加密,因此从网上各种查,官方的一种说法: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学 ...

  3. AES加密

    package com.edu.hpu; import java.math.BigInteger; import java.security.MessageDigest; import java.se ...

  4. Android数据加密之Aes加密

    前言: 项目中除了登陆,支付等接口采用rsa非对称加密,之外的采用aes对称加密,今天我们来认识一下aes加密. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes ...

  5. c#和js互通的AES加密解密

    一.使用场景 在使用前后端分离的框架中常常会进行传输数据相互加密解密以确保数据的安全性,如web Api返回加密数据客户端或web端进行解密,或者客户端或web端进行加密提交数据服务端解密数据等等. ...

  6. AES加密解密通用版Object-C / C# / JAVA

    1.无向量 128位 /// <summary> /// AES加密(无向量) /// </summary> /// <param name="plainByt ...

  7. nodejs与javascript中的aes加密

    简介 1.aes加密简单来说,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.高级加密标准已然成为对称密钥加 ...

  8. 非对称技术栈实现AES加密解密

    非对称技术栈实现AES加密解密 正如前面的一篇文章所述,https协议的SSL层是实现在传输层之上,应用层之下,也就是说在应用层上看到的请求还是明码的,对于某些场景下要求这些http请求参数是非可读的 ...

  9. Java aes加密C#解密的取巧方法

    摘要: 项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦.Java的代码和C#的代码无法互通. Ja ...

随机推荐

  1. MyBatis无限输出日志

    最近在项目中使用mybatis与spring集成,由于项目使用maven分模块打包,经常遇到mybatis mapper少配置子模块或者maven pom中忘记引用子模块导致的mybatis加载不到d ...

  2. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  3. jQuery和javaScript页面加载完成时触发的事件

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. Pandas描述性统计

    有很多方法用来集体计算DataFrame的描述性统计信息和其他相关操作. 其中大多数是sum(),mean()等聚合函数,但其中一些,如sumsum(),产生一个相同大小的对象. 一般来说,这些方法采 ...

  5. Java多线程 - 控制线程

    join线程 在某个线程的执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的线程完成为止. join()方法有三种重载形式: join():等待被join的线程执 ...

  6. org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 语法分析器在此文档中遇到多个 "64,000" 实体扩展; 这是应用程序施加的限制

    使用SAX解析XML文件.XML文件有1.5G,程序抛出了这个问题: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 语法 ...

  7. SpringCloud分布式开发理解

    谈到SpringCloud最新接触到的可能就是那五大"神兽",之前最先接触分布式开发是通过dubbo的RPC远程过程调用,而dubbo给我得感觉就是:虽然所有的主机物理上分布了,但 ...

  8. easyui-textbox高为0

    之前在项目中也遇到过,一段时间没遇到这种问题居然又忘记了,想着还是在博客中记录一下,方便自己记忆,也供大家参考. 大家是否也遇到过easyui-textbox高为0的情况呢 像这样:  用户名:< ...

  9. 0 与 “0" 与 '\0' 与 '0'相互之间的区别

    1. '\0'和‘0’都是字符,对应的ASCII值分别是0和48. 2. 0表示一个数字.也可以表示ASCII值,对应字符'\0'. 3. “0”表示字符串,第一个字符是'0'.

  10. IOS-HTTP协议

    网络由下往上分为 物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用层, 三者从本质上来说没有可 ...