If you have used Random() in C# to any extent before you probably know it isen't really that random, and can produce quite predictable results. Especially when it's being used in threads or parallel loops. I had such a scenario recently where I needed to have a better random number generator that even when used on different threads or from different instances still produced random numbers.
So how do you get a better random number than what Random() can provide?
Easy answer is you use the RNGCryptoServiceProvider. The purpose of this class is to create cryptographically strong random data. Perfect for the task at hand.
Here is the code I created for generating random integers between a given interval. I'm using the RNGCryptoServiceProvider to produce 4 bytes of random data that I then convert to an integer. The produced integer is somewhere between -int.Max and int.Max. So I reduce the size of the number by the proportion of the size of the range wanted as compared to the full range of an Int32 and then take the absolute value of that.
public int GetRealRandom(int min = 0, int max = int.MaxValue)
{
if (max <= min)
throw new ArgumentOutOfRangeException("max paramater must be greater than min paramater");
int result = 0;
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] data = new byte[4];
rng.GetBytes(data);
int value = BitConverter.ToInt32(data, 0);
result = value;
var proportion = (max - min + 0d) / int.MaxValue;
result = Math.Abs((int) Math.Round((result*proportion)));
result += min;
}
return result;
}
And to validate it you can use this Unit Test to check the result. Note that this test might fail if you dont do enough iterations to produce a big enough data set to test it on.
[TestMethod]
public void GenerateRealRandom()
{
var min = 0;
var max = 1000;
var pn = new List<int>();
foreach (var r in Enumerable.Range(0, 100000))
{
var number = GetRealRandom(min, max);
pn.Add(number);
Assert.IsTrue(number <= max && number >= min);
}
var average = pn.Average();
var minVal = pn.Min();
var maxVal = pn.Max();
var middle = (max - min) / 2;
Assert.IsTrue(average < middle + 1 && average > middle - 1);
Assert.IsTrue(minVal <= min + 1);
Assert.IsTrue(maxVal >= max - 1);
}
While creating a unit tests I tried to find code to generate Swedish personnumbers but couldent really find any copy paste pieces of code. So to remedy that here is a method which will generate a valid Swedish "Personnummer"
I tried to get it down to a single line but this is as close as I got before realising I have better things to do. If someone can make this into a single line of code I'd love to see that in a comment ;)
Update: Ok so I coulden't let it go and spent a few more minutes trying golf the code down in size. This is the shortest I managed, it's 189 characters long. Not very readable but it does generate a valid personnummer of a person between the ages of 10 and 60. Still coulden't manage to make it in one line of code though.
Here are 3 sample personnummer/social security numbers generated by the above code:
Update 2: As per the request in the comment here is a version of the code where you can set the age of the person whom you are want the personnumber to be generated for. Also included the unit test I used as this code is a little trickier.
Also including the unit test for this code if you want to validate that it actully produces propper values.
Some tags (in Swedish) which might help people searching for this: Generera personnummer med C# kod. Personnummer, Generera, Svenskt personnummer, Skapa personnummer för test, fejka personnummer. Generera personnummer i C#.
This is a function I find myself writing quite often, so I thought I would just post it here for future reference. It's purpose is simple, check if an array contains an element with a given key and value, if it does, return it other wise return a null value.
I was recently asked how hard it would be to create a home network that is completely secure (as close as it gets anyways) from snooping ISPs or third parties so that the user can browse any site they want without risking anyone finding out about it. This means both tunneling all traffic through a VPN connection but also blocking any and all traffic that tries to get around the VPN. That is, no traffic should go directly to the ISP even if the VPN connection goes down.
There are several use cases for this, the most common probably being:
The only downside to using a VPN is that your internet will be slightly slower, but if you use a good VPN provider you will only ever notice this if you are playing online action FPS games such as Counterstrike or Battlefield, for regular surfing or watching movies you will not notice any difference.
What we are really doing is creating a secure tunnel through your ISP to the VPN redirecting all the traffic so that it seems to come from the VPN provider, leaving your ISP clueless to what you are doing and anyone on the internet only ever sees your VPN providers IP and never your real one.
To get this to work you need:
I will assume that you have installed DD-WRT and are connected to the router at this point.
The file should look similar to this:
This is what my OpenVPN client settings looked like after doing the above.
Copy everything between the <ca></ca> tags including the begin and end text with their ---- lines and paste it into the CA Cert field.
Once you have done all of the above steps you should be hidden behind a VPN. The VPN might however go down, and in such cases I wanted to make sure I am not leaking any information by accident. The solution for this is simple and called firewalls and iptables.
This will allow all connections between tun0 (the VPN) and br0 (your LAN) and also block all traffic between br0 and vlan2 (the WAN port)
Two methods for formatting currency in C#.
The purpose being that you can throw a string containging a number in it and get out a nicely formatted string containing something you can present to a user.
Example of output.
var amountParsed = FormatCurrency("3123", "USD", true, "Not Known");
> 3 123 USD
var amountParsed = FormatCurrency("31.3", "USD", true, "Not Known");
> 31.30 USD
var amountParsed = FormatCurrency("12343", "USD", false, "Not Known");
> 12 343 USD
var amountParsed = FormatCurrency("XXX", "USD", false, "Not Known");
> Not Known
Code:
private static string FormatCurrency(string decimalStringValue, string currency, bool includeDecimals, string emptyPlaceHolder)
{
if (string.IsNullOrEmpty(decimalStringValue) == false)
{
decimal decResult = 0;
try
{
if (decimal.TryParse(decimalStringValue.Trim(), out decResult))
{
string formatted = FormatCurrency(decResult, currency, includeDecimals);
return formatted;
}
}
catch (Exception) {}
}
return emptyPlaceHolder;
}
private static string FormatCurrency(decimal decimalValue, string currency, bool includeDecimals)
{
if (string.IsNullOrEmpty(currency))
currency = "SEK";
var decimalTemp = Math.Round(decimalValue, 2);
var nfi = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
nfi.NumberGroupSeparator = " ";
string formatted = decimalTemp.ToString("#,0.00", nfi);
if (includeDecimals == false)
{
if (formatted.LastIndexOf('.') >= 0)
formatted = formatted.Substring(0, formatted.LastIndexOf('.'));
}
formatted = formatted.Trim() + " " + currency;
return formatted.Trim();
}