2 // MACTripleDES.cs: Handles MAC with TripleDES
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
12 using System.Security.Cryptography;
14 namespace System.Security.Cryptography {
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
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)
30 public MACAlgorithm (string algoName, CipherMode algoMode)
32 if ((algoMode != CipherMode.CBC) && (algoMode != CipherMode.CFB))
33 throw new CryptographicException();
35 algo = (SymmetricAlgorithm) CryptoConfig.CreateFromName (algoName);
37 algo.Padding = PaddingMode.Zeros;
38 BlockSize = (algo.BlockSize >> 3);
46 public void Dispose ()
49 // algo.Clear (); not yet present in SymmetricAlgorithm
52 public SymmetricAlgorithm Algo {
57 get { return algo.Key; }
58 set { algo.Key = value; }
62 get { return algo.IV; }
63 set { algo.IV = value; }
67 public void Initialize ()
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);
78 public void Core (byte[] rgb, int ib, int cb)
83 stream.Write (rgb, ib, cb);
86 [MonoTODO("How should it finish? encrypting the last block?")]
87 public byte[] Final ()
89 stream.FlushFinalBlock ();
90 byte[] mac = new byte [BlockSize];
91 ms.Position -= BlockSize;
92 ms.Read (mac, 0, BlockSize);
96 public void ZeroizeKey ()
98 // well maybe the algo did it - but better twice than none
100 Array.Clear (algo.Key, 0, algo.Key.Length);
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;
109 public MACTripleDES ()
111 mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
112 HashSizeValue = mac.Algo.BlockSize;
115 public MACTripleDES (byte[] rgbKey)
117 MACAlgorithm mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
118 HashSizeValue = mac.Algo.BlockSize;
122 public MACTripleDES (string strTripleDES, byte[] rgbKey)
124 MACAlgorithm mac = new MACAlgorithm (strTripleDES, CipherMode.CBC);
125 HashSizeValue = mac.Algo.BlockSize;
134 protected override void Dispose (bool disposing)
138 base.Dispose (disposing);
141 public override void Initialize ()
147 protected override void HashCore (byte[] rgb, int ib, int cb)
150 mac.Core (rgb, ib, cb);
153 protected override byte[] HashFinal ()