New test.
[mono.git] / mcs / class / Mono.Security.Win32 / Mono.Security.Cryptography / RNGCryptoServiceProvider.cs
1 //
2 // Mono.Security.Cryptography.RNGCryptoServiceProvider
3 //
4 // Authors:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //
7 // Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 //
9
10 using System;
11 using System.Security.Cryptography;
12 using System.Text;
13
14 namespace Mono.Security.Cryptography {
15         
16 public class RNGCryptoServiceProvider : RandomNumberGenerator {
17
18         private CapiRandomNumberGenerator rng;
19         private byte[] seed;
20
21         public RNGCryptoServiceProvider () 
22         {
23                 rng = new CapiRandomNumberGenerator ();
24                 seed = null;
25         }
26
27         public RNGCryptoServiceProvider (byte[] rgb) 
28         {
29                 rng = new CapiRandomNumberGenerator ();
30                 seed = rgb;
31         }
32
33         public RNGCryptoServiceProvider (CspParameters cspParams) 
34         {
35                 rng = new CapiRandomNumberGenerator (cspParams);
36                 seed = null;
37         }
38
39         public RNGCryptoServiceProvider (string str) 
40         {
41                 rng = new CapiRandomNumberGenerator ();
42                 seed = Encoding.Default.GetBytes (str);
43         }
44
45         ~RNGCryptoServiceProvider () 
46         {
47                 // zeroize seed
48                 if (seed != null)
49                         Array.Clear (seed, 0, seed.Length);
50                 // release unmanaged resources
51                 rng.Dispose ();
52         }
53
54         public override void GetBytes (byte[] data) 
55         {
56                 if (data == null)
57                         throw new ArgumentNullException ("data");
58
59                 // send the seed
60                 if (seed != null)
61                         rng.GenRandom (seed);   
62                 // note: by doing this seed is modified each time
63
64                 rng.GenRandom (data);
65
66                 // generate random
67                 if (!rng.Result)
68                         throw new CryptographicException (rng.Error);
69         }
70
71         public override void GetNonZeroBytes (byte[] data) 
72         {
73                 byte[] random = new byte [data.Length * 2];
74                 int i = 0;
75                 // one pass should be enough but hey this is random ;-)
76                 while (i < data.Length) {
77                         GetBytes (random);
78                         for (int j=0; j < random.Length; j++) {
79                                 if (i == data.Length)
80                                         break;
81                                 if (random [j] != 0)
82                                         data [i++] = random [j];
83                         }
84                 }
85         }
86 }
87
88 }