aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/MessageDigest.cs
blob: 5562f9d3668c59bc6364435e26f53eaf2e82c03c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;

namespace SharpCifs.Util.Sharpen
{
    public abstract class MessageDigest
	{
	    public void Digest (byte[] buffer, int o, int len)
		{
			byte[] d = Digest ();
			d.CopyTo (buffer, o);
		}

		public byte[] Digest (byte[] buffer)
		{
			Update (buffer);
			return Digest ();
		}

		public abstract byte[] Digest ();
		public abstract int GetDigestLength ();
		public static MessageDigest GetInstance (string algorithm)
		{
			switch (algorithm.ToLower ()) {
			case "sha-1":
                //System.Security.CryptographySHA1Managed not found
                //return new MessageDigest<SHA1Managed> ();
                return new MessageDigest<System.Security.Cryptography.SHA1>();
            case "md5":
                return new MessageDigest<Md5Managed> ();
            }
			throw new NotSupportedException (string.Format ("The requested algorithm \"{0}\" is not supported.", algorithm));
		}

		public abstract void Reset ();
		public abstract void Update (byte[] b);
		public abstract void Update (byte b);
		public abstract void Update (byte[] b, int offset, int len);
	}


	public class MessageDigest<TAlgorithm> : MessageDigest where TAlgorithm : HashAlgorithm //, new() //use static `Create` method
	{
		private TAlgorithm _hash;
        //private CryptoStream _stream; //don't work .NET Core
        private MemoryStream _stream;


        public MessageDigest ()
		{
			Init ();
		}

		public override byte[] Digest ()
		{
            //CryptoStream -> MemoryStream, needless method
            //_stream.FlushFinalBlock ();

            //HashAlgorithm.`Hash` property deleted
            //byte[] hash = _hash.Hash;
            byte[] hash = _hash.ComputeHash(_stream.ToArray());

            Reset ();
			return hash;
		}

		public void Dispose ()
		{
			if (_stream != null) {
				_stream.Dispose ();
			}
			_stream = null;
        }

        public override int GetDigestLength ()
		{
			return (_hash.HashSize / 8);
		}

		private void Init ()
		{
            //use static `Create` method
            //_hash = Activator.CreateInstance<TAlgorithm> ();
            var createMethod = typeof(TAlgorithm).GetRuntimeMethod("Create", new Type[0]);
            _hash = (TAlgorithm)createMethod.Invoke(null, new object[] {});

            //HashAlgorithm cannot cast `ICryptoTransform` on .NET Core, gave up using CryptoStream. 
            //_stream = new CryptoStream(Stream.Null, _hash, CryptoStreamMode.Write);
            //_stream = new CryptoStream(_tmpStream, (ICryptoTransform)_hash, CryptoStreamMode.Write);
            _stream = new MemoryStream();
        }

        public override void Reset ()
		{
			Dispose ();
			Init ();
		}

		public override void Update (byte[] input)
		{
			_stream.Write (input, 0, input.Length);
		}

		public override void Update (byte input)
		{
			_stream.WriteByte (input);
		}

		public override void Update (byte[] input, int index, int count)
		{
			if (count < 0)
				Console.WriteLine ("Argh!");
			_stream.Write (input, index, count);
		}
	}
}