Whats the standard code to generate HMAC SHA256 with key using C# - c#

I'd like to know if there is a standard code to generate a SHA256 hash using a key. I've come across several types of code, however, they don't generate the same output.
Code found at JokeCamp
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
Here's another one that I found
private static string ComputeHash(string apiKey, string message)
{
var key = Encoding.UTF8.GetBytes(apiKey);
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
The code generated by both of these are different to what is generated by http://www.freeformatter.com/hmac-generator.html#ad-output
I'll be using the SHA256 for one of our external API's where consumers would hash the data and send it to us. So we just want to make sure we use a standard approach so that they send us the correct hash. Also, I would like to know if there are any well-known nugets for this. I've also tried to find a solution with Bouncy Castle, however, I couldn't find one that uses a key to hash.

The difference is because of the character encodings (ASCII vs UTF-8 in your examples). Note that the hashing algorithm takes an array of bytes, and you do the conversion from a string to that byte-array beforehand.
Your question "whats the standard code" probably hasnt an answer, id say that if you expect the input to contain content from just the ASCII character-space, go for that, if not go for UTF-8. Either way - communicate it to your users
If you want to look at it from a usability perspective and make it the optimal for your users - go for both. Hash the content both ways and check agains the users incoming hash, but it all depends on your evaluation on clock-cycles vs security vs usability (you can have two)

They are almost equivalent.
The difference is how the encoding for the string is established.
In the first portion of code it assumes ASCII, whereas in the second portion it assumes UTF-8. It is possible that the string used another encoding which is none of those.
But regardless of that, the idea is to understand what is the goal of this operation. The truly relevant things in this context are:
Given equal input, output should be the same
There should be no way to retrieve the plaintext only by knowing the output (within a reasonable amount of time)
After hashing, you no longer require the original input in plaintext.
A secure cryptographic hashing function (meaning not older functions like MD5) achieves that.
Then, if your data store where hashes are stored is compromised, the attacker would only have a hash which cannot be used to retrieved the original plaintext. This is why hashing is used rather than encryption, encryption is a reversible operation (through decryption).
Then, within the system, if you've made the decision to use one encoding, you need to keep that decision consistent across all components in your system so they can interoperate.

Related

How to decrypt password in Meteor

is possible decrypt this type of password generated by Meteor application.
My idea is to use the same credentials (email and password) for my application in C #
As noted in other answers, you cannot decrypt the passwords, but you can very well use the Meteor database to authenticate in a different system.
This is how to do it:
In your other system, first find libraries that provide SHA256 and bcrypt implementations.
Then take the password as entered by the user, and first compute a SHA256 digest hash from it.
Then feed this hash string to bcrypt using number of rounds = 10 (This is the Meteor default).
Now compare the result from bcrypt with the services.password.bcrypt from the MongoDB database of Meteor. If they match, the user provided the correct password.
For reference, the Meteor implementation is here. It is quite simple and well commented.
The very purpose of hashing and encrypting your password is to make decrypting them unpractical.
However, you can reuse the bcrypt(hash(password)) from your meteor app and check against it in another application, provided you use the same scheme.
Is that a bcrypt hash? It depends on the size of the key as Blowfish as a variable sized key. If it's 32 bits. Sure, you could do it with some serious computing power and a few hours. It it is a 128bit key, you'd be long long dead (and so would the universe as we know it) before it every finishes brute forcing. Blowfish does have a minor vulnerability for weak keys though. I would rethink your implementation.
I encountered a similar use case where I was writing a C# application that would validate users created through a Meteor.js application. The code I got to work was this (using System.Security.Cryptography and BCrypt.Net-Next):
string sha256_hash(string value) {
StringBuilder stringBuilder = new StringBuilder();
using (SHA256 hash = SHA256.Create()) {
Encoding enc = Encoding.UTF8;
Byte[] resultingHash = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in resultingHash) {
stringBuilder.Append(b.ToString("x2"));
}
}
return stringBuilder.ToString();
}
// First compute SHA256 hash
string sha256hash = sha256_hash("my_password");
// Let BCrypt.Net rehash and check if it matches Meteor's hash
if (BCrypt.Net.BCrypt.Verify(sha256hash, dbPassword) == true) {
Console.WriteLine("Valid!");
}

Encryption and decryption ASP.NET [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I've been searching all over google just for a simple encryption and decryption method to store passwords. I'm not looking for a very complex encryption so I guess that's what is making it hard to find.
Does anyone have any simple encryption and decryption methods they could share with me?
You should hash your passwords using SHA256 for example. To check password validity, you hash the password received from the user and compare it with the hash stored in your database.
That said, you should ensure passwords are sent over SSL or they could be captured. If your own OS is not secured, the passwords could be captured in clear text as they arrive.
You would be better off using Windows Integrated Authentication when your web site is on the Intranet. For the Internet, OAuth might prove to be a better option.
Thanks to #philsoady for pointing out https://security.stackexchange.com/questions/35250/hmacsha512-versus-rfc2898derivebytes-for-password-hash for further reading.
As oscar132 explained in a comment, you shouldn't try and reinvent membership.
ASP.NET has a really good membership provider as a default option that requires not that much configuration. It has everything you need for good password management: User management, password resets, integrated web controls,...
It also does not do the terribly unsafe method of encryption, but instead hashes the passwords using the already recommended SHA256 method, with the option to use custom providers for enhanced cryptoalgorithms like PBKDF2 or bcrypt.
And even if your project already is underway, it's not that hard to add support for it. Visual Studio has default support for upgrading a asp.net website to an asp.net web forms application that implements membership.
Why you should use hashing rather than encryption:
If you use encryption, then you will need to have a key. This key can be taken and used to decrypt your passwords. Most likely, people within your organization will have access to this key. This means there is potential for everyone to know your users' passwords.
What does Hashing do differently?
Hashing is designed to be a one way linear transform. Therefore, you cannot go backwards and get the actual password. A simple hashing algorithm can be demonstrated in the following manner: use the remainder of dividing a password by 6. Lets say that your password is 10. You will store 4 in the database, as 10/6 has a remainder of 4. If you see 4 in the database, you cannot go backwards and figure out that you had 10, because it could also have been 4, or 16 (or infinitely many others). However, by passing in 10 you can verify that this is the same as the 4 stored in the database. You may notice an inherent flaw here. If you use 16 as your password it will still match in the database. This is known as a collision.
It is recommended that you use a hashing algorithm larger than SHA128 (output of 128 bits) because it is computationally infeasible to search until you find a collision. SHA algorithms are designed for speed, so these should still be fast enough for you (you said it was light weight). As an addition, some people generate sets of known popular passwords and their hashes (more commonly referred to as rainbow tables) which are used to quickly cross-reference against stored values.
For more security, creating a unique value (commonly referred to as salt) for each user which you should append to the beginning or end of your password before you hash. For example, the salt value is salt and the password is password, so we would hash saltpassword and store the result. Then when the user logs in again, we would compare the generated hash against the stored value. The reason this is better is in the scenario where two users have the same password, they will have two different unique hashes.
A small code sample:
using System.Security.Cryptography;
private string HashPassword(string password, string salt)
{
string hashedString = CryptoConfig.CreateFromName("SHA256")
.ComputeHash(salt+password);
return hashedString;
}
Basically, using encryption means that passwords can be discovered. Using hashing means that you cannot feasibly found out what they are, just find a potential collision (unless you are really lucky).
Not a SO question really but incase others find this.
Some do and donts. Home grown sites can be lacking here.
Don't Store passwords, Store one-way hashes. Encode them if possible.
Don't Use HMacSHA* as the algorithm, USE BCRPT, SCRYPT or RFC2898DerivedBytes(PBKDF2) for PASSWORDS. SHA is too fast and not suitable for password hashing.
Use a SALT
Prefer standard well tested and accepted tools eg in your environment ASP.Net Identity
Always use SSL when requesting a users password
If you Must (are you really sure) Encrypt and Decrypt have a machine Key / decryption key policy. The encryption is only as good as the key's safety.
If serious application consider using SCyrpt for c#
The bare minimum in standard c# to encode a password should be something like
the following using Rfc2898.
a) Store the encoded password and random SALT in you database.
b) Use a cost that takes at least 250 msecs.
c) compare the user provided password with stored SALT to the same routine and compare hashes.
private string PasswordEncode(string password, byte[] salt ) {
var deriver2898 = new Rfc2898DeriveBytes(password, salt,64000); // approx 300msecs
byte[] hash = deriver2898.GetBytes(20); //
// return hash;
// If you dont like storing bytes, use a string
return Convert.ToBase64String(hash);
}
// himalayan pink rock salt... the best kind
public byte[] GenerateSalt(int size = 64) {
using (var crypto = new RNGCryptoServiceProvider()) {
var bytes = new byte[size];
crypto.GetBytes(bytes); //get a bucket of very random bytes
return bytes;
}
}
if you at this stage are still convinced you need to Encrypt then use one of the symmetric algorithms from Microsoft. EG AesManaged
/// <summary>
/// Encrypt using preferred provider.
/// </summary>
/// <typeparam name="T">AesManaged,TripleDESCryptoServiceProvider,RijndaelManaged</typeparam>
/// <param name="value">Value to be encrypted</param>
/// <param name="decryptionKey">secret key .. see machine key descryptionKey</param>
/// <param name="salt">salt for process</param>
/// <returns></returns>
public string Encrypt<T>(string value, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream()) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write)) {
using (var writer = new StreamWriter(stream, Encoding.Unicode)) {
writer.Write(value);
}
}
// before finished with the buffer return, now as the stream is now closed
return Convert.ToBase64String(buffer.ToArray());
}
}
public string Decrypt<T>(string text, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
// could catch errors here, and return a null string. ?
// "CryptographicException: Padding is invalid and cannot be removed"
// can occur if there is a coding problem , such as invalid key or salt passed to this routine.
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateDecryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream(Convert.FromBase64String(text))) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read)) {
using (var reader = new StreamReader(stream, Encoding.Unicode)) {
return reader.ReadToEnd(); // error here implies wrong keys supplied , and code or environment problem.. NASTY issue
}
}
}
}
public DeriveBytes GenerateKey(string salt, string decryptionKey) {
// generate the key from the shared secret and the salt
var saltAsByteArray = salt.UTF8StringToByteArray();
var key = new Rfc2898DeriveBytes(decryptionKey, saltAsByteArray);
return key;
}
Sample calls: of encrypt and decrypt. Plus consider,how to get machine key and use as key here
Encrypt<AesManaged>(password, salt, decryptionKey);
Decrypt<AesManaged>(encryptedPassword, salt, decryptionKey);

Translate C# code to Ruby Code

I am trying to connect my system to a banks payment system. The problem is, their documentation was mostly not correct, if it wasn't a complete disaster.
In the documentation of 3D secure system, the bank asks me to fill out a html form and submit it to their system. The form should include some data AND a SHA1 hash of the data with the data. I tried many times but the bank's system returned "Hash not correct" error all the time.
After some inspection on their example C# code, I found a function they used to get hash results. The problem is function was doing some other stuff to the data rather than just hashing them. And bigger problem is I cannot find out what this piece of code is doing to the string that hashed.
public static string CreateHash(string notHashedStr)
{
SHA1 sha1 = new SHA1CryptoServiceProvider();
byte[] notHashedBytes = System.Text.Encoding.ASCII.GetBytes(notHashedStr);
byte[] hashedByte = sha1.ComputeHash(notHashedBytes);
string hashedStr = System.Convert.ToBase64String(hashedByte);
return hashedStr;
}
I have nearly no experience on .Net framework and also I am on a mac, so I cannot test the code easily, and MSDN is definitely not for me(I am a Ruby developer most of the time, and I know enough C). If anyone can explain what these functions do to the string to be hashed, i'll be very glad.
It's very simple.
Get the ASCII encoded bytes from notHashedStr.
Create a SHA1 hash from that bytes
Convert that hash in a Base64 encoded string.
return that Base64-SHA1-ASCII-String.
I never did any ruby, but it must look a bit like this.
require 'digest/sha1'
returnValue = Digest::SHA1.base64digest 'notHashedStr'

Reversing a md5 hash algorithm in C# [duplicate]

This question already exists:
Closed 11 years ago.
Possible Duplicate:
Reversing an MD5 Hash
Given this method in c#
public string CalculateFileHash(string filePaths) {
var csp = new MD5CryptoServiceProvider();
var pathBytes = csp.ComputeHash(Encoding.UTF8.GetBytes(filePaths));
return BitConverter.ToUInt64(pathBytes, 0).ToString();
}
how would one reverse this process with a "DecodeFileHash" method?
var fileQuery = "fileone.css,filetwo.css,file3.css";
var hashedQuery = CalculateFileHash(fileQuery); // e.g. "23948759234"
var decodedQuery = DecodeFileHash(hashedQuery); // "fileone.css,filetwo.css,file3.css"
where decodedQuery == fileQuery in the end.
Is this even possible? If it isn't possible, would there by any way to generate a hash that I could easily decode?
Edit: So just to be clear, I just want to compress the variable "fileQuery" and decompress fileQuery to determine what it originally was. Any suggestions for solving that problem since hashing/decoding is out?
Edit Again: just doing a base64 encode/decode sounds like the optimal solution then.
public string EncodeTo64(string toEncode) {
var toEncodeAsBytes = Encoding.ASCII.GetBytes(toEncode);
var returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
public string DecodeFrom64(string encodedData) {
var encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
var returnValue = Encoding.ASCII.GetString(encodedDataAsBytes);
return returnValue;
}
Impossible. By definition and design hashes cannot be reverted to plain text or their original input.
It sounds like you are actually trying to compress the files. If that is the case, here is a simple method to do so using GZip:
public static byte[] Compress( byte[] data )
{
var output = new MemoryStream();
using ( var gzip = new GZipStream( output, CompressionMode.Compress, true ) )
{
gzip.Write( data, 0, data.Length );
gzip.Close();
}
return output.ToArray();
}
A hash is derived from the original information, but it does not contain the original information. If you want a shorter value that hides the original information, but can be resolved to the original value your options are fairly limited:
Compress the original information. If you need a string, then your original information would have to be fairly large in order for the compressed, base-64-encoded version to not be even bigger than the original data.
Encrypt the original information - this is more secure than just compressing it, and can be combined with compression, but it's also probably going to be larger than the original information.
Store the original information somewhere and return a lookup key.
If you want to be able to get the data back, you want compression, not hashing.
What you want to do is Encrypt and Decrypt....
Not Hash and Unhash which, as #Thomas pointed out, is impossible.
Hashes are typically defeated using rainbow tables or some other data set which includes something which produces the same hash... not guaranteed to be the input value, just some value which produces the same output in the hashing algorithm.
Jeff Atwood has some good code for understanding encryption here:
http://www.codeproject.com/KB/security/SimpleEncryption.aspx
If that's useful to you
A cryptographic hash is by definition not reversible with typical amounts of computation power. It's usually not even possible to find any input which has the same hash as your original input.
Getting back the original input is mathematically impossible if there are more than 2^n different inputs. With n being the bitlength of the hash(128 for md5). Look up the pidgeonhole principle.
A hash is no lossless compression function.
A cryptographic hash, like MD5, is designed to be a one-way function, that is, it is computationally infeasable to derive the source data from which a given hash was computed. MD5, though, hasn't considered to be secure for some time, due to weaknesses that have been discovered:
Wikipedia on MD5 Security
MD5 Considered Harmful
Another weakness in MD5 is that due to its relative small size, large rainbow tables have been published that let you look up a given MD5 hash to get a source input that will collide with the specified hash value.

How would you generate repeateable encryption key?

I am looking to encrypt data. I want to generate encryption keys based on a password, and some moving value, like time. The goal is to have the key change, but have anyone that knows the password be able to decrypt. This is happening in C#. I am using the following code to hash the password.
private static string GetPasswordHash(string password)
{
TimeSpan span = (DateTime.UtcNow - new DateTime(1900, 1, 1));
string result = Convert.ToInt32(span.TotalHours).ToString();
result += password;
result += Convert.ToInt32(span.TotalDays).ToString();
result = Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.ASCII.GetBytes(result)));
return result;
}
I then use that hash, plus a salt to generate a key.
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(GetPasswordHash(password), salt);
rdb.IterationCount = 1000;
RijndaelManaged rm = new RijndaelManaged();
rm.KeySize = 256;
rm.Key = rdb.GetBytes(32);
rm.IV = rdb.GetBytes(16);
There seem to be issues with the way I am doing this. Some of the computers are in different timezones, or if the hour ticks as I send the data, or if the machines times are slightly off. Are there better suggestions?
The standard strategy is to just send the value (time, etc.) just be sent with the encryption key. Since the value you are using is public knowledge, it is fine if whoever first creates the password provides the "moving value" publicly. See Salt. What you are doing is not a new technique. You also seem to be using Key Strengthening.
You might just send the changing part (unencrypted) along with the encrypted data, so that anyone who knows the secret password can easily reconstruct the password used for encryption. Since the changing part is relatively easy to guess, it wouldn't make it much less secure.
You could find a scheme that generates the same moving value over a window of time, centered on the current time. Thus, if you choose a window of 12 hours, all computers 6 hours behind and 6 hours ahead of yours would generate the same encryption key.
Are you worried that a file with the same data encrypted with the same password looks the same?
You could use set the initialisation vector with the current time, and encrypt using your password.
To decrypt, you use the same IV value (so this has to be stored unencrypted with your file somewhere).
Password based key derivation is already implemented in .net. While I can't see anything wrong with your function GetPasswordHash() its always worth using library functions in crypto as they'll likely be better tested and small errors can completely destroy the security of a system. Here're two links, there are probably others too:
rfc2898derivebytes
passwordderivebytes

Categories

Resources