2002-10-25 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / MACTripleDES.cs
1 //
2 // MACTripleDES.cs: Handles MAC with TripleDES
3 //
4 // Author:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
8 //
9
10 using System;
11 using System.IO;
12 using System.Security.Cryptography;
13
14 namespace System.Security.Cryptography {
15
16 // References:
17 // a.   FIPS PUB 81: DES MODES OF OPERATION 
18 //      MAC: Appendix F (MACDES not MACTripleDES but close enough ;-)
19 //      http://www.itl.nist.gov/fipspubs/fip81.htm
20
21 // Generic MAC mechanims - most of the work is done in here
22 // It should work with any symmetric algorithm function e.g. DES for MACDES (fips81)
23 internal class MACAlgorithm {
24         protected SymmetricAlgorithm algo;
25         private ICryptoTransform enc;
26         private CryptoStream stream;
27         private MemoryStream ms;
28         private int BlockSize;  // in bytes (not in bits)
29
30         public MACAlgorithm (string algoName, CipherMode algoMode) 
31         {
32                 if ((algoMode != CipherMode.CBC) && (algoMode != CipherMode.CFB))
33                         throw new CryptographicException();
34
35                 algo = (SymmetricAlgorithm) CryptoConfig.CreateFromName (algoName);
36                 algo.Mode = algoMode;
37                 algo.Padding = PaddingMode.Zeros;
38                 BlockSize = (algo.BlockSize >> 3);
39         }
40
41         ~MACAlgorithm () 
42         {
43                 Dispose ();
44         }
45
46         public void Dispose () 
47         {
48                 ZeroizeKey ();
49                 // algo.Clear (); not yet present in SymmetricAlgorithm
50         }
51
52         public SymmetricAlgorithm Algo {
53                 get { return algo; }
54         }
55
56         public byte[] Key {
57                 get { return algo.Key; }
58                 set { algo.Key = value; }
59         }
60
61         public byte[] IV {
62                 get { return algo.IV; }
63                 set { algo.IV = value; }
64         }
65
66         [MonoTODO()]
67         public void Initialize () 
68         {
69                 if (algo.Mode == CipherMode.CBC)
70                         algo.IV = new Byte [BlockSize];
71                 enc = algo.CreateEncryptor();
72                 // TODO Change MemoryStream (unrealistic for big continuous streams)
73                 ms = new MemoryStream ();
74                 stream = new CryptoStream (ms, enc, CryptoStreamMode.Write);
75         }
76         
77         [MonoTODO("")]
78         public void Core (byte[] rgb, int ib, int cb) 
79         {
80                 if (enc == null)
81                         Initialize ();
82
83                 stream.Write (rgb, ib, cb);
84         }
85
86         [MonoTODO("How should it finish? encrypting the last block?")]
87         public byte[] Final () 
88         {
89                 stream.FlushFinalBlock ();
90                 byte[] mac = new byte [BlockSize];
91                 ms.Position -= BlockSize;
92                 ms.Read (mac, 0, BlockSize);
93                 return mac;
94         }
95
96         public void ZeroizeKey () 
97         {
98                 // well maybe the algo did it - but better twice than none
99                 if (algo.Key != null)
100                         Array.Clear (algo.Key, 0, algo.Key.Length);
101         }
102 }
103
104 // LAMESPEC: MACTripleDES == MAC-CBC using TripleDES (not MAC-CFB).
105 // LAMESPEC: Unlike FIPS81 or FIPS113 the result is encrypted twice (ANSI like?)
106 public class MACTripleDES: KeyedHashAlgorithm {
107         private MACAlgorithm mac;
108
109         public MACTripleDES () 
110         {
111                 mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
112                 HashSizeValue = mac.Algo.BlockSize;
113         }
114
115         public MACTripleDES (byte[] rgbKey)
116         {
117                 MACAlgorithm mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
118                 HashSizeValue = mac.Algo.BlockSize;
119                 mac.Key = rgbKey;
120         }
121
122         public MACTripleDES (string strTripleDES, byte[] rgbKey)
123         {
124                 MACAlgorithm mac = new MACAlgorithm (strTripleDES, CipherMode.CBC);
125                 HashSizeValue = mac.Algo.BlockSize;
126                 mac.Key = rgbKey;
127         }
128
129         ~MACTripleDES () 
130         {
131                 Dispose (false);
132         }
133
134         protected override void Dispose (bool disposing) 
135         {
136                 if (mac != null)
137                         mac.Dispose();
138                 base.Dispose (disposing);
139         }
140
141         public override void Initialize () 
142         {
143                 State = 0;
144                 mac.Initialize ();
145         }
146
147         protected override void HashCore (byte[] rgb, int ib, int cb) 
148         {
149                 State = 1;
150                 mac.Core (rgb, ib, cb);
151         }
152
153         protected override byte[] HashFinal () 
154         {
155                 State = 0;
156                 return mac.Final ();
157         }
158 }
159
160 }