SHA512 reverse (Decrypt) of CreateSHAHash function in c# - c#

How can i Decrypt the encrypted sctring in SHA512
static readonly string securityCode = "mJeb44V5grh0pTB6wgepSw==";
encrypted_Text = CreateSHAHash("12345");
public static string CreateSHAHash(string PasswordSHA512)
{
SHA512Managed sha512 = new SHA512Managed();
Byte[] EncryptedSHA512 = sha512.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(PasswordSHA512, securityCode)));
sha512.Clear();
return Convert.ToBase64String(EncryptedSHA512);
}

In general, you can't "decrypt" a hashed string, because encryption is always a reversible transformation, and hashing is not reversible by design.
To see why hashing isn't reversible without needing to use any math, consider:
A SHA-512 hash is always exactly the same length.
That means there are only a finite number of messages it can encode.
But there are an infinite number of possible messages you might choose to hash.
By the pigeonhole principle, you cannot map an infinite number of messages into a finite number of hashes.
∴ You can't reverse a hash to the original message.

Related

Securing users passwords using c# - Rfc2898DeriveBytes vs SHA512

I've been reading about securing users passwords in the database (https://crackstation.net/hashing-security.htm). The basic idea is understood - generate a random Salt, append it to the password and hash the password.
So here's what I did (I didn't put here some methods that do conversion to strings):
RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
byte[] rndBytes = new byte[512];
randomNumberGenerator.GetBytes(rndBytes);
string salt = ToHexString(rndBytes);
var sha512Hasher = SHA512.Create();
string hashedPwd = ToHexString(sha512Hasher.ComputeHash(GetBytes(pwd + salt)))
According to the article this is secured but can be even more secured by using "key stretching" which for my understanding is hashing that done slower (using a parameter) to make brute-force the password harder.
So here's what I did:
RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
byte[] salt = new byte[512];
randomNumberGenerator.GetBytes(salt);
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(user.Password, salt, 1000);
byte[] hashBytes = k1.GetBytes(512);
string hash = ToHexString(hashBytes);
Now here are my questions:
What is the difference between SHA512 and Rfc2898DeriveBytes? which is more secure?
Should I have smaller salt with more iterations? Will it make it more secure?
On a 1000 iterations it runs very fast - how slow should it be? half a second? a second? What is the rule of thumb here?
On the database - should I convert the byte array to string and store strings or should I store the byte array in a binary data field?
Edit (another questions)
If I iterate a 1000 times over rehashing SHA512 - does it give the same security?
What is the difference between SHA512 and Rfc2898DeriveBytes?
SHA512 is a cryptographic hash function, while Rfc2898DeriveBytes is a key-derivation function. As you already wrote, hash functions are too fast and can be brute-forced too easily, that's why we need functions with a cost factor like BCrypt, SCrypt, PBKDF2 or Argon2. As far as i know, Rfc2898DeriveBytes implements the PBKDF2 using a HMAC with SHA1. This answers your other question that an iterated SHA is less secure than Rfc2898DeriveBytes.
Should I have smaller salt with more iterations?
Salt and cost factor are not related and have different purposes. The salt prevents the usage of rainbow tables, the iterations are a counter measure for brute-force attacks. More infos you can get from my tutorial about safe password storage. So no, don't make the salt shorter.
how slow should it be?
Of course this depends on your server and your requirements for security, slower means harder to brute-force. A rule of thumb is about 50 milliseconds for a single hash.
On the database - should I convert the byte array to string?
This is up to you. Strings are easier to handle for backups, migration and debugging, while byte arrays need less space in the database. Maybe you should also have a look at BCrypt.Net, it generates strings as output which contain the salt and are easy to store in a single database field [string].

How to generate a SHA256 encrypted string in C#?

For a project I need to generate a SHA256 encrypted string in C#.
The requirements are Key: todaysDate and Value: "exampleString".
How can i realize that in C#? As far as I see the SHA256-Class does not contain a property for key in C#.
SHA256 isn't an encryption algorithm, it's a hash algorithm. In other words, it's a one way function whose job is to take an input of any length and produce an output of fixed length with low collisions that's always the same for the same input. Thus, it doesn't receive a key as an input because the nature of hashing is quite different from that of encryption.
If you want to encrypt something with a key and later decrypt it by having the same key, look into symmetric encryption like AES (e.g. using the AesManaged class).
You should do your own homework. If we do it for you, you learn nothing.
Also, as Theodoros mentioned, SHA256 is a hash, not encryption. A hash is a cryptographic checksum that is used to validate or compare data. It can not be reversed into the original plaintext, which is a requirement of encryption.
How can i realize that in C#? As far as I see the SHA256-Class does not contain a property for key in C#.
Either you or the person who gave you the assignment doesn't understand what is being asked.
SHA256 doesn't have a key or a value, it only has data going in and a hash coming out. No matter how much data you run through it, the size of the hash does not change, although it's value does. You can think of a hash as a fingerprint for a particular dataset.
Maybe something like this:
public static string sha256_hash(string sValue) {
StringBuilder oResHash = new StringBuilder();
using (SHA256 oHash = SHA256Managed.Create()) {
Encoding oEnc = Encoding.UTF8;
byte[] baResult = oHash.ComputeHash(oEnc.GetBytes(sValue));
foreach (byte b in baResult)
oResHash.Append(b.ToString("x2"));
}
return oResHash.ToString();
}

The data to be decrypted exceeds the maximum for this modulus of 36 bytes

I'm trying to make a password safe, but theres something wrong with how I use RSA.
Heres my codes:
private void testencodedecode()
{
string mehdi = "mehdi";
var enc = encodePass(mehdi);
var dec = decodePass(enc);
}
private RSAParameters rsaKey()
{
var setting = context.Settings.First(s => s.ID == 1);
byte[] pwd = Encoding.ASCII.GetBytes(setting.PWDKEY);
byte[] expo = {1,0,1};
var key = new System.Security.Cryptography.RSAParameters();
key.Exponent = expo;
key.Modulus = pwd;
return key;
}
private string encodePass(string pass)
{
var provider = new RSACryptoServiceProvider();
provider.ImportParameters(rsaKey());
var encryptedBytes = provider.Encrypt(Encoding.UTF8.GetBytes(pass), false);
return Encoding.UTF8.GetString(encryptedBytes);
}
private string decodePass(string pass)
{
var provider = new RSACryptoServiceProvider();
provider.ImportParameters(rsaKey());
string decrypted = Encoding.UTF8.GetString(provider.Decrypt(Encoding.UTF8.GetBytes(pass), true));
return decrypted;
}
It seems to encrypt fine, but on decryption has the following error:
The data to be decrypted exceeds the maximum for this modulus of 36 bytes.
There are some major issues with the method here. The first, as you mentioned in a comment on another answer is that you're using a Guid to construct the RSA modulus, which is entirely invalid. You cannot use random data to construct the public key directly for a number of reasons:
The modulus must conform to a specific structure, i.e. it is the product of two large prime numbers, whereas your Guid in binary form generally will not be.
In order to decrypt the RSA-encrypted data, you must know the two primes used to generate the modulus. Even if your random modulus was magically the product of two large primes you wouldn't be able to determine them, since this would require factoring the modulus, which is an intentionally difficult thing to do (indeed, the difficulty is the entire basis of RSA's security).
You should be generating the RSA key using the RsaCryptoServiceProvider constructor e.g.:
// Construct the RsaCryptoServiceProvider, and create a new 2048bit key
var csp = new RsaCryptoServiceProvider(2048);
The parameters for this newly generated key can then be exported:
// Export the RSA parameters, including the private parameters
var parameters = csp.ExportParameters(true);
The parameters can then be stored (securely) and used to re-initialize the CSP for decryption later.
There are also other obvious problems, such as the fact that the amount of data you can actually encrypt with RSA is limited by the key size, so with a 2048 bit key as created above, you can encrypt 2048 / 8 - 11 = 245 bytes (where the 11 bytes is a result of the PKCS#1 v1.5 padding that is applied). If you want to encrypt more than this, the general method is to use a symmetric cipher (e.g. AES) to encrypt the data, and then use RSA only to encrypt the AES key.
Finally, whilst this may work, I still wouldn't rely on it for security as there are almost always issues with roll-your-own encryption schemes.
The modulus for RSA should be at least 1024 bits (128 bytes). Anything less will be completely insecure. And for modern applications it is even recommended to use a 2048 or larger modulus.
And secondly, you are not generating the RSA keys properly! You shouldn't just use the password as a modulus..
The public exponent and the modulus must be chosen such that the exponent is relatively prime to p-1 for all primes p which divide the modulus. If you are just arbitrarily setting the modulus to a binary representation of a password (PWDKEY) it's unlikely that you are choosing an appropriate exponent/modulus pair. And as I said earlier the modulus must be a relatively large number, usually chosen to be 1024, 2048 or 4096 bits long.

Any simple recommendations for creating a Password Salt and Hashing it?

wondering if anyone has some quick links to code snippets to generate a random salt (that's not easy too easy to guess) and then hashing some plain text password with the generated hash.
Suggestions or links, please?
.NET code, please.
The salt can be know. Why would you want the salt "not easy to guess"? It just has to be unique so that if two people share the same password the salt applied to the password ensures that they don't end up with the same hash value and to reduce the effectiveness of Rainbow attacks (where a reverse Hash dictionary is used to see the possible plain text value(s) that can produce a particular hash value)
From a code snippet on MSDN:
private static string CreateSalt(int size)
{
// Generate a cryptographic random number using the cryptographic
// service provider
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number
return Convert.ToBase64String(buff);
}
You can then append or prepend this on to the plain text password, then hash it.

How can I unhash a hash using C#?

Can someone reverse this handy hash code I'm using?
using System.Security.Cryptography;
public static string EncodePasswordToBase64(string password)
{ byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
return Convert.ToBase64String(inArray);
}
Everything I end up doing fails horribly :(.
No, you can't reverse a hash. The typical process is to compare other input to the hash you have, to check if they are the same.
Like (pseudo):
initial = Hash(password);
possible = Hash("test");
if( initial == possible ){
// we infer that password = "test"
}
But note that SHA1, SHA0, and MD5 should no longer be used; (due to various degrees of breaking in each). You should use SHA-2
The only real way of "unhashing" is using a rainbow table, which is a big table of hashes computed for all possible inputs. You look up the hash and get what was probably the original input.
http://en.wikipedia.org/wiki/Rainbow_table
You cannot un-hash SHA1, MD5, or any other one-way hash method unfortunately. Though it is possible to undo BASE-64.
SHA is an NSA acronym for "Secure Hash Algorithm".
Secure Hashes are hard to reverse by definition -- otherwise they would not be Secure.
You need to use a reversible hash function if you want to be able to easily compute sources that will generate the same hash (and even then you might not get the original source due to hash collisions where more than one source input can result in the same hash output).

Categories

Resources