File: CapiHash.cs

package info (click to toggle)
mono 1.2.2.1-1etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 142,720 kB
  • ctags: 256,408
  • sloc: cs: 1,495,736; ansic: 249,442; sh: 18,327; xml: 12,463; makefile: 5,046; perl: 1,248; asm: 635; yacc: 285; sql: 7
file content (99 lines) | stat: -rw-r--r-- 2,298 bytes parent folder | download | duplicates (15)
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
//
// Mono.Security.Cryptography.CapiHash
//
// Authors:
//	Sebastien Pouliot (sebastien@ximian.com)
//
// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) 2004 Novell (http://www.novell.com)
//

using System;
using System.Security.Cryptography;

namespace Mono.Security.Cryptography {

public class CapiHash : IDisposable {

	private CapiContext context;
	private IntPtr handle;
	private uint hashSize;

	public CapiHash (int hashAlgorithm) 
	{
		context = new CapiContext ();
		Initialize (hashAlgorithm);
	}

	public CapiHash (CapiContext ctx, int hashAlgorithm) 
	{
		context = ctx;
		Initialize (hashAlgorithm);
	}

	public CapiHash (CspParameters cspParams, int hashAlgorithm) 
	{
		context = new CapiContext (cspParams);
		Initialize (hashAlgorithm);
	}

	~CapiHash () 
	{
		Dispose ();
	}

	public IntPtr Handle {
		get { return handle; }
	}

	public int HashSize {
		get { return (int) hashSize; }
	}

	public void Initialize (int algo) 
	{
		if (context != null) {
			context.InternalResult = CryptoAPI.CryptCreateHash (context.Handle, (uint)algo, IntPtr.Zero, 0, ref handle);
			hashSize = 0;
			if (context.Result)
				context.InternalResult = CryptoAPI.CryptGetHashParam (handle, CryptoAPI.HP_HASHVAL, null, ref hashSize, 0);
			GC.KeepAlive (this);
		}
	}

	public void Dispose () 
	{
		if (handle != IntPtr.Zero) {
			CryptoAPI.CryptDestroyHash (handle);
			context.Dispose ();
			GC.KeepAlive (this);
			handle = IntPtr.Zero;
			GC.SuppressFinalize (this);
		}
	}

	// FIXME: calling this function 1,000,000 times (with a single character)
	// is a good way to lose time (and hung NUnit)
	// TODO: find the bug that hang NUnit
	// TODO: optimize the function to call CryptHashData less often (bufferize)
	public void HashCore (byte[] data, int start, int length) 
	{
		byte[] toBeHashed = data;
		if (start != 0) {
			toBeHashed = new byte [length];
			Array.Copy (data, start, toBeHashed, 0, length);
		}
		context.InternalResult = CryptoAPI.CryptHashData (handle, toBeHashed, (uint)length, 0);
		GC.KeepAlive (this);
	}

	public byte[] HashFinal () 
	{
		byte[] hash = new byte [hashSize];
		context.InternalResult = CryptoAPI.CryptGetHashParam (handle, CryptoAPI.HP_HASHVAL, hash, ref hashSize, 0);
		GC.KeepAlive (this);
		return hash;
	}
}

}