using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace APress.DotNetSecurity.Chapter2.ExcludingRNG
{
class ExcludingRNGTester
{
static void Main(string[] args)
{
try
{
byte[] randomExcludedData = new byte[255];
byte[] excludedData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
Console.WriteLine("Excluded bytes are " +
ArrayToHexString(excludedData));
Console.WriteLine("Creating the FineGrainedRNG instance...");
FineGrainedRNG fng = new ExcludingRNG();
Console.WriteLine("Getting the excluded random bytes...");
fng.GetBytes(randomExcludedData, excludedData);
Console.WriteLine("Random bytes are " +
ArrayToHexString(randomExcludedData));
}
catch(CryptographicUnexpectedOperationException cuoe)
{
Console.WriteLine("CryptographicUnexpectedOperationException: "
+ cuoe.Message);
Console.WriteLine(cuoe.StackTrace);
}
catch(CryptographicException ce)
{
Console.WriteLine("CryptographicException: " + ce.Message);
Console.WriteLine(ce.StackTrace);
}
catch(Exception ge)
{
Console.WriteLine("Exception: " + ge.GetType().Name + " " + ge.Message);
Console.WriteLine(ge.StackTrace);
}
finally
{
Console.WriteLine("Press the return key to continue...");
Console.Read();
}
}
private static String ArrayToHexString(byte[] ByteData)
{
StringBuilder retVal = new StringBuilder();
foreach(byte b in ByteData)
{
retVal.Append(b.ToString("X2"));
retVal.Append(" ");
}
retVal.Remove(retVal.Length - 1, 1);
return retVal.ToString();
}
}
public interface FineGrainedRNG
{
void GetBytes(byte[] data, byte[] excludedValues);
}
public class ExcludingRNG : RNGCryptoServiceProvider, FineGrainedRNG
{
public ExcludingRNG() : base()
{
}
public void GetBytes(byte[] data, byte[] excludedValues)
{
if(null != excludedValues && excludedValues.Length > 0)
{
byte[] tempData = {1};
for(int i = 0; i < data.Length; i++)
{
do
{
base.GetBytes(tempData);
} while (Array.IndexOf(excludedValues, tempData[0]) >= 0);
data[i] = tempData[0];
}
}
else
{
throw new ArgumentException("The excludedValues argument is invalid.");
}
}
}
}