Iterative / Additive MD5 - c#

I need to generate a checksum over a dictionary. Keys and Values.
Is there any simple way to accomplish this in an iterative way.
foreach(var item in dic.Keys)
checksum += checksum(dic[item]) + checksum(item);
In this case, keys and values could be converted to strings, concatinated and then a single checksum applied over these but is there a better way?
Ideally MD5 but other options could work. Using this to validate data that is passed over a couple of storage methods. The checksum is then encrypted along with some other information (using AES) so I am not horribly worried about an ideal, unbreakable checksum.

Generating a signature is pretty much the same process all over: create a MD5 hash object, then you digest all the bytes of interest, then you extract the hash value. The important thing is that you and the verifier agree on the bytes to hash and on the order they are hashed.
In C# you can achieve this by calling HashAlgorithm.TransformBlock repeatedly, and then finally calling HashAlgorithm.TransformFinalBlock. This is automated by using a CryptoStream with a HashTransform (MD5 implements ICryptoTransform) and then simply writing your dictionary into the crypto stream.
As aside note, countless protocols and crypto schemes that digest a hash and encrypt it were humiliated in the wild. I would suggest taking the beaten path and use well established industry standards::
Use a HMAC, see HMACMD5
Use an RSA signature (ie. private key encryption of an MD5 hash), and save your self from all key provisioning and master secret exchange problems, see RSACryptoServiceProvider.SignHash

Answered my own question I think....
GetHashCode() on each item. Add them in an unchecked {} environment. Too simple.

You should not be writing any new code relying on MD5. It's deprecated, and for some extremely solid reasons. You should look at SHA-256, or at the very least SHA-1, instead
And you should take Remus' advice. Cryptography + hashes = digital signatures. Pull something down off a shelf (just not XML-Security, please!), learn it, use it, and get on to other interesting parts of your project.

Related

What does CreateSignature(HashAlgorithm) achieve?

I am working with some old code and I don't understand what has been done when creating a signed hash. The authors used this implementation:
AsymmetricSignatureFormatter.CreateSignature(HashAlgorithm)
All the examples I can find, and all the Microsoft documentation, use the other implementation:
AsymmetricSignatureFormatter.CreateSignature(byte[]HashedDataValue)
I understand that the second approach is signing a hash of some user data. At the receiver, we can re-hash the received plain text and compare it with this sent signed version to confirm it hasn't been changed.
But what is the first approach trying to do? No signed data seems to be sent, only a signed version of 'the agorithm', but what actually gets signed? Does it sign the Hash.hash byte array? But if so, there is no plain text byte array at the receiver to re-hash and check the sent hash against.
I suspect I have some fundamental misunderstanding of the purpose of this implementation.
It turns out that to use this form:
AsymmetricSignatureFormatter.CreateSignature(HashAlgorithm)
you need to have done some pre-work with the HashAlgorithm object. The HashAlgorithm object internally stores the hash of the last thing it 'hashed'.
Hence, if alg is the HashAlgorithm and userData is a byte array then
alg.ComputeHash(userData)
will store the hash within the alg object. Now we can sign the hash of userData using this form of the method:
AsymmetricSignatureFormatter.CreateSignature(HashAlgorithm)

Asp.net C# Encryption/Decryption on Client and server Side

Sir,
I have the jquery solution to encryption on the client side but it create "MD5" only.
I want Salted Md5 Encryption on the Clientside
and Decrypt it at the Server Side in Asp.net 4.0 and C#
My Code for encryption are as follows:
<script type="text/javascript">
function chn() {
var a = document.getElementById('txt1');
var b = document.getElementById('txt2');
var c = a.value; var d = $.md5(c);
b.value = (d);
}
</script>
I want that encryption must be change on every attempt..
Example : first time encryption of abc is xyz
and again if I will try with that name "Abc" then it should create another Encryption
and check on server Side.
Please Help me out
MD5 is a hash, not an encryption mechanism. Hashes are by their very nature lossy, and multiple inputs can (and by virtue of the pigeonhole principle absolutely will) produce the same outputs.
Running MD5 works like counting the number of vowels in a word. If I tell you that a word has 4 vowels in it, and ask you to tell me what the original word was, you simply don't have enough information to give me the the correct answer. You may be able to find some word that has 4 vowels in it, but you won't know whether the word you found was my word. Maybe it is, maybe it isn't. It's mathematically impossible for you to tell.
MD5 works the same way. You're throwing away tons of information, possible gigabytes or terabytes of information, and producing instead a single 16-byte summary.
It is, by intention, an inherently one-way process.
MD5 cant be decrypted. It is a one way hash. Beside I find that anything that could be decrypted on the other end is insecure, in the case it is intercepted. Always design and code to ensure that you can validate a salt and not decrypt it :)

Initialization vector - DES/triple-des algorithm

In order to generate the encrypted data we would need to define a Key that should suffice generating the data. But in .net DESCryptoServiceProvider requires Key and Intialisation Vector to generate the encrypted data. In this regard, I would like to know the importance & the benefit gained by defining this initialisation vector field. Is this mandatory while encryption using DES algorithm.
Pls share your thoughts on the same.
Regards,
Balu
If a key is used to encrypt multiple items that happen to be the same (or start out the same) without an initialization vector, you'll get the same ciphertext output, which is a pretty big problem.
Using a unique initialization vector for each item that's encrypted solves that problem.
See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29 for a bit more detail.

Byte encryption ( DES-CBC zero pad )

Currently writing my own AMF TcpSocketServer. Everything works good so far i can send and recieve objects and i use some serialization/deserialization code. Now i started working on the encryption code and i am not so familiar with this stuff.
I work with bytes , is DES-CBC a good
way to encrypt this stuff? Or are
there other more performant/secure
ways to send my data? Note that
performance is a must :).
When i call: ReadAmf3Object with the decrypter specified i get an: InvalidOperationException thrown by my ReadAmf3Object function when i read out the first byte the Amf3TypeCode isn't specified ( they range from 0 to 16 i believe (Bool, String, Int, DateTime, etc) ). I got Typecodes varying from 97 to 254? Anyone knows whats going wrong? I think it has something to do with the encryption part. Since the deserializer works fine w/o the encryption. I am using the right padding/mode/key?
I used: http://code.google.com/p/as3crypto/ as as3 encryption/decryption library. And i wrote an Async tcp server with some abuse of the threadpool ;)
Anyway here some code:
C# crypter initalization code
System.Security.Cryptography.DESCryptoServiceProvider crypter = new DESCryptoServiceProvider();
crypter.Padding = PaddingMode.Zeros;
crypter.Mode = CipherMode.CBC;
crypter.Key = Encoding.ASCII.GetBytes("TESTTEST");
AS3
private static var _KEY:ByteArray = Hex.toArray(Hex.fromString("TESTTEST"));
private static var _TYPE:String = "des-cbc";
public static function encrypt(array:ByteArray):ByteArray
{
var pad:IPad = new NullPad;
var mode:ICipher = Crypto.getCipher(_TYPE, _KEY, pad);
pad.setBlockSize(mode.getBlockSize());
mode.encrypt(array);
return array;
}
public static function decrypt(array:ByteArray):ByteArray
{
var pad:IPad = new NullPad;
var mode:ICipher = Crypto.getCipher(_TYPE, _KEY, pad);
pad.setBlockSize(mode.getBlockSize());
mode.decrypt(array);
return array;
}
C# read/unserialize/decrypt code
public override object Read(int length)
{
object d;
using (MemoryStream stream = new MemoryStream())
{
stream.Write(this._readBuffer, 0, length);
stream.Position = 0;
if (this.Decrypter != null)
{
using (CryptoStream c = new CryptoStream(stream, this.Decrypter, CryptoStreamMode.Read))
using (AmfReader reader = new AmfReader(c))
{
d = reader.ReadAmf3Object();
}
}
else
{
using (AmfReader reader = new AmfReader(stream))
{
d = reader.ReadAmf3Object();
}
}
}
return d;
}
Define "secure."
DES is more secure than plain text, but due to it's 56-bit keysize, it's not usually used anymore. If you're protecting data against your family, or the casual ease dropper this might be okay.
If people are using DES these days, it's Triple DES which essentially runs DES, three times, on each datablock.
Now a days the symmetric encryption algorithm (which DES is) of choice is AES, which is like the spiritual successor to DES.
AES with a sufficiently large key of 256 (really 512 or higher now a days) is cryptographically secure for most applications.
The few caveats of AES are:
It's still restricted to US Export controls
The NSA can decrypt your information if they want to (yes
this is tin hat thinking)
Regarding your error, first try switching to AES, and see if you still get a problem.
Regarding AES:
Key selection is important, as well as key protection.
Key Selection
If you want to "password" protect your data, using AES, then you need to convert your password into an AES key. This is a common pitfall for many amateur computer security developers. Adobe essentially destroyed all the protection of AES in their PDF's by using an MD5 hash of the users password as the key. Needless to say, you're smarter than all of Adobe's engineers combined, so you won't make that mistake.
The proper way to generate a key from a password is using RFC2898 aka PBKD2 (password based key derivation function). .NET handily has a method that does this: Rfc2898DeriveBytes(). Essentially what this does is cryptographically securely hashes your password, with a supplied salt (more on this in a bit), a number of times, supplied by the user. This provides several layers to protect against brute force attacks against your password (assuming your key is large enough to prevent brute force attacks against it!)
Each iteration of PBKD2 takes a minuscule amount of time to run. The more interation you run (i think the recommend number is > 1000), the more computer time it takes. This time is still less than a human would recognize, but in computer time it's like a century. Thus without knowing the exact iteration count, it makes it a very lengthy process to brute force attack a password.
Salt. Rather than taking a direct hash of your password, a salt adds extra information to your input password, creating a unique hash. This prevents rainbow table attacks, assuming you keep your salt value protected.
Key Storage
The other side to cryptography is key storage. If you are password protecting your data, then you need to securely store the password. The easiest way is to use the OS's built in security. On Windows thats using DPAPI in the registry, and Unix, filepermissions.
AES as a Session Key
If you are looking to securely transmit data across a nonsecure channel (or even adding your own extra security ontop of SSL), you may want to looking at using AES as a session encryption.
Essentially this is two scheme encryption system that works as follows:
You generate a public/private key pair using your favorite assymetric encryption (RSA!) for your server.
Each trusted client is given the public key.
During a session, the client generates a new random AES key of 256 bit or higher.
This AES Session key is encrypted using the public RSA key.
This encrypted data containing the AES session key is sent to the server.
The server decrypts the data using it's private RSA key, and keeps the AES Session key.
During the rest of the session, all data is encrypted with the session AES key.
At the end of the session, the AES key is discarded.
While this does require more handshaking, this gives you the added protection of limiting exposure. Since the AES key is only good for a session, if it's discovered, the damage is only limited to a single session.
DES is a block cipher, so in general it makes working with bytes more tedious. AS3 is a stream cipher used primarily with GSM phone systems, because it's a stream cipher it'll work nicely with bytes.
Personally, I would use RC4 if you really need to use a stream cipher; it's very quick. There's a good implementation here http://dotnet-snippets.com/dns/rc4-encryption-SID577.aspx
There are some very important caveats you should be aware of when using stream ciphers:
1) NEVER re-use an encryption key with a stream cipher.
2) Because you're encrypting one byte at a time, it's hard to determine if the data has been tampered with, so you'll need add a digital signature or HMAC to the stream.

What format is the output of HashPasswordForStoringInConfigFile () and how to store it the best?

I'm using this function to generate a hash for a password and then store it in the database (SQL Server).
The code looks like this:
byte[] saltBytes = new byte[16];
new RNGCryptoServiceProvider ().GetBytes (saltBytes);
string salt = Convert.ToBase64String (saltBytes);
string saltedPasswordHash =
FormsAuthentication.HashPasswordForStoringInConfigFile (password + salt, FormsAuthPasswordFormat.SHA1.ToString ());
Now the question: in what format is the output of HashPasswordForStoringInConfigFile () - do I store it as char(length) or nchar(length)?
Or is there any other preferred way to store the hash, maybe not as a string?
Any input and semi-relevant comments are greatly appreciated.
SQL Server supports binary columns (binary(len), and varbinary(len)) designed to store binary data. You might want to consider using them. In that case, you could use classes such as System.Security.Cryptography.SHA512Managed directly, instead of HashPasswordForStoringInConfigFile
Since you are using C#, it might be worth considering using a BCrypt hashing solution. It's designed on the BCrypt encryption algorithm by the guys writing OpenBSD and is a very strong algorithm. Best part is that you don't have to worry about salts (but they are there) and you can make salt generation hard as time goes on.
BCrypt.net - Strong Password Hashing for .NET and Mono

Categories

Resources