DESCryptoServiceProvider.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // System.Security.Cryptography.DESCryptoServiceProvider
  3. //
  4. // Author:
  5. // Sergey Chaban ([email protected])
  6. //
  7. using System;
  8. using System.Security.Cryptography;
  9. namespace System.Security.Cryptography {
  10. internal class DESTransformBase : ICryptoTransform {
  11. internal enum Mode : int {
  12. ENCRYPTOR = 0,
  13. DECRYPTOR = 1
  14. }
  15. protected delegate void Filter (byte [] workBuff);
  16. private DESCore core;
  17. private DESCore.DESCall cryptFn;
  18. private Filter preprocess;
  19. private Filter postprocess;
  20. private byte [] iv;
  21. private byte [] tmpBlock;
  22. protected DESTransformBase (Mode mode, byte [] key, byte [] iv)
  23. {
  24. core = new DESCore ();
  25. if (mode == Mode.ENCRYPTOR) {
  26. cryptFn = new DESCore.DESCall (core.Encrypt);
  27. preprocess = new Filter (this.EncPreprocess);
  28. postprocess = new Filter (this.EncPostprocess);
  29. } else {
  30. cryptFn = new DESCore.DESCall (core.Decrypt);
  31. preprocess = new Filter (this.DecPreprocess);
  32. postprocess = new Filter (this.DecPostprocess);
  33. }
  34. core.SetKey (key);
  35. this.iv = new byte [DESCore.BLOCK_BYTE_SIZE];
  36. Array.Copy (iv, 0, this.iv, 0, DESCore.BLOCK_BYTE_SIZE);
  37. tmpBlock = new byte [DESCore.BLOCK_BYTE_SIZE];
  38. }
  39. public virtual bool CanTransformMultipleBlocks {
  40. get {
  41. return true;
  42. }
  43. }
  44. public virtual int InputBlockSize {
  45. get {
  46. return DESCore.BLOCK_BYTE_SIZE;
  47. }
  48. }
  49. public virtual int OutputBlockSize {
  50. get {
  51. return DESCore.BLOCK_BYTE_SIZE;
  52. }
  53. }
  54. private void EncPreprocess (byte [] workBuff)
  55. {
  56. byte [] iv = this.iv;
  57. for (int i = 0; i < DESCore.BLOCK_BYTE_SIZE; i++) {
  58. workBuff [i] ^= iv [i];
  59. }
  60. }
  61. private void EncPostprocess (byte [] workBuff)
  62. {
  63. Array.Copy (workBuff, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
  64. }
  65. private void DecPreprocess (byte [] workBuff)
  66. {
  67. Array.Copy (workBuff, 0, tmpBlock, 0, DESCore.BLOCK_BYTE_SIZE);
  68. }
  69. private void DecPostprocess (byte [] workBuff)
  70. {
  71. EncPreprocess (workBuff);
  72. Array.Copy (tmpBlock, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
  73. }
  74. private void Transform (byte [] workBuff)
  75. {
  76. preprocess (workBuff);
  77. cryptFn (workBuff, null);
  78. postprocess (workBuff);
  79. }
  80. public virtual int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
  81. {
  82. if ((inputCount & (DESCore.BLOCK_BYTE_SIZE-1)) != 0)
  83. throw new CryptographicException ("Invalid input block size.");
  84. if (outputOffset + inputCount > outputBuffer.Length)
  85. throw new CryptographicException ("Insufficient output buffer size.");
  86. int step = InputBlockSize;
  87. int offs = inputOffset;
  88. int full = inputCount / step;
  89. byte [] workBuff = new byte [step];
  90. for (int i = 0; i < full; i++) {
  91. Array.Copy (inputBuffer, offs, workBuff, 0, step);
  92. Transform (workBuff);
  93. Array.Copy (workBuff, 0, outputBuffer, outputOffset, step);
  94. offs += step;
  95. outputOffset += step;
  96. }
  97. return (full * step);
  98. }
  99. public virtual byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
  100. {
  101. // TODO: add decryption support
  102. int num = (inputCount + DESCore.BLOCK_BYTE_SIZE) & (~(DESCore.BLOCK_BYTE_SIZE-1));
  103. byte [] res = new byte [num];
  104. int full = num - DESCore.BLOCK_BYTE_SIZE;
  105. TransformBlock (inputBuffer, inputOffset, full, res, 0);
  106. int rem = inputCount & (DESCore.BLOCK_BYTE_SIZE-1);
  107. // PKCS-5 padding
  108. for (int i = num; --i >= (num - rem);) {
  109. res [i] = (byte) rem;
  110. }
  111. Array.Copy (inputBuffer, inputOffset + full, res, full, rem);
  112. // the last padded block will be transformed in-place
  113. TransformBlock (res, full, DESCore.BLOCK_BYTE_SIZE, res, full);
  114. /*
  115. byte [] workBuff = new byte [DESCore.BLOCK_BYTE_SIZE];
  116. Array.Copy (res, full, workBuff, 0, DESCore.BLOCK_BYTE_SIZE);
  117. preprocess (workBuff);
  118. cryptFn (workBuff, null);
  119. Array.Copy (workBuff, 0, res, full, DESCore.BLOCK_BYTE_SIZE);
  120. */
  121. return res;
  122. }
  123. } // DESTransformBase
  124. internal sealed class DESEncryptor : DESTransformBase {
  125. internal DESEncryptor (byte [] key, byte [] iv)
  126. : base (DESTransformBase.Mode.ENCRYPTOR, key, iv)
  127. {
  128. }
  129. } // DESEncryptor
  130. internal sealed class DESDecryptor : DESTransformBase {
  131. internal DESDecryptor (byte [] key, byte [] iv)
  132. : base (DESTransformBase.Mode.DECRYPTOR, key, iv)
  133. {
  134. }
  135. } // DESDecryptor
  136. public class DESCryptoServiceProvider {
  137. private byte [] iv;
  138. private byte [] key;
  139. public DESCryptoServiceProvider ()
  140. {
  141. }
  142. //
  143. // Factories
  144. //
  145. public virtual ICryptoTransform CreateEncryptor()
  146. {
  147. return new DESEncryptor (key, iv);
  148. }
  149. public virtual ICryptoTransform CreateDecryptor()
  150. {
  151. return new DESDecryptor (key, iv);
  152. }
  153. // FIXME: Ought to be in DES.cs
  154. public /*override*/ byte[] Key {
  155. get {
  156. return this.key;
  157. }
  158. set {
  159. this.key = new byte [DESCore.KEY_BYTE_SIZE];
  160. Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
  161. }
  162. }
  163. public virtual byte[] IV {
  164. get {
  165. return this.iv;
  166. }
  167. set {
  168. this.iv = new byte [DESCore.KEY_BYTE_SIZE];
  169. Array.Copy (value, 0, this.iv, 0, DESCore.KEY_BYTE_SIZE);
  170. }
  171. }
  172. public override string ToString ()
  173. {
  174. return "mono::System.Security.Cryptography.DESCryptoServiceProvider";
  175. }
  176. } // DESCryptoServiceProvider
  177. } // System.Security.Cryptography