2004-05-06 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / TripleDESCryptoServiceProvider.cs
1 //
2 // TripleDESCryptoServiceProvider.cs: Default TripleDES implementation
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
8 // (C) 2004 Novell (http://www.novell.com)
9 //
10
11 using System;
12 using Mono.Security.Cryptography;
13
14 namespace System.Security.Cryptography {
15
16         // References:
17         // a.   FIPS PUB 46-3: TripleDES
18         //      http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
19         // b.   ANSI X9.52
20         //      not free :-(
21         //      http://webstore.ansi.org/ansidocstore/product.asp?sku=ANSI+X9%2E52%2D1998
22         
23         public sealed class TripleDESCryptoServiceProvider : TripleDES {
24         
25                 public TripleDESCryptoServiceProvider ()
26                 {
27                 }
28         
29                 public override void GenerateIV () 
30                 {
31                         IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
32                 }
33                 
34                 public override void GenerateKey () 
35                 {
36                         KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
37                 }
38                 
39                 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
40                 {
41                         Key = rgbKey;
42                         IV = rgbIV;
43                         return new TripleDESTransform (this, false, rgbKey, rgbIV);
44                 }
45                 
46                 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
47                 {
48                         Key = rgbKey;
49                         IV = rgbIV;
50                         return new TripleDESTransform (this, true, rgbKey, rgbIV);
51                 }
52         }
53         
54         // TripleDES is just DES-EDE
55         internal class TripleDESTransform : SymmetricTransform {
56         
57                 // for encryption
58                 private DESTransform E1;
59                 private DESTransform D2;
60                 private DESTransform E3;
61         
62                 // for decryption
63                 private DESTransform D1;
64                 private DESTransform E2;
65                 private DESTransform D3;
66                 
67                 public TripleDESTransform (TripleDES algo, bool encryption, byte[] key, byte[] iv) : base (algo, encryption, iv) 
68                 {
69                         byte[] key1 = new byte [8];
70                         byte[] key2 = new byte [8];
71                         byte[] key3 = new byte [8];
72                         DES des = DES.Create ();
73                         Buffer.BlockCopy (key, 0, key1, 0, 8);
74                         Buffer.BlockCopy (key, 8, key2, 0, 8);
75                         if (key.Length == 16)
76                                 Buffer.BlockCopy (key, 0, key3, 0, 8);
77                         else
78                                 Buffer.BlockCopy (key, 16, key3, 0, 8);
79         
80                         // note: some modes (like CFB) requires encryption when decrypting
81                         if ((encryption) || (algo.Mode == CipherMode.CFB)) {
82                                 E1 = new DESTransform (des, true, key1, iv);
83                                 D2 = new DESTransform (des, false, key2, iv);
84                                 E3 = new DESTransform (des, true, key3, iv);
85                         }
86                         else {
87                                 D1 = new DESTransform (des, false, key3, iv);
88                                 E2 = new DESTransform (des, true, key2, iv);
89                                 D3 = new DESTransform (des, false, key1, iv);
90                         }
91                 }
92         
93                 // note: this method is garanteed to be called with a valid blocksize
94                 // for both input and output
95                 protected override void ECB (byte[] input, byte[] output) 
96                 {
97                         byte[] temp = new byte [input.Length];
98                         if (encrypt) {
99                                 E1.ProcessBlock (input, output);
100                                 D2.ProcessBlock (output, temp);
101                                 E3.ProcessBlock (temp, output);
102                         }
103                         else {
104                                 D1.ProcessBlock (input, output);
105                                 E2.ProcessBlock (output, temp);
106                                 D3.ProcessBlock (temp, output);
107                                 // don't keep decrypted content in memory
108                                 Array.Clear (temp, 0, temp.Length);
109                         }
110                 }
111         }
112 }