I created a random string. First, I'd like to display the string and after that, I'd like to convert it to a MD5 hash. Can someone help me? I tried a lot but I can't get the right solution.
Here is my Code:
public static string Generate(int lenght)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
return new string(Enumerable.Repeat(chars, lenght).Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string MD5Hash()
{
StringBuilder hash = new StringBuilder();
MD5CryptoServiceProvider md5provider = new MD5CryptoServiceProvider();
byte[] bytes = md5provider.ComputeHash(new UTF8Encoding().GetBytes(Generate));
for (int i = 0; i < bytes.Length; i++)
{
hash.Append(bytes[i].ToString("x2"));
}
return hash.ToString();
}
Thank you in advance
Best Regards
Either pass a string argument into the MD5Hash method (MD5Hash(string input) for example) OR you can use the Generate method inside the MD5Hash method (string input = Generate(*LengthYouWant*); for example).
Afterwards you can replace the Generate you've put inside of GetBytes currently with the input string.
Related
I want to create a unique ID from a string like "Testcase1", "Testcase2" and so on. Therefore I want to convert the string to a integer respectively a long.
I've tried this, but I think the number/ID is neither unique nor is this method correct. I want to convert the entire word into a number.
long numberId = 0;
foreach (var character in testString.ToCharArray())
{
numberId += Convert.ToInt16(character);
}
How about this?
var sha = System.Security.Cryptography.SHA512.Create();
var inputBytes = System.Text.Encoding.ASCII.GetBytes("Test case");
var hash = sha.ComputeHash(inputBytes);
var result = BitConverter.ToInt64(hash);
I dont have proof but I think following method will generate unique value.
public static void Main()
{
long numberId = 0;
var testString = "Testcase3";
long multiplier = (long)Math.Pow(10,testString.Length);
foreach (var character in testString.ToCharArray())
{
numberId += Convert.ToInt16(character)*multiplier;
multiplier /=10;
}
Console.WriteLine(numberId);
}
Not sure if this is what you are after:
static void Main(string[] args)
{
var inputText = "Testcase1";
Console.WriteLine($"{inputText} =>{CalculateTotal(GetHashString(string.Concat(inputText,DateTime.Now.Date.ToString(), DateTime.Now.TimeOfDay.ToString())).ToArray<char>())}");
inputText = "Testcase2";
Console.WriteLine($"{inputText} =>{CalculateTotal(GetHashString(string.Concat(inputText,DateTime.Now.Date.ToString(), DateTime.Now.TimeOfDay.ToString())).ToArray<char>())}");
}
static string GetHashString(string inputText)
{
HashAlgorithm hash = new SHA256Managed();
var bytes = new byte[inputText.Length];
bytes = Encoding.ASCII.GetBytes(inputText);
return Encoding.ASCII.GetString( hash.ComputeHash(bytes));
}
static long CalculateTotal(char [] items)
{
var i = Array.ConvertAll<char, long>(items, Convert.ToInt64);
return i.Sum();
}
output:
Testcase1 =>1880
Testcase2 =>1788
If it needs to be unique then long won't work, because there are more strings than can fit into a long. If you really need a unique number, you could use the constructor of System.Numerics.BigInteger that takes a byte array, e.g.
var id = new BigInteger(Encoding.Unicode.GetBytes("string goes here"));
Depending on what you're doing, this may or may not be useful.
How about this implementation using the sum of byte array based on the test string:
long uniqueId = "Testcase1".SelectMany(BitConverter.GetBytes).ToArray().Sum(c=> c);
long uniqueId2 = "Testcase2".SelectMany(BitConverter.GetBytes).ToArray().Sum(c => c);
Testcase1 ->877
Testcase2 ->878
I, like many hopeless romantics in the online world, believe that I can successfully mine bit coins. Problems is, I can't get the basic algorithm correct for taking data from a previous mine block and creating the hash for the next mined block. I understand from several articles that we start with the current hash of a block, reverse and append the merkel root, add the nonce, then get the SHA256 hash of that string.
static void Main(string[] args)
{
//get the hash of the current block
string currentHash =
#"000000000000000000c5c04011f9a3fb5f46064fed7e06dcdae69024ed6484c1";
//get the merkel root
string merkel =
#"f73a382814c51cbc5a59ab9817ac54c63decb7b3dac5b049df5213c029162bdf";
//reverese the merkel root
char[] c = merkel.ToCharArray();
Array.Reverse(c);
merkel = new string(c);
//get a hash object that returns SHA256
Hash hash = new Hash();
//get the nonce that mined the block
uint nonce = 3546041956;
//string together current hash, merkel root and the hex of the nonce
string stringTotal = currentHash + merkel + nonce.ToString("x2");
//calculate the SHA256 hash of the
string nextHash = hash.GetHash(stringTotal);
Console.WriteLine(nextHash);
Console.ReadKey();
}
Anyone know the correct algorithm? I used this block https://blockchain.info/block-height/477065 and tried to calculate the hash for the next block.
So I was curious about the same thing. This is what I came up with. It's obviously not production quality, but it gets the idea across and seems to work.
It probably would have been much easier if it weren't for the reverse and swap logic that was practically undocumented everything I was looking.
Anyways, hope this helps. I found a bunch of help here if you're interested: http://trogers.net/2018/01/29/how-to-validate-a-bitcoin-blocks-proof-of-work-c/
class Program
{
static void Main(string[] args)
{
// https://blockchain.info/block-height/286819
int version = 2;
string previousBlock = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717";
string merkelRoot = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a";
uint nonce = 856192328;
long timestamp = new DateTimeOffset(DateTime.SpecifyKind(DateTime.Parse("2014-02-20 04:57:25"), DateTimeKind.Utc)).ToUnixTimeSeconds();
uint bits = 419520339;
var header = new StringBuilder()
.Append(ReverseAndSwap(version.ToString("D8")))
.Append(ReverseAndSwap(previousBlock))
.Append(ReverseAndSwap(merkelRoot))
.Append(ReverseAndSwap(timestamp.ToString("x2")))
.Append(ReverseAndSwap(bits.ToString("x2")))
.Append(ReverseAndSwap(nonce.ToString("x2")))
.ToString();
Debug.Assert(string.CompareOrdinal(header, "0200000017975b97c18ed1f7e255adf297599b55330edab87803c81701000000000000008a97295a2747b4f1a0b3948df3990344c0e19fa6b2b92b3a19c8e6badc141787358b0553535f011948750833") == 0);
var bytes = HexToBytes(header);
SHA256 sha = new SHA256Managed();
bytes = sha.ComputeHash(sha.ComputeHash(bytes)).Reverse().ToArray();
var hash = BytesToHex(bytes);
Debug.Assert(string.CompareOrdinal(hash, "0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50") == 0);
}
private static string ReverseAndSwap(string input)
{
StringBuilder sb = new StringBuilder();
for (var i = input.Length - 1; i >= 0; i--)
{
sb.Append(input[i - (i % 2 == 0 ? -1 : 1)]);
}
return sb.ToString();
}
public static byte[] HexToBytes(string hex)
{
byte[] hexAsBytes = new byte[hex.Length / 2];
for (int index = 0; index < hexAsBytes.Length; index++)
{
string byteValue = hex.Substring(index * 2, 2);
hexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return hexAsBytes;
}
public static string BytesToHex(byte[] bytes)
{
var output = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < bytes.Length; ++i)
{
output.AppendFormat("{0:x2}", bytes[i]);
}
return output.ToString();
}
}
After 24 hours worth of programming I finally cracked, I want to make a C# WindowsForm application that shows you the value of a hashed hexstring input like in hashcalc.
I could only make it for textstring input even after googling it.
To demonstrate, the input 060201080808040602040909080909003583150369840500 should output d8f6b336a4df3336bf7de58a38b1189f6c5ce1e8
and not a6879cb4510b18e8f41b3491ce474fd2ff9e2979
Also this is for SHA1 Hashing so keep it only at that, Thanks!
For this 090505050509050009080003000605003569190380108300
I have 3b8d562adb792985a7393a6ab228aa6e7526410a, not 3b8d562adb792985a7393a6ab228aa6e752641a
I think that the last byte is wrong.
I think I don't really understand your problem. You can hash any input and output it any way you want. To achieve this, you are likely to use the Encoding class with an encoding of your choice and call the GetBytes() method. Then you take the SHA1 class and let it calculate the hash value. And for user text you tell the string class to use hex formatting for numbers. And this not only applies to the SHA1 class ;)
You need to import the namespace:
using System.Security.Cryptography
and call
var hash = new SHA1CryptoServiceProvider().ComputeHash(inputBytes);
to produce the hash.
If your problem is about converting the hex string to bytes, here's a full sample that shows how to parse the input and format the output:
var input = "060201080808040602040909080909003583150369840500";
// parse the input into a byte[]
var inputBytes = Enumerable.Range(0, input.Length/2)
.Select(i => input.Substring(i*2, 2))
.Select(s => byte.Parse(s, NumberStyles.HexNumber))
.ToArray();
var hash = new SHA1CryptoServiceProvider().ComputeHash(inputBytes);
var outputHexString = string.Join(" ",
hash.Select(b => b.ToString("X")).ToArray());
Console.WriteLine(outputHexString);
Here's how it works: http://ideone.com/BE7ecU
private void button1_Click(object sender, EventArgs e)
{
string input= "060201080808040602040909080909003583150369840500";
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] hash = sha1.ComputeHash(ConvertHexStringToByteArray(input));
string delimitedHexHash = BitConverter.ToString(hash);
string hexHash = delimitedHexHash.Replace("-", "");
MessageBox.Show(hexHash);
}
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
}
byte[] HexAsBytes = new byte[hexString.Length / 2];
for (int index = 0; index < HexAsBytes.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return HexAsBytes;
}
I'm trying to generate a 16 chars random string with NO DUPLICATE CHARS. I thoght that it shouldn't be to hard but I'm stuck.
I'm using 2 methods, one to generate key and another to remove duplicate chars. In main I've created a while loop to make sure that generated string is 16 chars long.
There is something wrong with my logic because it just shoots up 16-char string
with duplicates. Just can't get it right.
The code:
public string RemoveDuplicates(string s)
{
string newString = string.Empty;
List<char> found = new List<char>();
foreach (char c in s)
{
if (found.Contains(c))
continue;
newString += c.ToString();
found.Add(c);
}
return newString;
}
public static string GetUniqueKey(int maxSize)
{
char[] chars = new char[62];
chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
data = new byte[maxSize];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(maxSize);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length)]);
}
return result.ToString();
}
string builder = "";
do
{
builder = GetUniqueKey(16);
RemoveDuplicates(builder);
lblDir.Text = builder;
Application.DoEvents();
} while (builder.Length != 16);
Consider implementing shuffle algorithm with which you will shuffle your string with unique characters and then just pick up first 16 characters.
You can do this in-place, by allocating single StringBuffer which will contain your initial data ("abc....") and just use Durstenfeld's version of the algorithm to mutate your buffer, than return first 16 chars.
There are many algorithms for this.
One easy one is:
Fill an array of chars with the available chars.
Shuffle the array.
Take the first N items (where N is the number of characters you need).
Sample code:
using System;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
Random rng = new Random();
for (int i = 0; i < 10; ++i)
{
string randomString = RandomString(16, chars, rng);
Console.WriteLine(randomString);
}
}
public static string RandomString(int n, char[] chars, Random rng)
{
Shuffle(chars, rng);
return new string(chars, 0, n);
}
public static void Shuffle(char[] array, Random rng)
{
for (int n = array.Length; n > 1; )
{
int k = rng.Next(n);
--n;
char temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
}
const string chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var r = new Random();
var s = new string(chars.OrderBy(x => r.Next()).Take(16).ToArray());
I am using a GUID generation method it itself generates random strings and you can modify it if a number appears in the beginning,
use the code given below:
string guid = System.Guid.NewGuid().ToString("N");
while (char.IsDigit(guid[0]))
guid = System.Guid.NewGuid().ToString("N");
Hope that helps.
See if this helps:
RandomString()
{
string randomStr = Guid.NewGuid().ToString();
randomStr = randomStr.Replace("-", "").Substring(0, 16);
Console.WriteLine(randomStr);
}
This returns alpha-numeric string.
I am making a password generator that generates a random number, then I have it converted to a letter using ascii. Inside the for loop, I need the letters to convert a string instead of a list. It works, but it just displays random letters as a list.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class MainClass
{
static void Main()
{
int x = 1;
int length;
string a = "Press any key to continue";
object num;
while (x == 1)
{
Console.WriteLine("How many Characters would you like the Password to be? (Press -1 to Stop)");
length = Convert.ToInt32(Console.ReadLine());
try
{
for (int i = 0; i < length; i++)
{
int num1 = Number();
Int32 ASCII = num1;
num = (char)num1;
if (length > 0)
{
Console.WriteLine(num);
}
}
}
catch
{
Console.WriteLine(a);
}
if (length == -1)
break;
}
}
static Random _r = new Random();
static int Number()
{
return _r.Next(65, 90); // decimal
}
}
StringBuilder sb = new StringBuilder();
for( int i = 0; i < length; i++ )
{
int num1 = Number();
Int32 ASCII = num1;
num = (char)num1;
sb.Append( num );
}
Console.WriteLine( sb.ToString() );
This isn't how I would build a password nor how I would generate random text, but this will give you a string and answer the original question.
As to how I would do this task:
System.Security.Cryptography.RNGCryptoServiceProvider _crypto = new System.Security.Cryptography.RNGCryptoServiceProvider();
byte[] bytes = new byte[8]; // this array can be larger if desired
_crypto.GetBytes( bytes );
ulong randomNumber = (ulong)BitConverter.ToInt64( bytes, 0 );
// convert to a string with the encoding of your choice; I prefer Base 62
For completeness sake, here's a Base62 algorithm which I use. Base62 has the advantage over the more commonly-used Base64 in that it does not include any special characters so it is easy to use in query strings, HTML, and JavaScript (with a few minor caveats). Of course, passwords shouldn't be used in any of those places, and you may want to include special characters to make a password more complex.
Regardless, here is how I convert random numbers to Base62.
private static readonly char[] _base62Characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
public static string ToBase62String( long value )
{
if( value < 0L )
{
throw new ArgumentException( "Number must be zero or greater." );
}
if( value == 0 )
{
return "0";
}
string retVal = "";
while( value > 0 )
{
retVal = _base62Characters[value % 62] + retVal;
value = value / 62;
}
return retVal;
}
Lastly, I want to point out that passwords should very rarely be generated for any purpose, because that means they are being distributed in some form. Passwords should be hashed and salted; password resets should rely on random, expiring security tokens allowing the user a one-time reset. Passwords should never be emailed to a user; passwords should never be stored in plaintext or any reversible format.
For password reset token generation, the code I provided could work nicely because it produces a large, cryptographically random number encoded with a web-safe format. But even a hashed GUID would do the trick in that case.
var sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.Append((char)Number());
}
string password = sb.ToString();
Console.WriteLine(password );
But I would change your Number() method to:
private static char GetRandomChar()
{
return (char)_r.Next(65, 90);
}
and then replace the line inside the loop:
sb.Append(GetRandomChar());
//You have to append the values generated by the RandomNumber in to your password variable
class MainClass
{
static void Main()
{
int x = 1;
int length;
string a = "Press any key to continue";
string num=string.Empty;
while (x == 1)
{
Console.WriteLine("How many Characters would you like the Password to be? (Press -1 to Stop)");
length = Convert.ToInt32(Console.ReadLine());
try
{
for (int i = 0; i < length; i++)
{
int num1 = Number();
Int32 ASCII = num1;
num =num+ ((char)num1);
}
Console.WriteLine(num);
}
catch
{
Console.WriteLine(a);
}
if (length == -1)
break;
}
}
static Random _r = new Random();
static int Number()
{
return _r.Next(65, 90); // decimal
}
}
you can try this one
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PasswordSample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Generated password: {0}", GeneratePassword(12, true));
}
/// <summary>
/// Generate a random password
/// </summary>
/// <param name="pwdLenght">Password lenght</param>
/// <param name="nonAlphaNumericChars">Indicates if password will include non alpha-numeric</param>
/// <returns>Return a password</returns>
private static String GeneratePassword(int pwdLenght, bool nonAlphaNumericChars)
{
// Allowed characters
String allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
if (nonAlphaNumericChars)
{
// Add non-alphanumeric chars
allowedChars += "-&##%!*$?_";
}
char[] passwordChars = new char[pwdLenght];
Random rnd = new Random();
// Generate a random password
for (int i = 0; i < pwdLenght; i++)
passwordChars[i] = allowedChars[rnd.Next(0, allowedChars.Length)];
return new String(passwordChars);
}
}
}
just define a string at near int x...
like
String Password = "";
and in the if statement appent the keyyword.
if (length > 0)
{
Console.WriteLine(num);
Password+=num
}
I found the following post useful when I had to create a method to generate a random password:
https://stackoverflow.com/a/730352/1015289
However, when I wanted to create a short 'validation' style code which would be emailed to a user to confirm their details, I wanted to restrict the validation code to only 8 characters.
For this I used the following:
string validationCoce = Guid.NewGuid().ToString().Substring(0, 8);
This would be stored in a database which also held the users email, both encrypted before being stored for security purposes.
Both the email and validation code were required to validate the users account.
Hope either of the above help?
Kind Regards, Wayne
use Console.Write() instead of Console.WriteLine() otherwise append to some string and print outside the loop