Symmetric key encryption, also called secret key encryption, requires that the key used for encryption also be used for decryption. You can use a SymmetricKeyAlgorithmProvider object to specify a symmetric algorithm and create or import a key. You can use static methods on the CryptographicEngine class to encrypt and decrypt data by using the algorithm and key.
Under normal circumstances on top of the encryption key used, you would need to send vector values which is used as the initialization vector. However, for a simple scenario (e.g. you want to send a password value from the client to the server or vice-versa, and you don’t want to do a post with clear-text). You wouldn’t go through the trouble of carrying the IV buffer to the client side as well.
So here is a simple implementation that uses the AES encryption with ECB cipher mode and PKCS7 padding (PKCS #7 algorithms automatically pads the message to an appropriate length, so you don’t need to pad the cipher to a multiple of the block-size of the encryption algorithm you are using)
First step is to implement an MD5 hash generator which will be use to compute a hash from the encryption key that is being used.
private static IBuffer GetMD5Hash(string key) { // Convert the message string to binary data. IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); // Create a HashAlgorithmProvider object. HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); // Hash the message. IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg); // Verify that the hash length equals the length specified for the algorithm. if (buffHash.Length != objAlgProv.HashLength) { throw new Exception("There was an error creating the hash"); } return buffHash; }
Once the key material is ready to be used to generate the symmetric key, we can go on with the encryption.
/// <summary> /// Encrypt a string using dual encryption method. Returns an encrypted text. /// </summary> /// <param name="toEncrypt">String to be encrypted</param> /// <param name="key">Unique key for encryption/decryption</param>m> /// <returns>Returns encrypted string.</returns> public static string Encrypt(string toEncrypt, string key) { try { // Get the MD5 key hash (you can as well use the binary of the key string) var keyHash = GetMD5Hash(key); // Create a buffer that contains the encoded message to be encrypted. var toDecryptBuffer = CryptographicBuffer.ConvertStringToBinary(toEncrypt, BinaryStringEncoding.Utf8); // Open a symmetric algorithm provider for the specified algorithm. var aes = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7); // Create a symmetric key. var symetricKey = aes.CreateSymmetricKey(keyHash); // The input key must be securely shared between the sender of the cryptic message // and the recipient. The initialization vector must also be shared but does not // need to be shared in a secure manner. If the sender encodes a message string // to a buffer, the binary encoding method must also be shared with the recipient. var buffEncrypted = CryptographicEngine.Encrypt(symetricKey, toDecryptBuffer, null); // Convert the encrypted buffer to a string (for display). // We are using Base64 to convert bytes to string since you might get unmatched characters // in the encrypted buffer that we cannot convert to string with UTF8. var strEncrypted = CryptographicBuffer.EncodeToBase64String(buffEncrypted); return strEncrypted; } catch (Exception ex) { // MetroEventSource.Log.Error(ex.Message); return ""; } }
The decryption function is not any different in this case except for the fact that you would need to use Base64 conversion to convert the encrypted cipher to a buffer.
/// <summary> /// Decrypt a string using dual encryption method. Return a Decrypted clear string /// </summary> /// <param name="cipherString">Encrypted string</param> /// <param name="key">Unique key for encryption/decryption</param> /// <returns>Returns decrypted text.</returns> public static string Decrypt(string cipherString, string key) { try { // Get the MD5 key hash (you can as well use the binary of the key string) var keyHash = GetMD5Hash(key); // Create a buffer that contains the encoded message to be decrypted. IBuffer toDecryptBuffer = CryptographicBuffer.DecodeFromBase64String(cipherString); // Open a symmetric algorithm provider for the specified algorithm. SymmetricKeyAlgorithmProvider aes = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7); // Create a symmetric key. var symetricKey = aes.CreateSymmetricKey(keyHash); var buffDecrypted = CryptographicEngine.Decrypt(symetricKey, toDecryptBuffer, null); string strDecrypted = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, buffDecrypted); return strDecrypted; } catch (Exception ex) { // MetroEventSource.Log.Error(ex.Message); //throw; return ""; } }
And there it goes, a simple symmetric key encryption ready to be used in Windows Store Apps (aka Metro).
Happy coding everyone…
Pingback: Windows 8 Developer Links – 2012-10-04 | Dan Rigby
Pingback: Simple AES (Symmetric Key) Encryption in WinRT
worked like a wonder ! Thanks a lot ! 🙂
LikeLike
hehe 🙂 glad it worked out for you..
LikeLike
How can I encrypt StorageFiles ?
LikeLike
what is “string key” in encrypt and decrypt methods?
LikeLike
Great post.
LikeLike
çok güzel bir yazı teşekkürler 🙂
LikeLike
it’s awesome. Thanks your post, Can Bilgin.
LikeLike
Don’t ever use ECB. It is kind of the “don’t encrypt properly” mode: http://blog.codinghorror.com/why-isnt-my-encryption-encrypting/ . Some more background on the common encryption modes: https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb/22958889#22958889
LikeLike
Would I require an ECCN to submit the app on windows store in case I use this encryption method?
LikeLike
As far as I understood from the msdn documentation on this topic, if you are dealing with simple password or some sort of key encryption, you wouldn’t need ECCN. But it all seems in the gray area when it comes to encryption.
LikeLike
It’s extremely irresponsible of you to suggest people use ECB mode. It leaks information. People are going to use this example and will get burned by the fact that this is not safe, for anything.
A proper mode of operation should be used with a corresponding properly generated nonce and/or IV.
LikeLike
I agree ECB is the simplest of all where each block is encrypted separately but did you even read the post completely? I am specifically referring to the second paragraph… I am not suggesting this should be used for data encryption on sensitive info, just for simple use-cases. When you see a password encrypted over the wire with ECB, which pattern are you going to use to crack it or which type of info is going to be leaked… could you enlighten us?
LikeLike