Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/class
diff options
context:
space:
mode:
authorSebastien Pouliot <sebastien@ximian.com>2002-10-13 22:38:54 +0400
committerSebastien Pouliot <sebastien@ximian.com>2002-10-13 22:38:54 +0400
commit053b98da026216f1e62e177e019bfbb45b169fc6 (patch)
treeb2088d1d4952059862f3fe11853c41e5f2912cbc /mcs/class
parent9220e111890479cad968c1b3aa68b134c88fc286 (diff)
2002-10-13 Sebastien Pouliot <spouliot@videotron.ca>
* HashAlgorithm.cs: Added Dispose() to HashAlgorithm because it inherits ICryptoTransform * KeyedHashAlgorithm.cs: New implementation * HMACSHA1.cs: New (include a generic HMACAlgorithm as internal class) * MACTripleDES.cs: New (missing core implementation on generic MACAlgorithm) * CryptoStream.cs: Added limited functionalities to support HMACSHA1 svn path=/trunk/mcs/; revision=8221
Diffstat (limited to 'mcs/class')
-rw-r--r--mcs/class/corlib/System.Security.Cryptography/ChangeLog15
-rwxr-xr-xmcs/class/corlib/System.Security.Cryptography/CryptoStream.cs257
-rw-r--r--mcs/class/corlib/System.Security.Cryptography/HMACSHA1.cs221
-rw-r--r--mcs/class/corlib/System.Security.Cryptography/KeyedHashAlgorithm.cs73
-rw-r--r--mcs/class/corlib/System.Security.Cryptography/MACTripleDES.cs160
5 files changed, 606 insertions, 120 deletions
diff --git a/mcs/class/corlib/System.Security.Cryptography/ChangeLog b/mcs/class/corlib/System.Security.Cryptography/ChangeLog
index faaabd8238e..fffa2f30ba2 100644
--- a/mcs/class/corlib/System.Security.Cryptography/ChangeLog
+++ b/mcs/class/corlib/System.Security.Cryptography/ChangeLog
@@ -1,3 +1,18 @@
+2002-10-13 Sebastien Pouliot <spouliot@videotron.ca>
+
+ * HashAlgorithm.cs: Added Dispose() to HashAlgorithm because it
+ inherits ICryptoTransform
+ * KeyedHashAlgorithm.cs: New implementation
+ * HMACSHA1.cs: New (include a generic HMACAlgorithm as internal class)
+ * MACTripleDES.cs: New (missing core implementation on generic MACAlgorithm)
+ * CryptoStream.cs: Added limited functionalities to support HMACSHA1
+
+2002-10-12 Sebastien Pouliot <spouliot@videotron.ca>
+
+ * DSA.cs: changed constructor to public from internal (like MS)
+ * HashAlgorithm.cs: Completed ComputeHash methods
+ * SHA1.cs: Added HashSizeValue = 160
+
2002-10-12 Sebastien Pouliot <spouliot@videotron.ca>
* ICryptoTransform.cs: Now inherits from IDisposable
diff --git a/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs b/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs
index 6dad1ca628d..0f4df3c6cf3 100755
--- a/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs
+++ b/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs
@@ -1,120 +1,137 @@
-//
-// System.Security.Cryptography CryptoStream.cs
-//
-// Author:
-// Thomas Neidhart (tome@sbox.tugraz.at)
-//
-
-using System;
-using System.IO;
-
-namespace System.Security.Cryptography
-{
-
- public class CryptoStream : Stream
- {
- private CryptoStreamMode _mode;
-
- public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
- {
- _mode = mode;
- }
-
- public override bool CanRead
- {
- get {
- switch (_mode) {
- case CryptoStreamMode.Read:
- return true;
-
- case CryptoStreamMode.Write:
- return false;
-
- default:
- return false;
- }
- }
- }
-
- public override bool CanSeek
- {
- get {
- return false;
- }
- }
-
- public override bool CanWrite
- {
- get {
- switch (_mode) {
- case CryptoStreamMode.Read:
- return false;
-
- case CryptoStreamMode.Write:
- return true;
-
- default:
- return false;
- }
- }
- }
-
- public override long Length
- {
- get {
- throw new NotSupportedException("Length property not supported by CryptoStream");
- }
- }
-
- public override long Position
- {
- get {
- throw new NotSupportedException("Position property not supported by CryptoStream");
- }
- set {
- throw new NotSupportedException("Position property not supported by CryptoStream");
- }
- }
-
- [MonoTODO]
- public override int Read(byte[] buffer, int offset, int count)
- {
- // TODO: implement
- return 0;
- }
-
- [MonoTODO]
- public override void Write(byte[] buffer, int offset, int count)
- {
- // TODO: implement
- }
-
- [MonoTODO]
- public override void Flush()
- {
- // TODO: implement
- }
-
- [MonoTODO]
- public void FlushFinalBlock()
- {
- if (_mode != CryptoStreamMode.Write)
- throw new NotSupportedException("cannot flush a non-writeable CryptoStream");
-
- // TODO: implement
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException("cannot seek a CryptoStream");
- }
-
- public override void SetLength(long value)
- {
- // LAMESPEC: should throw NotSupportedException like Seek??
- return;
- }
-
- } // CryptoStream
-
-} // System.Security.Cryptography
+//
+// System.Security.Cryptography CryptoStream.cs
+//
+// Author:
+// Thomas Neidhart (tome@sbox.tugraz.at)
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.IO;
+
+namespace System.Security.Cryptography {
+
+public class CryptoStream : Stream {
+ private Stream _stream;
+ private ICryptoTransform _transform;
+ private CryptoStreamMode _mode;
+
+ public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
+ {
+ _stream = stream;
+ _transform = transform;
+ _mode = mode;
+ }
+
+ ~CryptoStream ()
+ {
+ Dispose (false);
+ }
+
+ public override bool CanRead {
+ get { return (_mode == CryptoStreamMode.Read); }
+ }
+
+ public override bool CanSeek {
+ get { return false; }
+ }
+
+ public override bool CanWrite {
+ get { return (_mode == CryptoStreamMode.Write); }
+ }
+
+ public override long Length {
+ get {
+ throw new NotSupportedException("Length property not supported by CryptoStream");
+ }
+ }
+
+ public override long Position {
+ get {
+ throw new NotSupportedException("Position property not supported by CryptoStream");
+ }
+ set {
+ throw new NotSupportedException("Position property not supported by CryptoStream");
+ }
+ }
+
+ public void Clear ()
+ {
+ Dispose (true);
+ }
+
+ [MonoTODO("Limited support for HMACSHA1")]
+ public override void Close ()
+ {
+ if (_mode != CryptoStreamMode.Write)
+ throw new NotSupportedException ();
+ // TODO: limited implemention for HMACSHA1
+ byte[] buffer = new byte [0];
+ _transform.TransformFinalBlock (buffer, 0, 0);
+ if (_stream != null)
+ _stream.Close();
+ }
+
+ [MonoTODO]
+ public override int Read (byte[] buffer, int offset, int count)
+ {
+ if (_mode != CryptoStreamMode.Read)
+ throw new NotSupportedException ();
+ if ((offset < 0) || (count < 0))
+ throw new ArgumentOutOfRangeException ();
+ if (offset + count > buffer.Length)
+ throw new ArgumentException ();
+ // TODO: implement
+ return 0;
+ }
+
+ [MonoTODO("Limited support for HMACSHA1")]
+ public override void Write (byte[] buffer, int offset, int count)
+ {
+ if (_mode != CryptoStreamMode.Write)
+ throw new NotSupportedException ();
+ if ((offset < 0) || (count < 0))
+ throw new ArgumentOutOfRangeException ();
+ if (offset + count > buffer.Length)
+ throw new ArgumentException ();
+ // TODO: limited implemention for HMACSHA1
+ byte[] output = new byte [count];
+ _transform.TransformBlock (buffer, offset, count, output, 0);
+ }
+
+ [MonoTODO]
+ public override void Flush ()
+ {
+ if (_mode != CryptoStreamMode.Write)
+ throw new NotSupportedException ("cannot flush a non-writeable CryptoStream");
+ // TODO: implement
+ }
+
+ [MonoTODO]
+ public void FlushFinalBlock ()
+ {
+ if (_mode != CryptoStreamMode.Write)
+ throw new NotSupportedException ("cannot flush a non-writeable CryptoStream");
+ // TODO: implement
+ }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException ("cannot Seek a CryptoStream");
+ }
+
+ // LAMESPEC: Exception NotSupportedException not documented
+ public override void SetLength (long value)
+ {
+ throw new NotSupportedException ("cannot SetLength a CryptoStream");
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ }
+
+} // CryptoStream
+
+} // System.Security.Cryptography
diff --git a/mcs/class/corlib/System.Security.Cryptography/HMACSHA1.cs b/mcs/class/corlib/System.Security.Cryptography/HMACSHA1.cs
new file mode 100644
index 00000000000..71b12fd2c97
--- /dev/null
+++ b/mcs/class/corlib/System.Security.Cryptography/HMACSHA1.cs
@@ -0,0 +1,221 @@
+//
+// HMACSHA1.cs: Handles HMAC with SHA-1
+//
+// Author:
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography {
+
+// References:
+// a. FIPS PUB 198: The Keyed-Hash Message Authentication Code (HMAC), 2002 March.
+// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
+// b. Internet RFC 2104, HMAC, Keyed-Hashing for Message Authentication
+// (include C source for HMAC-MD5)
+// http://www.ietf.org/rfc/rfc2104.txt
+// c. IETF RFC2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
+// (include C source for HMAC-MD5 and HAMAC-SHA1)
+// http://www.ietf.org/rfc/rfc2202.txt
+// d. ANSI X9.71, Keyed Hash Message Authentication Code.
+// not free :-(
+// http://webstore.ansi.org/ansidocstore/product.asp?sku=ANSI+X9%2E71%2D2000
+
+// Generic HMAC mechanisms - most of HMAC work is done in here.
+// It should work with any hash function e.g. MD5 for HMACMD5 (RFC2104)
+internal class HMACAlgorithm {
+ private byte[] key;
+ private byte[] hash;
+ private HashAlgorithm algo;
+ private string hashName;
+ private CryptoStream stream;
+
+ public HMACAlgorithm (string algoName)
+ {
+ CreateHash (algoName);
+ }
+
+ ~HMACAlgorithm ()
+ {
+ Dispose ();
+ }
+
+ private void CreateHash (string algoName)
+ {
+ algo = (HashAlgorithm) CryptoConfig.CreateFromName (algoName);
+ hashName = algoName;
+ }
+
+ public void Dispose ()
+ {
+ ZeroizeKey ();
+ }
+
+ public HashAlgorithm Algo {
+ get { return algo; }
+ }
+
+ public string HashName {
+ get { return hashName; }
+ set {
+ // only if its not too late for a change
+ if (stream == null)
+ CreateHash (value);
+ }
+ }
+
+ public byte[] HashValue {
+ get { return hash; }
+ }
+
+ public byte[] Key {
+ get { return key; }
+ set {
+ if ((value != null) && (value.Length > 64))
+ key = algo.ComputeHash (value);
+ else
+ key = (byte[]) value.Clone();
+ }
+ }
+
+ public void Initialize ()
+ {
+ hash = null;
+ }
+
+ private byte[] KeySetup (byte[] key, byte padding)
+ {
+ byte[] buf = new byte [64];
+
+ for (int i = 0; i < key.Length; ++i)
+ buf [i] = (byte) ((byte) key [i] ^ padding);
+
+ for (int i = key.Length; i < 64; ++i)
+ buf [i] = padding;
+
+ return buf;
+ }
+
+ public void Core (byte[] rgb, int ib, int cb)
+ {
+ if (stream == null) {
+ byte[] buf = KeySetup (key, 0x36);
+ algo.Initialize ();
+ stream = new CryptoStream (Stream.Null, algo, CryptoStreamMode.Write);
+ stream.Write (buf, 0, buf.Length);
+ }
+ stream.Write (rgb, ib, cb);
+ }
+
+ public byte[] Final ()
+ {
+ stream.Close ();
+ stream = null;
+ byte[] intermediate = algo.Hash;
+ byte[] buf = KeySetup (key, 0x5C);
+
+ algo.Initialize ();
+ stream = new CryptoStream (Stream.Null, algo, CryptoStreamMode.Write);
+ stream.Write (buf, 0, buf.Length);
+ stream.Write (intermediate, 0, intermediate.Length);
+ stream.Close ();
+ stream = null;
+
+ hash = algo.Hash;
+ algo.Clear ();
+ return hash;
+ }
+
+ // Note: this key is different (well most of the time) from the key
+ // used in KeyHashAlgorithm (this one may be padded or hashed). So
+ // it need to be zeroized independently.
+ public void ZeroizeKey ()
+ {
+ if (key != null)
+ Array.Clear (key, 0, key.Length);
+ }
+}
+
+public class HMACSHA1: KeyedHashAlgorithm {
+ private HMACAlgorithm hmac;
+
+ public HMACSHA1 () : base ()
+ {
+ hmac = new HMACAlgorithm ("SHA1");
+ HashSizeValue = 160;
+ GenerateKey();
+ }
+
+ public HMACSHA1 (byte[] rgbKey)
+ {
+ hmac = new HMACAlgorithm ("SHA1");
+ HashSizeValue = 160;
+ hmac.Key = rgbKey;
+ }
+
+ ~HMACSHA1 ()
+ {
+ Dispose (false);
+ }
+
+ public override byte[] Key {
+ get { return base.Key; }
+ set {
+ hmac.Key = value;
+ base.Key = value;
+ }
+ }
+
+ public string HashName {
+ get { return hmac.HashName; }
+ set { hmac.HashName = value; }
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (hmac != null)
+ hmac.Dispose();
+ base.Dispose (disposing);
+ }
+
+ // generate a random 64 bits key
+ private void GenerateKey ()
+ {
+ KeyValue = new byte[8];
+ RandomNumberGenerator rng = RandomNumberGenerator.Create();
+ rng.GetBytes (KeyValue);
+ hmac.Key = KeyValue;
+ }
+
+ public override void Initialize ()
+ {
+ State = 0;
+ hmac.Initialize ();
+ }
+
+ protected override void HashCore (byte[] rgb, int ib, int cb)
+ {
+ if (State == 0) {
+ // let us throw an exception if hash name is invalid
+ // for HMACSHA1 (obviously this can't be done by the
+ // generic HMAC class)
+ if (! (hmac.Algo is SHA1))
+ throw new InvalidCastException ();
+ }
+ State = 1;
+ hmac.Core (rgb, ib, cb);
+ }
+
+ protected override byte[] HashFinal ()
+ {
+ State = 0;
+ return hmac.Final ();
+ }
+}
+
+} \ No newline at end of file
diff --git a/mcs/class/corlib/System.Security.Cryptography/KeyedHashAlgorithm.cs b/mcs/class/corlib/System.Security.Cryptography/KeyedHashAlgorithm.cs
new file mode 100644
index 00000000000..682dcb3d49d
--- /dev/null
+++ b/mcs/class/corlib/System.Security.Cryptography/KeyedHashAlgorithm.cs
@@ -0,0 +1,73 @@
+//
+// KeyedHashAlgorithm.cs: Handles keyed hash and MAC classes.
+//
+// Author:
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography {
+
+public abstract class KeyedHashAlgorithm : HashAlgorithm {
+
+ protected byte[] KeyValue;
+
+ protected KeyedHashAlgorithm () : base ()
+ {
+ // create a random 64 bits key
+ }
+
+ ~KeyedHashAlgorithm ()
+ {
+ Dispose (false);
+ }
+
+ public virtual byte[] Key {
+ get {
+ return (byte[]) KeyValue.Clone ();
+ }
+ set {
+ // can't change the key during a hashing ops
+ if (State != 0)
+ throw new CryptographicException ();
+ // zeroize current key material for security
+ ZeroizeKey ();
+ // copy new key
+ KeyValue = (byte[]) value.Clone ();
+ }
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // zeroize key material for security
+ ZeroizeKey();
+ // dispose managed resources
+ // none so far
+ // dispose unmanaged resources
+ // none so far
+ // calling base class HashAlgorithm
+ base.Dispose (disposing);
+ }
+
+ private void ZeroizeKey()
+ {
+ if (KeyValue != null)
+ Array.Clear (KeyValue, 0, KeyValue.Length);
+ }
+
+ public static new KeyedHashAlgorithm Create ()
+ {
+ return Create ("System.Security.Cryptography.KeyedHashAlgorithm");
+ }
+
+ public static new KeyedHashAlgorithm Create (string algName)
+ {
+ return (KeyedHashAlgorithm) CryptoConfig.CreateFromName (algName);
+ }
+}
+
+} \ No newline at end of file
diff --git a/mcs/class/corlib/System.Security.Cryptography/MACTripleDES.cs b/mcs/class/corlib/System.Security.Cryptography/MACTripleDES.cs
new file mode 100644
index 00000000000..5a051af481c
--- /dev/null
+++ b/mcs/class/corlib/System.Security.Cryptography/MACTripleDES.cs
@@ -0,0 +1,160 @@
+//
+// MACTripleDES.cs: Handles MAC with TripleDES
+//
+// Author:
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography {
+
+// References:
+// a. FIPS PUB 81: DES MODES OF OPERATION
+// MAC: Appendix F (MACDES not MACTripleDES but close enough ;-)
+// http://www.itl.nist.gov/fipspubs/fip81.htm
+
+// Generic MAC mechanims - most of the work is done in here
+// It should work with any symmetric algorithm function e.g. DES for MACDES (fips81)
+internal class MACAlgorithm {
+ protected SymmetricAlgorithm algo;
+ private ICryptoTransform enc;
+ private CryptoStream stream;
+ private MemoryStream ms;
+ private int BlockSize; // in bytes (not in bits)
+
+ public MACAlgorithm (string algoName, CipherMode algoMode)
+ {
+ if ((algoMode != CipherMode.CBC) && (algoMode != CipherMode.CFB))
+ throw new CryptographicException();
+
+ algo = (SymmetricAlgorithm) CryptoConfig.CreateFromName (algoName);
+ algo.Mode = algoMode;
+ algo.Padding = PaddingMode.Zeros;
+ BlockSize = (algo.BlockSize >> 3);
+ }
+
+ ~MACAlgorithm ()
+ {
+ Dispose ();
+ }
+
+ public void Dispose ()
+ {
+ ZeroizeKey ();
+ // algo.Clear (); not yet present in SymmetricAlgorithm
+ }
+
+ public SymmetricAlgorithm Algo {
+ get { return algo; }
+ }
+
+ public byte[] Key {
+ get { return algo.Key; }
+ set { algo.Key = value; }
+ }
+
+ public byte[] IV {
+ get { return algo.IV; }
+ set { algo.IV = value; }
+ }
+
+ [MonoTODO()]
+ public void Initialize ()
+ {
+ if (algo.Mode == CipherMode.CBC)
+ algo.IV = new Byte [BlockSize];
+ enc = algo.CreateEncryptor();
+ // TODO Change MemoryStream (unrealistic for big continuous streams)
+ ms = new MemoryStream ();
+ stream = new CryptoStream (ms, enc, CryptoStreamMode.Write);
+ }
+
+ [MonoTODO("")]
+ public void Core (byte[] rgb, int ib, int cb)
+ {
+ if (enc == null)
+ Initialize ();
+
+ stream.Write (rgb, ib, cb);
+ }
+
+ [MonoTODO("How should it finish? encrypting the last block?")]
+ public byte[] Final ()
+ {
+ stream.FlushFinalBlock ();
+ byte[] mac = new byte [BlockSize];
+ ms.Position -= BlockSize;
+ ms.Read (mac, 0, BlockSize);
+ return mac;
+ }
+
+ public void ZeroizeKey ()
+ {
+ // well maybe the algo did it - but better twice than none
+ if (algo.Key != null)
+ Array.Clear (algo.Key, 0, algo.Key.Length);
+ }
+}
+
+// LAMESPEC: MACTripleDES == MAC-CBC using TripleDES (not MAC-CFB).
+// LAMESPEC: Unlike FIPS81 or FIPS113 the result is encrypted twice (ANSI like?)
+public class MACTripleDES: KeyedHashAlgorithm {
+ private MACAlgorithm mac;
+
+ public MACTripleDES ()
+ {
+ mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
+ HashSizeValue = mac.Algo.BlockSize;
+ }
+
+ public MACTripleDES (byte[] rgbKey)
+ {
+ MACAlgorithm mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
+ HashSizeValue = mac.Algo.BlockSize;
+ mac.Key = rgbKey;
+ }
+
+ public MACTripleDES (string strTripleDES, byte[] rgbKey)
+ {
+ MACAlgorithm mac = new MACAlgorithm (strTripleDES, CipherMode.CBC);
+ HashSizeValue = mac.Algo.BlockSize;
+ mac.Key = rgbKey;
+ }
+
+ ~MACTripleDES ()
+ {
+ Dispose (false);
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (mac != null)
+ mac.Dispose();
+ base.Dispose (disposing);
+ }
+
+ public override void Initialize ()
+ {
+ State = 0;
+ mac.Initialize ();
+ }
+
+ protected override void HashCore (byte[] rgb, int ib, int cb)
+ {
+ State = 1;
+ mac.Core (rgb, ib, cb);
+ }
+
+ protected override byte[] HashFinal ()
+ {
+ State = 0;
+ return mac.Final ();
+ }
+}
+
+} \ No newline at end of file