DCPrijndael.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of Rijndael *****************************}
  5. {******************************************************************************}
  6. {* Copyright (c) 1999-2002 David Barton *}
  7. {* Permission is hereby granted, free of charge, to any person obtaining a *}
  8. {* copy of this software and associated documentation files (the "Software"), *}
  9. {* to deal in the Software without restriction, including without limitation *}
  10. {* the rights to use, copy, modify, merge, publish, distribute, sublicense, *}
  11. {* and/or sell copies of the Software, and to permit persons to whom the *}
  12. {* Software is furnished to do so, subject to the following conditions: *}
  13. {* *}
  14. {* The above copyright notice and this permission notice shall be included in *}
  15. {* all copies or substantial portions of the Software. *}
  16. {* *}
  17. {* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *}
  18. {* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *}
  19. {* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *}
  20. {* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *}
  21. {* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *}
  22. {* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *}
  23. {* DEALINGS IN THE SOFTWARE. *}
  24. {******************************************************************************}
  25. unit DCPrijndael;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  29. const
  30. BC= 4;
  31. MAXROUNDS= 14;
  32. type
  33. TDCP_rijndael= class(TDCP_blockcipher128)
  34. protected
  35. numrounds: longword;
  36. rk, drk: array[0..MAXROUNDS,0..7] of DWord;
  37. procedure InitKey(const Key; Size: longword); override;
  38. public
  39. class function GetID: integer; override;
  40. class function GetAlgorithm: string; override;
  41. class function GetMaxKeySize: integer; override;
  42. class function SelfTest: boolean; override;
  43. procedure Burn; override;
  44. procedure EncryptECB(const InData; var OutData); override;
  45. procedure DecryptECB(const InData; var OutData); override;
  46. end;
  47. {******************************************************************************}
  48. {******************************************************************************}
  49. implementation
  50. {$R-}{$Q-}
  51. {$I DCPrijndael.inc}
  52. class function TDCP_rijndael.GetMaxKeySize: integer;
  53. begin
  54. Result:= 256;
  55. end;
  56. class function TDCP_rijndael.GetID: integer;
  57. begin
  58. Result:= DCP_rijndael;
  59. end;
  60. class function TDCP_rijndael.GetAlgorithm: string;
  61. begin
  62. Result:= 'Rijndael';
  63. end;
  64. class function TDCP_rijndael.SelfTest: boolean;
  65. const
  66. Key1: array[0..15] of byte=
  67. ($00,$01,$02,$03,$05,$06,$07,$08,$0A,$0B,$0C,$0D,$0F,$10,$11,$12);
  68. InData1: array[0..15] of byte=
  69. ($50,$68,$12,$A4,$5F,$08,$C8,$89,$B9,$7F,$59,$80,$03,$8B,$83,$59);
  70. OutData1: array[0..15] of byte=
  71. ($D8,$F5,$32,$53,$82,$89,$EF,$7D,$06,$B5,$06,$A4,$FD,$5B,$E9,$C9);
  72. Key2: array[0..23] of byte=
  73. ($A0,$A1,$A2,$A3,$A5,$A6,$A7,$A8,$AA,$AB,$AC,$AD,$AF,$B0,$B1,$B2,
  74. $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC);
  75. InData2: array[0..15] of byte=
  76. ($4F,$1C,$76,$9D,$1E,$5B,$05,$52,$C7,$EC,$A8,$4D,$EA,$26,$A5,$49);
  77. OutData2: array[0..15] of byte=
  78. ($F3,$84,$72,$10,$D5,$39,$1E,$23,$60,$60,$8E,$5A,$CB,$56,$05,$81);
  79. Key3: array[0..31] of byte=
  80. ($00,$01,$02,$03,$05,$06,$07,$08,$0A,$0B,$0C,$0D,$0F,$10,$11,$12,
  81. $14,$15,$16,$17,$19,$1A,$1B,$1C,$1E,$1F,$20,$21,$23,$24,$25,$26);
  82. InData3: array[0..15] of byte=
  83. ($5E,$25,$CA,$78,$F0,$DE,$55,$80,$25,$24,$D3,$8D,$A3,$FE,$44,$56);
  84. OutData3: array[0..15] of byte=
  85. ($E8,$B7,$2B,$4E,$8B,$E2,$43,$43,$8C,$9F,$FF,$1F,$0E,$20,$58,$72);
  86. var
  87. Block: array[0..15] of byte;
  88. Cipher: TDCP_rijndael;
  89. begin
  90. Cipher:= TDCP_rijndael.Create(nil);
  91. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  92. Cipher.EncryptECB(InData1,Block);
  93. Result:= boolean(CompareMem(@Block,@OutData1,16));
  94. Cipher.DecryptECB(Block,Block);
  95. Cipher.Burn;
  96. Result:= Result and boolean(CompareMem(@Block,@InData1,16));
  97. Cipher.Init(Key2,Sizeof(Key2)*8,nil);
  98. Cipher.EncryptECB(InData2,Block);
  99. Result:= Result and boolean(CompareMem(@Block,@OutData2,16));
  100. Cipher.DecryptECB(Block,Block);
  101. Cipher.Burn;
  102. Result:= Result and boolean(CompareMem(@Block,@InData2,16));
  103. Cipher.Init(Key3,Sizeof(Key3)*8,nil);
  104. Cipher.EncryptECB(InData3,Block);
  105. Result:= Result and boolean(CompareMem(@Block,@OutData3,16));
  106. Cipher.DecryptECB(Block,Block);
  107. Cipher.Burn;
  108. Result:= Result and boolean(CompareMem(@Block,@InData3,16));
  109. Cipher.Free;
  110. end;
  111. procedure InvMixColumn(a: PByteArray; BC: byte);
  112. var
  113. j: longword;
  114. begin
  115. for j:= 0 to (BC-1) do
  116. PDWord(@(a^[j*4]))^:= PDWord(@U1[a^[j*4+0]])^ xor
  117. PDWord(@U2[a^[j*4+1]])^ xor
  118. PDWord(@U3[a^[j*4+2]])^ xor
  119. PDWord(@U4[a^[j*4+3]])^;
  120. end;
  121. procedure TDCP_rijndael.InitKey(const Key; Size: longword);
  122. var
  123. KC, ROUNDS, j, r, t, rconpointer: longword;
  124. tk: array[0..MAXKC-1,0..3] of byte;
  125. begin
  126. Size:= Size div 8;
  127. FillChar(tk,Sizeof(tk),0);
  128. Move(Key,tk,Size);
  129. if Size<= 16 then
  130. begin
  131. KC:= 4;
  132. Rounds:= 10;
  133. end
  134. else if Size<= 24 then
  135. begin
  136. KC:= 6;
  137. Rounds:= 12;
  138. end
  139. else
  140. begin
  141. KC:= 8;
  142. Rounds:= 14;
  143. end;
  144. numrounds:= rounds;
  145. r:= 0;
  146. t:= 0;
  147. j:= 0;
  148. while (j< KC) and (r< (rounds+1)) do
  149. begin
  150. while (j< KC) and (t< BC) do
  151. begin
  152. rk[r,t]:= PDWord(@tk[j])^;
  153. Inc(j);
  154. Inc(t);
  155. end;
  156. if t= BC then
  157. begin
  158. t:= 0;
  159. Inc(r);
  160. end;
  161. end;
  162. rconpointer:= 0;
  163. while (r< (rounds+1)) do
  164. begin
  165. tk[0,0]:= tk[0,0] xor S[tk[KC-1,1]];
  166. tk[0,1]:= tk[0,1] xor S[tk[KC-1,2]];
  167. tk[0,2]:= tk[0,2] xor S[tk[KC-1,3]];
  168. tk[0,3]:= tk[0,3] xor S[tk[KC-1,0]];
  169. tk[0,0]:= tk[0,0] xor rcon[rconpointer];
  170. Inc(rconpointer);
  171. if KC<> 8 then
  172. begin
  173. for j:= 1 to (KC-1) do
  174. PDWord(@tk[j])^:= PDWord(@tk[j])^ xor PDWord(@tk[j-1])^;
  175. end
  176. else
  177. begin
  178. for j:= 1 to ((KC div 2)-1) do
  179. PDWord(@tk[j])^:= PDWord(@tk[j])^ xor PDWord(@tk[j-1])^;
  180. tk[KC div 2,0]:= tk[KC div 2,0] xor S[tk[KC div 2 - 1,0]];
  181. tk[KC div 2,1]:= tk[KC div 2,1] xor S[tk[KC div 2 - 1,1]];
  182. tk[KC div 2,2]:= tk[KC div 2,2] xor S[tk[KC div 2 - 1,2]];
  183. tk[KC div 2,3]:= tk[KC div 2,3] xor S[tk[KC div 2 - 1,3]];
  184. for j:= ((KC div 2) + 1) to (KC-1) do
  185. PDWord(@tk[j])^:= PDWord(@tk[j])^ xor PDWord(@tk[j-1])^;
  186. end;
  187. j:= 0;
  188. while (j< KC) and (r< (rounds+1)) do
  189. begin
  190. while (j< KC) and (t< BC) do
  191. begin
  192. rk[r,t]:= PDWord(@tk[j])^;
  193. Inc(j);
  194. Inc(t);
  195. end;
  196. if t= BC then
  197. begin
  198. Inc(r);
  199. t:= 0;
  200. end;
  201. end;
  202. end;
  203. Move(rk,drk,Sizeof(rk));
  204. for r:= 1 to (numrounds-1) do
  205. InvMixColumn(@drk[r],BC);
  206. end;
  207. procedure TDCP_rijndael.Burn;
  208. begin
  209. numrounds:= 0;
  210. FillChar(rk,Sizeof(rk),0);
  211. FillChar(drk,Sizeof(drk),0);
  212. inherited Burn;
  213. end;
  214. procedure TDCP_rijndael.EncryptECB(const InData; var OutData);
  215. var
  216. r: longword;
  217. tempb: array[0..MAXBC-1,0..3] of byte;
  218. a: array[0..MAXBC,0..3] of byte;
  219. begin
  220. if not fInitialized then
  221. raise EDCP_blockcipher.Create('Cipher not initialized');
  222. PDword(@a[0,0])^:= PDword(@InData)^;
  223. PDword(@a[1,0])^:= PDword(dword(@InData)+4)^;
  224. PDword(@a[2,0])^:= PDword(dword(@InData)+8)^;
  225. PDword(@a[3,0])^:= PDword(dword(@InData)+12)^;
  226. for r:= 0 to (numrounds-2) do
  227. begin
  228. PDWord(@tempb[0])^:= PDWord(@a[0])^ xor rk[r,0];
  229. PDWord(@tempb[1])^:= PDWord(@a[1])^ xor rk[r,1];
  230. PDWord(@tempb[2])^:= PDWord(@a[2])^ xor rk[r,2];
  231. PDWord(@tempb[3])^:= PDWord(@a[3])^ xor rk[r,3];
  232. PDWord(@a[0])^:= PDWord(@T1[tempb[0,0]])^ xor
  233. PDWord(@T2[tempb[1,1]])^ xor
  234. PDWord(@T3[tempb[2,2]])^ xor
  235. PDWord(@T4[tempb[3,3]])^;
  236. PDWord(@a[1])^:= PDWord(@T1[tempb[1,0]])^ xor
  237. PDWord(@T2[tempb[2,1]])^ xor
  238. PDWord(@T3[tempb[3,2]])^ xor
  239. PDWord(@T4[tempb[0,3]])^;
  240. PDWord(@a[2])^:= PDWord(@T1[tempb[2,0]])^ xor
  241. PDWord(@T2[tempb[3,1]])^ xor
  242. PDWord(@T3[tempb[0,2]])^ xor
  243. PDWord(@T4[tempb[1,3]])^;
  244. PDWord(@a[3])^:= PDWord(@T1[tempb[3,0]])^ xor
  245. PDWord(@T2[tempb[0,1]])^ xor
  246. PDWord(@T3[tempb[1,2]])^ xor
  247. PDWord(@T4[tempb[2,3]])^;
  248. end;
  249. PDWord(@tempb[0])^:= PDWord(@a[0])^ xor rk[numrounds-1,0];
  250. PDWord(@tempb[1])^:= PDWord(@a[1])^ xor rk[numrounds-1,1];
  251. PDWord(@tempb[2])^:= PDWord(@a[2])^ xor rk[numrounds-1,2];
  252. PDWord(@tempb[3])^:= PDWord(@a[3])^ xor rk[numrounds-1,3];
  253. a[0,0]:= T1[tempb[0,0],1];
  254. a[0,1]:= T1[tempb[1,1],1];
  255. a[0,2]:= T1[tempb[2,2],1];
  256. a[0,3]:= T1[tempb[3,3],1];
  257. a[1,0]:= T1[tempb[1,0],1];
  258. a[1,1]:= T1[tempb[2,1],1];
  259. a[1,2]:= T1[tempb[3,2],1];
  260. a[1,3]:= T1[tempb[0,3],1];
  261. a[2,0]:= T1[tempb[2,0],1];
  262. a[2,1]:= T1[tempb[3,1],1];
  263. a[2,2]:= T1[tempb[0,2],1];
  264. a[2,3]:= T1[tempb[1,3],1];
  265. a[3,0]:= T1[tempb[3,0],1];
  266. a[3,1]:= T1[tempb[0,1],1];
  267. a[3,2]:= T1[tempb[1,2],1];
  268. a[3,3]:= T1[tempb[2,3],1];
  269. PDWord(@a[0])^:= PDWord(@a[0])^ xor rk[numrounds,0];
  270. PDWord(@a[1])^:= PDWord(@a[1])^ xor rk[numrounds,1];
  271. PDWord(@a[2])^:= PDWord(@a[2])^ xor rk[numrounds,2];
  272. PDWord(@a[3])^:= PDWord(@a[3])^ xor rk[numrounds,3];
  273. PDword(@OutData)^:= PDword(@a[0,0])^;
  274. PDword(dword(@OutData)+4)^:= PDword(@a[1,0])^;
  275. PDword(dword(@OutData)+8)^:= PDword(@a[2,0])^;
  276. PDword(dword(@OutData)+12)^:= PDword(@a[3,0])^;
  277. end;
  278. procedure TDCP_rijndael.DecryptECB(const InData; var OutData);
  279. var
  280. r: longword;
  281. tempb: array[0..MAXBC-1,0..3] of byte;
  282. a: array[0..MAXBC,0..3] of byte;
  283. begin
  284. if not fInitialized then
  285. raise EDCP_blockcipher.Create('Cipher not initialized');
  286. PDword(@a[0,0])^:= PDword(@InData)^;
  287. PDword(@a[1,0])^:= PDword(dword(@InData)+4)^;
  288. PDword(@a[2,0])^:= PDword(dword(@InData)+8)^;
  289. PDword(@a[3,0])^:= PDword(dword(@InData)+12)^;
  290. for r:= NumRounds downto 2 do
  291. begin
  292. PDWord(@tempb[0])^:= PDWord(@a[0])^ xor drk[r,0];
  293. PDWord(@tempb[1])^:= PDWord(@a[1])^ xor drk[r,1];
  294. PDWord(@tempb[2])^:= PDWord(@a[2])^ xor drk[r,2];
  295. PDWord(@tempb[3])^:= PDWord(@a[3])^ xor drk[r,3];
  296. PDWord(@a[0])^:= PDWord(@T5[tempb[0,0]])^ xor
  297. PDWord(@T6[tempb[3,1]])^ xor
  298. PDWord(@T7[tempb[2,2]])^ xor
  299. PDWord(@T8[tempb[1,3]])^;
  300. PDWord(@a[1])^:= PDWord(@T5[tempb[1,0]])^ xor
  301. PDWord(@T6[tempb[0,1]])^ xor
  302. PDWord(@T7[tempb[3,2]])^ xor
  303. PDWord(@T8[tempb[2,3]])^;
  304. PDWord(@a[2])^:= PDWord(@T5[tempb[2,0]])^ xor
  305. PDWord(@T6[tempb[1,1]])^ xor
  306. PDWord(@T7[tempb[0,2]])^ xor
  307. PDWord(@T8[tempb[3,3]])^;
  308. PDWord(@a[3])^:= PDWord(@T5[tempb[3,0]])^ xor
  309. PDWord(@T6[tempb[2,1]])^ xor
  310. PDWord(@T7[tempb[1,2]])^ xor
  311. PDWord(@T8[tempb[0,3]])^;
  312. end;
  313. PDWord(@tempb[0])^:= PDWord(@a[0])^ xor drk[1,0];
  314. PDWord(@tempb[1])^:= PDWord(@a[1])^ xor drk[1,1];
  315. PDWord(@tempb[2])^:= PDWord(@a[2])^ xor drk[1,2];
  316. PDWord(@tempb[3])^:= PDWord(@a[3])^ xor drk[1,3];
  317. a[0,0]:= S5[tempb[0,0]];
  318. a[0,1]:= S5[tempb[3,1]];
  319. a[0,2]:= S5[tempb[2,2]];
  320. a[0,3]:= S5[tempb[1,3]];
  321. a[1,0]:= S5[tempb[1,0]];
  322. a[1,1]:= S5[tempb[0,1]];
  323. a[1,2]:= S5[tempb[3,2]];
  324. a[1,3]:= S5[tempb[2,3]];
  325. a[2,0]:= S5[tempb[2,0]];
  326. a[2,1]:= S5[tempb[1,1]];
  327. a[2,2]:= S5[tempb[0,2]];
  328. a[2,3]:= S5[tempb[3,3]];
  329. a[3,0]:= S5[tempb[3,0]];
  330. a[3,1]:= S5[tempb[2,1]];
  331. a[3,2]:= S5[tempb[1,2]];
  332. a[3,3]:= S5[tempb[0,3]];
  333. PDWord(@a[0])^:= PDWord(@a[0])^ xor drk[0,0];
  334. PDWord(@a[1])^:= PDWord(@a[1])^ xor drk[0,1];
  335. PDWord(@a[2])^:= PDWord(@a[2])^ xor drk[0,2];
  336. PDWord(@a[3])^:= PDWord(@a[3])^ xor drk[0,3];
  337. PDword(@OutData)^:= PDword(@a[0,0])^;
  338. PDword(dword(@OutData)+4)^:= PDword(@a[1,0])^;
  339. PDword(dword(@OutData)+8)^:= PDword(@a[2,0])^;
  340. PDword(dword(@OutData)+12)^:= PDword(@a[3,0])^;
  341. end;
  342. end.