OSDN Git Service

GUI: Added button to generate a random password to the "Encrypt" tab.
[slunkcrypt/SlunkCrypt.git] / gui / Utilities / SecureRandom.cs
1 /******************************************************************************/
2 /* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
3 /* This work has been released under the CC0 1.0 Universal license!           */
4 /******************************************************************************/
5
6 using System;
7 using System.IO;
8 using System.Security.Cryptography;
9
10 namespace com.muldersoft.slunkcrypt.gui.utils
11 {
12     class SecureRandom : IDisposable
13     {
14         private volatile bool m_disposed = false;
15
16         private readonly RNGCryptoServiceProvider m_provider;
17         private readonly byte[] m_tempBuffer = new byte[256];
18
19         private int m_offset = int.MaxValue;
20
21         // =============================================================================
22         // Constructor
23         // =============================================================================
24
25         public SecureRandom()
26         {
27             try
28             {
29                 m_provider = new RNGCryptoServiceProvider();
30             }
31             catch (Exception e)
32             {
33                 throw new IOException("Failed to create RNGCryptoServiceProvider instance!", e);
34             }
35         }
36
37         ~SecureRandom()
38         {
39             Dispose();
40         }
41
42         // =============================================================================
43         // Public methods
44         // =============================================================================
45
46         public int NextInt32()
47         {
48             if (m_disposed)
49             {
50                 throw new ObjectDisposedException("SecureRandom");
51             }
52             EnsureBytesAvailable(sizeof(int));
53             int value = BitConverter.ToInt32(m_tempBuffer, m_offset);
54             m_offset += sizeof(int);
55             return value;
56         }
57
58         public uint NextUInt32()
59         {
60             if (m_disposed)
61             {
62                 throw new ObjectDisposedException("SecureRandom");
63             }
64             EnsureBytesAvailable(sizeof(uint));
65             uint value = BitConverter.ToUInt32(m_tempBuffer, m_offset);
66             m_offset += sizeof(uint);
67             return value;
68         }
69
70         public long NextInt64()
71         {
72             if (m_disposed)
73             {
74                 throw new ObjectDisposedException("SecureRandom");
75             }
76             EnsureBytesAvailable(sizeof(long));
77             long value = BitConverter.ToInt64(m_tempBuffer, m_offset);
78             m_offset += sizeof(long);
79             return value;
80         }
81
82         public ulong NextUInt64()
83         {
84             if (m_disposed)
85             {
86                 throw new ObjectDisposedException("SecureRandom");
87             }
88             EnsureBytesAvailable(sizeof(ulong));
89             ulong value = BitConverter.ToUInt64(m_tempBuffer, m_offset);
90             m_offset += sizeof(ulong);
91             return value;
92         }
93
94         public void Dispose()
95         {
96             if (!m_disposed)
97             {
98                 m_disposed = true;
99                 GC.SuppressFinalize(this);
100                 try
101                 {
102                     FillArray(m_tempBuffer, 0);
103                 }
104                 finally
105                 {
106                     try
107                     {
108                         m_provider.Dispose();
109                     }
110                     catch { }
111                 }
112             }
113         }
114
115         // =============================================================================
116         // Internal methods
117         // =============================================================================
118
119         private void EnsureBytesAvailable(int length)
120         {
121             if ((m_offset >= m_tempBuffer.Length) || ((m_tempBuffer.Length - m_offset) < length))
122             {
123                 try
124                 {
125                     m_provider.GetBytes(m_tempBuffer);
126                     m_offset = 0;
127                 }
128                 catch (Exception e)
129                 {
130                     throw new IOException("Failed to generated random bytes!", e);
131                 }
132             }
133         }
134
135         private static void FillArray(byte[] array, byte value)
136         {
137             if (!ReferenceEquals(array, null))
138             {
139                 for (int i = 0; i < array.Length; ++i)
140                 {
141                     array[i] = value;
142                 }
143             }
144         }
145     }
146 }