Search code examples
c#pythonencryptionwindows-phone-8aes

Looking for equivalent windows phone c# code for python AES MODE_CBC encryption


I have encryption / decryption method in python written as

import base64
from Crypto.Cipher import AES


def get_encrypted_message(message):
    """Return encrypted message."""
    length = 16 - (len(message) % 16)
    message += chr(length) * length
    cipher = AES.new('abcdefghijklmnopqrstuvwxyz123456',
                     AES.MODE_CBC, 16 * '\x00')
    message = cipher.encrypt(message)
    return base64.b64encode(message)


def get_decrypted_message(message):
    """Return decrypted message."""
    if not message:
        return
    message = base64.b64decode(message)
    cipher = AES.new(
        'abcdefghijklmnopqrstuvwxyz123456', AES.MODE_CBC, 16 * '\x00')
    msg = cipher.decrypt(message)
    return msg.strip()


ENCRYPTED_MSG = get_encrypted_message('123')
print ENCRYPTED_MSG         # 5pRIk9MDE3z9caf/ayilIA==
print get_decrypted_message(ENCRYPTED_MSG)  # 123

I am now looking for equivalent Windows phone 8.1 C# AES algorithm encryption method. I am new to windows phone development and in my application i have to query data by passing encrypted data.

Please guide or help in writing this simple code. As I am finding it very difficult to get winphone 8.1 c# algo, I dont see any AES algo is available or not as it was available in 8.

Thanks!


Solution

  • WP 8.1 and WinRT

    public static string Encrypt2(string password, string plainText)
    {
        IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
        IBuffer plainBuffer = CryptographicBuffer.ConvertStringToBinary(plainText, BinaryStringEncoding.Utf8);
        IBuffer iv = WindowsRuntimeBuffer.Create(16);
    
        SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
        // create symmetric key from derived password key
        CryptographicKey symmKey = symProvider.CreateSymmetricKey(passwordBuffer);
    
        // encrypt data buffer using symmetric key and derived salt material
        IBuffer encryptedBuffer = CryptographicEngine.Encrypt(symmKey, plainBuffer, iv);
        string encryptedText = CryptographicBuffer.EncodeToBase64String(encryptedBuffer);
        return encryptedText;
    }
    
    public static string Decrypt2(string password, string encryptedText)
    {
        IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
        IBuffer encryptedBuffer = CryptographicBuffer.DecodeFromBase64String(encryptedText);
        IBuffer iv = WindowsRuntimeBuffer.Create(16);
    
        SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
        // create symmetric key from derived password material
        CryptographicKey symmKey = symProvider.CreateSymmetricKey(passwordBuffer);
    
        // encrypt data buffer using symmetric key and derived salt material
        IBuffer plainBuffer = CryptographicEngine.Decrypt(symmKey, encryptedBuffer, iv);
        string plainText = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, plainBuffer);
        return plainText;
    }
    

    EVERYTHING ELSE

    public static string Encrypt(string password, string plainText)
    {
        using (var aes = new AesManaged())
        {
            aes.Key = Encoding.UTF8.GetBytes(password);
            aes.IV = new byte[16];
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
    
            byte[] plainBuffer = Encoding.UTF8.GetBytes(plainText);
    
            using (MemoryStream input = new MemoryStream(plainBuffer))
            using (MemoryStream output = new MemoryStream())
            using (ICryptoTransform encryptor = aes.CreateEncryptor())
            using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
            {
                input.CopyTo(cs);
                cs.FlushFinalBlock();
                string encryptedText = Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
                return encryptedText;
            }
        }
    }
    
    public static string Decrypt(string password, string encryptedText)
    {
        using (var aes = new AesManaged())
        {
            aes.Key = Encoding.UTF8.GetBytes(password);
            aes.IV = new byte[16];
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
    
            byte[] encryptedBuffer = Convert.FromBase64String(encryptedText);
    
            using (MemoryStream input = new MemoryStream(encryptedBuffer))
            using (MemoryStream output = new MemoryStream())
            using (ICryptoTransform decryptor = aes.CreateDecryptor())
            using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
            {
                cs.CopyTo(output);
                string plainText = Encoding.UTF8.GetString(output.GetBuffer(), 0, (int)output.Length);
                return plainText;
            }
        }
    }
    

    Note that there is a small problem here: I'm using UTF8 for the encoding of both the password and the strPlainText, but python uses bytestring for everything, and bytestring is encoding agnostic (see What is a Python bytestring?).

    Example of use:

    string result = Encrypt("abcdefghijklmnopqrstuvwxyz123456", "123"); // 5pRIk9MDE3z9caf/ayilIA==
    string decrypted = Decrypt("abcdefghijklmnopqrstuvwxyz123456", result); // 123
    

    The method returns the same encrypted result as your example.

    A small problem of this piece of code is that the IV (the initialization vector) is initialized with an empty biffer (new byte[16] and 16 * '\x00' in Python). This is a "bad habit". Even using the CBC cyphermode is considered to be "bad".