2 // System.Security.Cryptography.DESCryptoServiceProvider
5 // Sergey Chaban (serge@wildwestsoftware.com)
11 using System.Security.Cryptography;
14 namespace System.Security.Cryptography {
17 internal class DESTransformBase : ICryptoTransform {
19 internal enum Mode : int {
24 protected delegate void Filter (byte [] workBuff);
28 private DESCore.DESCall cryptFn;
29 private Filter preprocess;
30 private Filter postprocess;
33 private byte [] tmpBlock;
35 protected DESTransformBase (Mode mode, byte [] key, byte [] iv)
37 core = new DESCore ();
39 if (mode == Mode.ENCRYPTOR) {
40 cryptFn = new DESCore.DESCall (core.Encrypt);
41 preprocess = new Filter (this.EncPreprocess);
42 postprocess = new Filter (this.EncPostprocess);
44 cryptFn = new DESCore.DESCall (core.Decrypt);
45 preprocess = new Filter (this.DecPreprocess);
46 postprocess = new Filter (this.DecPostprocess);
50 this.iv = new byte [DESCore.BLOCK_BYTE_SIZE];
51 Array.Copy (iv, 0, this.iv, 0, DESCore.BLOCK_BYTE_SIZE);
53 tmpBlock = new byte [DESCore.BLOCK_BYTE_SIZE];
57 public virtual bool CanTransformMultipleBlocks {
64 public virtual int InputBlockSize {
66 return DESCore.BLOCK_BYTE_SIZE;
70 public virtual int OutputBlockSize {
72 return DESCore.BLOCK_BYTE_SIZE;
76 private void EncPreprocess (byte [] workBuff)
79 for (int i = 0; i < DESCore.BLOCK_BYTE_SIZE; i++) {
80 workBuff [i] ^= iv [i];
84 private void EncPostprocess (byte [] workBuff)
86 Array.Copy (workBuff, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
90 private void DecPreprocess (byte [] workBuff)
92 Array.Copy (workBuff, 0, tmpBlock, 0, DESCore.BLOCK_BYTE_SIZE);
95 private void DecPostprocess (byte [] workBuff)
97 EncPreprocess (workBuff);
98 Array.Copy (tmpBlock, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
103 private void Transform (byte [] workBuff)
105 preprocess (workBuff);
106 cryptFn (workBuff, null);
107 postprocess (workBuff);
111 public virtual int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
113 if ((inputCount & (DESCore.BLOCK_BYTE_SIZE-1)) != 0)
114 throw new CryptographicException ("Invalid input block size.");
116 if (outputOffset + inputCount > outputBuffer.Length)
117 throw new CryptographicException ("Insufficient output buffer size.");
119 int step = InputBlockSize;
120 int offs = inputOffset;
121 int full = inputCount / step;
123 byte [] workBuff = new byte [step];
125 for (int i = 0; i < full; i++) {
126 Array.Copy (inputBuffer, offs, workBuff, 0, step);
127 Transform (workBuff);
128 Array.Copy (workBuff, 0, outputBuffer, outputOffset, step);
130 outputOffset += step;
133 return (full * step);
138 public virtual byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
140 // TODO: add decryption support
142 int num = (inputCount + DESCore.BLOCK_BYTE_SIZE) & (~(DESCore.BLOCK_BYTE_SIZE-1));
143 byte [] res = new byte [num];
144 int full = num - DESCore.BLOCK_BYTE_SIZE;
146 TransformBlock (inputBuffer, inputOffset, full, res, 0);
148 int rem = inputCount & (DESCore.BLOCK_BYTE_SIZE-1);
151 for (int i = num; --i >= (num - rem);) {
152 res [i] = (byte) rem;
155 Array.Copy (inputBuffer, inputOffset + full, res, full, rem);
157 // the last padded block will be transformed in-place
158 TransformBlock (res, full, DESCore.BLOCK_BYTE_SIZE, res, full);
161 byte [] workBuff = new byte [DESCore.BLOCK_BYTE_SIZE];
162 Array.Copy (res, full, workBuff, 0, DESCore.BLOCK_BYTE_SIZE);
163 preprocess (workBuff);
164 cryptFn (workBuff, null);
165 Array.Copy (workBuff, 0, res, full, DESCore.BLOCK_BYTE_SIZE);
172 } // DESTransformBase
175 internal sealed class DESEncryptor : DESTransformBase {
176 internal DESEncryptor (byte [] key, byte [] iv)
177 : base (DESTransformBase.Mode.ENCRYPTOR, key, iv)
183 internal sealed class DESDecryptor : DESTransformBase {
184 internal DESDecryptor (byte [] key, byte [] iv)
185 : base (DESTransformBase.Mode.DECRYPTOR, key, iv)
191 public class DESCryptoServiceProvider {
195 public DESCryptoServiceProvider ()
204 public virtual ICryptoTransform CreateEncryptor()
206 return new DESEncryptor (key, iv);
209 public virtual ICryptoTransform CreateDecryptor()
211 return new DESDecryptor (key, iv);
216 // FIXME: Ought to be in DES.cs
218 [MonoTODO ("Ought to be in DES.cs")]
219 public /*override*/ byte[] Key {
224 this.key = new byte [DESCore.KEY_BYTE_SIZE];
225 Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
229 public virtual byte[] IV {
234 this.iv = new byte [DESCore.KEY_BYTE_SIZE];
235 Array.Copy (value, 0, this.iv, 0, DESCore.KEY_BYTE_SIZE);
243 public override string ToString ()
245 return "mono::System.Security.Cryptography.DESCryptoServiceProvider";
248 } // DESCryptoServiceProvider
250 } // System.Security.Cryptography