ClpMod.pas 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. { *********************************************************************************** }
  2. { * CryptoLib Library * }
  3. { * Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe * }
  4. { * Github Repository <https://github.com/Xor-el> * }
  5. { * Distributed under the MIT software license, see the accompanying file LICENSE * }
  6. { * or visit http://www.opensource.org/licenses/mit-license.php. * }
  7. { * Acknowledgements: * }
  8. { * * }
  9. { * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * }
  10. { * development of this library * }
  11. { * ******************************************************************************* * }
  12. (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
  13. unit ClpMod;
  14. {$I ..\..\Include\CryptoLib.inc}
  15. interface
  16. uses
  17. ClpCryptoLibTypes,
  18. {$IFDEF DELPHI}
  19. ClpBitConverter,
  20. {$ENDIF DELPHI}
  21. ClpNat,
  22. ClpConverters,
  23. ClpSecureRandom,
  24. ClpISecureRandom,
  25. SysUtils;
  26. resourcestring
  27. SCannotBeZero = 'cannot be 0, "x"';
  28. type
  29. TMod = class abstract(TObject)
  30. strict private
  31. class var
  32. FRandomSource: ISecureRandom;
  33. class constructor &Mod();
  34. class procedure InversionResult(p: TCryptoLibUInt32Array; ac: Int32;
  35. a: TCryptoLibUInt32Array; z: TCryptoLibUInt32Array); static; inline;
  36. class procedure InversionStep(p, u: TCryptoLibUInt32Array; uLen: Int32;
  37. x: TCryptoLibUInt32Array; var xc: Int32); static;
  38. public
  39. class procedure Invert(p, x, z: TCryptoLibUInt32Array); static;
  40. class function Random(p: TCryptoLibUInt32Array)
  41. : TCryptoLibUInt32Array; static;
  42. class procedure Add(p, x, y, z: TCryptoLibUInt32Array); static; inline;
  43. class procedure Subtract(p, x, y, z: TCryptoLibUInt32Array); static; inline;
  44. class function GetTrailingZeroes(x: UInt32): Int32; static; inline;
  45. end;
  46. implementation
  47. { TMod }
  48. class procedure TMod.Add(p, x, y, z: TCryptoLibUInt32Array);
  49. var
  50. len: Int32;
  51. c: UInt32;
  52. begin
  53. len := System.Length(p);
  54. c := TNat.Add(len, x, y, z);
  55. if (c <> 0) then
  56. begin
  57. TNat.SubFrom(len, p, z);
  58. end;
  59. end;
  60. class function TMod.GetTrailingZeroes(x: UInt32): Int32;
  61. var
  62. count: Int32;
  63. begin
  64. {$IFDEF DEBUG}
  65. System.Assert(x <> 0);
  66. {$ENDIF DEBUG}
  67. count := 0;
  68. while ((x and 1) = 0) do
  69. begin
  70. x := x shr 1;
  71. System.Inc(count);
  72. end;
  73. result := count;
  74. end;
  75. class procedure TMod.InversionResult(p: TCryptoLibUInt32Array; ac: Int32;
  76. a, z: TCryptoLibUInt32Array);
  77. begin
  78. if (ac < 0) then
  79. begin
  80. TNat.Add(System.Length(p), a, p, z);
  81. end
  82. else
  83. begin
  84. System.Move(a[0], z[0], System.Length(p) * System.SizeOf(UInt32));
  85. end;
  86. end;
  87. class procedure TMod.InversionStep(p, u: TCryptoLibUInt32Array; uLen: Int32;
  88. x: TCryptoLibUInt32Array; var xc: Int32);
  89. var
  90. len, count, zeroes, i: Int32;
  91. begin
  92. len := System.Length(p);
  93. count := 0;
  94. while (u[0] = 0) do
  95. begin
  96. TNat.ShiftDownWord(uLen, u, 0);
  97. count := count + 32;
  98. end;
  99. zeroes := GetTrailingZeroes(u[0]);
  100. if (zeroes > 0) then
  101. begin
  102. TNat.ShiftDownBits(uLen, u, zeroes, 0);
  103. count := count + zeroes;
  104. end;
  105. raise Exception.Create(
  106. u[0].ToString + ' DADA ' +
  107. u[1].ToString + ' DADA ' +
  108. u[2].ToString + ' DADA ' +
  109. u[3].ToString + ' DADA ' +
  110. u[4].ToString + ' DADA ' +
  111. u[5].ToString + ' DADA ' +
  112. u[6].ToString + ' DADA ' +
  113. u[7].ToString + ' DADA ');
  114. i := 0;
  115. while i < count do
  116. begin
  117. if ((x[0] and 1) <> 0) then
  118. begin
  119. if (xc < 0) then
  120. begin
  121. xc := xc + Int32(TNat.AddTo(len, p, x));
  122. end
  123. else
  124. begin
  125. xc := xc + (TNat.SubFrom(len, p, x));
  126. end;
  127. end;
  128. {$IFDEF DEBUG}
  129. System.Assert((xc = 0) or (xc = -1));
  130. {$ENDIF DEBUG}
  131. TNat.ShiftDownBit(len, x, UInt32(xc));
  132. System.Inc(i);
  133. end;
  134. end;
  135. class procedure TMod.Invert(p, x, z: TCryptoLibUInt32Array);
  136. var
  137. len, ac, bc, uvLen: Int32;
  138. u, a, v, b: TCryptoLibUInt32Array;
  139. begin
  140. len := System.Length(p);
  141. if (TNat.IsZero(len, x)) then
  142. begin
  143. raise EArgumentCryptoLibException.CreateRes(@SCannotBeZero);
  144. end;
  145. if (TNat.IsOne(len, x)) then
  146. begin
  147. System.Move(x[0], z[0], len * System.SizeOf(UInt32));
  148. Exit;
  149. end;
  150. u := TNat.Copy(len, x);
  151. a := TNat.Create(len);
  152. a[0] := 1;
  153. ac := 0;
  154. if ((u[0] and 1) = 0) then
  155. begin
  156. InversionStep(p, u, len, a, ac);
  157. end;
  158. if (TNat.IsOne(len, u)) then
  159. begin
  160. InversionResult(p, ac, a, z);
  161. Exit;
  162. end;
  163. v := TNat.Copy(len, p);
  164. b := TNat.Create(len);
  165. bc := 0;
  166. uvLen := len;
  167. while True do
  168. begin
  169. while ((u[uvLen - 1] = 0) and (v[uvLen - 1] = 0)) do
  170. begin
  171. System.Dec(uvLen);
  172. end;
  173. if (TNat.Gte(len, u, v)) then
  174. begin
  175. TNat.SubFrom(len, v, u);
  176. {$IFDEF DEBUG}
  177. System.Assert((u[0] and 1) = 0);
  178. {$ENDIF DEBUG}
  179. ac := ac + (TNat.SubFrom(len, b, a) - bc);
  180. InversionStep(p, u, uvLen, a, ac);
  181. if (TNat.IsOne(len, u)) then
  182. begin
  183. InversionResult(p, ac, a, z);
  184. Exit;
  185. end;
  186. end
  187. else
  188. begin
  189. TNat.SubFrom(len, u, v);
  190. {$IFDEF DEBUG}
  191. System.Assert((v[0] and 1) = 0);
  192. {$ENDIF DEBUG}
  193. bc := bc + (TNat.SubFrom(len, a, b) - ac);
  194. InversionStep(p, v, uvLen, b, bc);
  195. if (TNat.IsOne(len, v)) then
  196. begin
  197. InversionResult(p, bc, b, z);
  198. Exit;
  199. end;
  200. end;
  201. end;
  202. end;
  203. class constructor TMod.&Mod;
  204. begin
  205. TSecureRandom.Boot;
  206. FRandomSource := TSecureRandom.Create();
  207. end;
  208. class function TMod.Random(p: TCryptoLibUInt32Array): TCryptoLibUInt32Array;
  209. var
  210. len: Int32;
  211. m: UInt32;
  212. s: TCryptoLibUInt32Array;
  213. bytes: TCryptoLibByteArray;
  214. begin
  215. len := System.Length(p);
  216. s := TNat.Create(len);
  217. m := p[len - 1];
  218. m := m or (m shr 1);
  219. m := m or (m shr 2);
  220. m := m or (m shr 4);
  221. m := m or (m shr 8);
  222. m := m or (m shr 16);
  223. System.SetLength(bytes, len shl 2);
  224. repeat
  225. FRandomSource.NextBytes(bytes);
  226. TConverters.be32_copy(PByte(bytes), 0, PCardinal(s), 0, System.Length(s));
  227. s[len - 1] := s[len - 1] and m;
  228. until (not(TNat.Gte(len, s, p)));
  229. result := s;
  230. end;
  231. class procedure TMod.Subtract(p, x, y, z: TCryptoLibUInt32Array);
  232. var
  233. len, c: Int32;
  234. begin
  235. len := System.Length(p);
  236. c := TNat.Sub(len, x, y, z);
  237. if (c <> 0) then
  238. begin
  239. TNat.AddTo(len, p, z);
  240. end;
  241. end;
  242. end.