3

I would like to encrypt and decrypt strings with a password. I use C# and WinRT (MetroStyle). Have somebody a class for encryption/decryption?

Michael
  • 727
  • 2
  • 10
  • 22
  • Okey, maybe you miss understand me I want just to know how do this in WinRT. It must not be very high secure. Just simple, but enough secure to store personal data in there – Michael Sep 09 '12 at 11:06

1 Answers1

11

The normal .Net System.Security.Cryptography namespace does not exist in Metro. You use the CryptographicEngine class in Windows.Security.Cryptography.Core namespace instead.

If the password is only being verified/authenticated, do not encrypt it. Instead, use the following:

using Windows.Security.Cryptography.Core;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;

...
// Use Password Based Key Derivation Function 2 (PBKDF2 or RFC2898)
KeyDerivationAlgorithmProvider pbkdf2 = 
    KeyDerivationAlgorithmProvider.OpenAlgorithm(
        KeyDerivationAlgorithmNames.Pbkdf2Sha256);

// Do not store passwords in strings if you can avoid them. The
// password may be retained in memory until it is garbage collected.
// Crashing the application and looking at the memory dump may 
// reveal it.
IBuffer passwordBuffer = 
     CryptographicBuffer.ConvertStringToBinary("password", 
         BinaryStringEncoding.Utf8);
CryptographicKey key = pbkdf2.CreateKey(passwordBuffer);

// Use random salt and 10,000 iterations. Store the salt along with 
// the derviedBytes (see below).
IBuffer salt = CryptographicBuffer.GenerateRandom(32);
KeyDerivationParameters parameters = 
    KeyDerivationParameters.BuildForPbkdf2(salt, 10000);

// Store the returned 32 bytes along with the salt for later verification
byte[] derviedBytes = 
    CryptographicEngine.DeriveKeyMaterial(key, parameters, 32).ToArray();

When a password is supplied run through the same process using the same salt and compare derivedBytes. Store the secret as you would an encryption key.

If the password will be used, such as to connect to another service:

// Use AES, CBC mode with PKCS#7 padding (good default choice)
SymmetricKeyAlgorithmProvider aesCbcPkcs7 = 
    SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);

// Create an AES 128-bit (16 byte) key
CryptographicKey key = 
    aesCbcPkcs7.CreateSymmetricKey(CryptographicBuffer.GenerateRandom(16));

// Creata a 16 byte initialization vector
IBuffer iv = CryptographicBuffer.GenerateRandom(aesCbcPkcs7.BlockLength);

// Encrypt the data
byte[] plainText = Encoding.UTF8.GetBytes("Hello, world!"); // Data to encrypt
byte[] cipherText = CryptographicEngine.Encrypt(
    key, plainText.AsBuffer(), iv).ToArray();

// Decrypt the data
string newPlainText = new string(
    Encoding.UTF8.GetChars(CryptographicEngine.Decrypt(
        key, cipherText.AsBuffer(), iv).ToArray()));

// newPlainText contains "Hello, world!"

As with any cryptography, make sure to protect your keys appropriately and follow best practise. The linked documentation also provides examples.

akton
  • 13,492
  • 3
  • 42
  • 45
  • @Michael I'm working on one write now. I'll update my answer in about 5 minutes when I'm sure it works. – akton Sep 09 '12 at 11:12
  • @Michael It is part of .Net 4.5 only (http://msdn.microsoft.com/en-us/library/hh598393). Are you using an older version of .Net? – akton Sep 09 '12 at 11:48
  • 1
    For understanding: If i want to check later if a password saved as cipherText is the password in the passwordbox, I also need the key and the iv? Or just the key? Where should I save key (?and iv?). Should the key and iv be predefined or random? – Michael Sep 09 '12 at 11:58
  • @Michael To check it, you will need both the key and the IV. However, if the only thing you are ever doing is checking the password, consider the CryptographicEngine.DeriveKeyMaterial method instead. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.cryptography.core.cryptographicengine.derivekeymaterial.aspx for help and an example. – akton Sep 09 '12 at 12:05
  • I would like to check if the password is correct and if it is I would encrypt some strings. So maybe you can give me the right input how to handle key, IV. (password) Thanks in advance! – Michael Sep 09 '12 at 14:22
  • Thanks! If I understand it correctly, the passwort is just used to activate the encrypt/decrypt service and not the actual key of the encryption/decryption. – Michael Sep 09 '12 at 15:15
  • @Michael That is correct. In the new example, the password is used to derive a secret which is used in subsequent password checks. – akton Sep 09 '12 at 15:16
  • But the derviedBytes are not the key for the second part? – Michael Sep 09 '12 at 15:47
  • Password checking has its own password and salt and encryption/decryption has its onw key and IV – Michael Sep 09 '12 at 15:48