/******************************************************************************/ /* SlunkCrypt, by LoRd_MuldeR */ /* 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; } } } } }