147 lines
4.3 KiB
C#
147 lines
4.3 KiB
C#
/******************************************************************************/
|
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
|
/* This work has been released under the CC0 1.0 Universal license! */
|
|
/******************************************************************************/
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace com.muldersoft.slunkcrypt.gui.utils
|
|
{
|
|
class SecureRandom : IDisposable
|
|
{
|
|
private volatile bool m_disposed = false;
|
|
|
|
private readonly RNGCryptoServiceProvider m_provider;
|
|
private readonly byte[] m_tempBuffer = new byte[256];
|
|
|
|
private int m_offset = int.MaxValue;
|
|
|
|
// =============================================================================
|
|
// Constructor
|
|
// =============================================================================
|
|
|
|
public SecureRandom()
|
|
{
|
|
try
|
|
{
|
|
m_provider = new RNGCryptoServiceProvider();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new IOException("Failed to create RNGCryptoServiceProvider instance!", e);
|
|
}
|
|
}
|
|
|
|
~SecureRandom()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
// =============================================================================
|
|
// Public methods
|
|
// =============================================================================
|
|
|
|
public int NextInt32()
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("SecureRandom");
|
|
}
|
|
EnsureBytesAvailable(sizeof(int));
|
|
int value = BitConverter.ToInt32(m_tempBuffer, m_offset);
|
|
m_offset += sizeof(int);
|
|
return value;
|
|
}
|
|
|
|
public uint NextUInt32()
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("SecureRandom");
|
|
}
|
|
EnsureBytesAvailable(sizeof(uint));
|
|
uint value = BitConverter.ToUInt32(m_tempBuffer, m_offset);
|
|
m_offset += sizeof(uint);
|
|
return value;
|
|
}
|
|
|
|
public long NextInt64()
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("SecureRandom");
|
|
}
|
|
EnsureBytesAvailable(sizeof(long));
|
|
long value = BitConverter.ToInt64(m_tempBuffer, m_offset);
|
|
m_offset += sizeof(long);
|
|
return value;
|
|
}
|
|
|
|
public ulong NextUInt64()
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("SecureRandom");
|
|
}
|
|
EnsureBytesAvailable(sizeof(ulong));
|
|
ulong value = BitConverter.ToUInt64(m_tempBuffer, m_offset);
|
|
m_offset += sizeof(ulong);
|
|
return value;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!m_disposed)
|
|
{
|
|
m_disposed = true;
|
|
GC.SuppressFinalize(this);
|
|
try
|
|
{
|
|
FillArray(m_tempBuffer, 0);
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
m_provider.Dispose();
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Internal methods
|
|
// =============================================================================
|
|
|
|
private void EnsureBytesAvailable(int length)
|
|
{
|
|
if ((m_offset >= m_tempBuffer.Length) || ((m_tempBuffer.Length - m_offset) < length))
|
|
{
|
|
try
|
|
{
|
|
m_provider.GetBytes(m_tempBuffer);
|
|
m_offset = 0;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new IOException("Failed to generated random bytes!", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void FillArray(byte[] array, byte value)
|
|
{
|
|
if (!ReferenceEquals(array, null))
|
|
{
|
|
for (int i = 0; i < array.Length; ++i)
|
|
{
|
|
array[i] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|