2002-01-14 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DESCryptoServiceProvider.cs
1 //
2 // System.Security.Cryptography.DESCryptoServiceProvider
3 //
4 // Author:
5 //   Sergey Chaban (serge@wildwestsoftware.com)
6 //
7
8
9
10 using System;
11 using System.Security.Cryptography;
12
13
14 namespace System.Security.Cryptography {
15
16
17         internal class DESTransformBase : ICryptoTransform {
18
19                 internal enum Mode : int {
20                         ENCRYPTOR = 0,
21                         DECRYPTOR = 1
22                 }
23
24                 protected delegate void Filter (byte [] workBuff);
25
26                 private DESCore core;
27
28                 private DESCore.DESCall cryptFn;
29                 private Filter preprocess;
30                 private Filter postprocess;
31
32                 private byte [] iv;
33                 private byte [] tmpBlock;
34
35                 protected DESTransformBase (Mode mode, byte [] key, byte [] iv)
36                 {
37                         core = new DESCore ();
38
39                         if (mode == Mode.ENCRYPTOR) {
40                                 cryptFn = new DESCore.DESCall (core.Encrypt);
41                                 preprocess = new Filter (this.EncPreprocess);
42                                 postprocess = new Filter (this.EncPostprocess);
43                         } else {
44                                 cryptFn = new DESCore.DESCall (core.Decrypt);
45                                 preprocess = new Filter (this.DecPreprocess);
46                                 postprocess = new Filter (this.DecPostprocess);
47                         }
48
49                         core.SetKey (key);
50                         this.iv = new byte [DESCore.BLOCK_BYTE_SIZE];
51                         Array.Copy (iv, 0, this.iv, 0, DESCore.BLOCK_BYTE_SIZE);
52
53                         tmpBlock = new byte [DESCore.BLOCK_BYTE_SIZE];
54                 }
55
56
57                 public virtual bool CanTransformMultipleBlocks {
58                         get {
59                                 return true;
60                         }
61                 }
62
63
64                 public virtual int InputBlockSize {
65                         get {
66                                 return DESCore.BLOCK_BYTE_SIZE;
67                         }
68                 }
69
70                 public virtual int OutputBlockSize {
71                         get {
72                                 return DESCore.BLOCK_BYTE_SIZE;
73                         }
74                 }
75
76                 private void EncPreprocess (byte [] workBuff)
77                 {
78                         byte [] iv = this.iv;
79                         for (int i = 0; i < DESCore.BLOCK_BYTE_SIZE; i++) {
80                                 workBuff [i] ^= iv [i];
81                         }
82                 }
83
84                 private void EncPostprocess (byte [] workBuff)
85                 {
86                         Array.Copy (workBuff, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
87                 }
88
89
90                 private void DecPreprocess (byte [] workBuff)
91                 {
92                         Array.Copy (workBuff, 0, tmpBlock, 0, DESCore.BLOCK_BYTE_SIZE);
93                 }
94
95                 private void DecPostprocess (byte [] workBuff)
96                 {
97                         EncPreprocess (workBuff);
98                         Array.Copy (tmpBlock, 0, iv, 0, DESCore.BLOCK_BYTE_SIZE);
99                 }
100
101
102
103                 private void Transform (byte [] workBuff)
104                 {
105                         preprocess (workBuff);
106                         cryptFn (workBuff, null);
107                         postprocess (workBuff);
108                 }
109
110
111                 public virtual int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
112                 {
113                         if ((inputCount & (DESCore.BLOCK_BYTE_SIZE-1)) != 0)
114                                 throw new CryptographicException ("Invalid input block size.");
115
116                         if (outputOffset + inputCount > outputBuffer.Length)
117                                 throw new CryptographicException ("Insufficient output buffer size.");
118
119                         int step = InputBlockSize;
120                         int offs = inputOffset;
121                         int full = inputCount / step;
122
123                         byte [] workBuff = new byte [step];
124
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);
129                                 offs += step;
130                                 outputOffset += step;
131                         }
132
133                         return (full * step);
134                 }
135
136
137                 [MonoTODO]
138                 public virtual byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
139                 {
140                         // TODO: add decryption support
141
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;
145
146                         TransformBlock (inputBuffer, inputOffset, full, res, 0);
147
148                         int rem = inputCount & (DESCore.BLOCK_BYTE_SIZE-1);
149
150                         // PKCS-5 padding
151                         for (int i = num; --i >= (num - rem);) {
152                                 res [i] = (byte) rem;
153                         }
154
155                         Array.Copy (inputBuffer, inputOffset + full, res, full, rem);
156
157                         // the last padded block will be transformed in-place
158                         TransformBlock (res, full, DESCore.BLOCK_BYTE_SIZE, res, full);
159
160                         /*
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);
166                         */
167
168                         return res;
169                 }
170
171
172         } // DESTransformBase
173
174
175         internal sealed class DESEncryptor : DESTransformBase {
176                 internal DESEncryptor (byte [] key, byte [] iv)
177                 : base (DESTransformBase.Mode.ENCRYPTOR, key, iv)
178                 {
179                 }
180         } // DESEncryptor
181
182
183         internal sealed class DESDecryptor : DESTransformBase {
184                 internal DESDecryptor (byte [] key, byte [] iv)
185                 : base (DESTransformBase.Mode.DECRYPTOR, key, iv)
186                 {
187                 }
188         } // DESDecryptor
189
190
191         public class DESCryptoServiceProvider {
192                 private byte [] iv;
193                 private byte [] key;
194
195                 public DESCryptoServiceProvider ()
196                 {
197                 }
198
199
200                 //
201                 // Factories
202                 //
203
204                 public virtual ICryptoTransform CreateEncryptor()
205                 {
206                         return new DESEncryptor (key, iv);
207                 }
208
209                 public virtual ICryptoTransform CreateDecryptor()
210                 {
211                         return new DESDecryptor (key, iv);
212                 }
213
214
215
216                 // FIXME: Ought to be in DES.cs
217
218                 [MonoTODO ("Ought to be in DES.cs")]
219                 public /*override*/ byte[] Key {
220                         get {
221                                 return this.key;
222                         }
223                         set {
224                                 this.key = new byte [DESCore.KEY_BYTE_SIZE];
225                                 Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
226                         }
227                 }
228
229                 public virtual byte[] IV {
230                         get {
231                                 return this.iv;
232                         }
233                         set {
234                                 this.iv = new byte [DESCore.KEY_BYTE_SIZE];
235                                 Array.Copy (value, 0, this.iv, 0, DESCore.KEY_BYTE_SIZE);
236                         }
237                 }
238
239
240
241
242
243                 public override string ToString ()
244                 {
245                         return "mono::System.Security.Cryptography.DESCryptoServiceProvider";
246                 }
247
248         } // DESCryptoServiceProvider
249
250 } // System.Security.Cryptography