SM18
SM18

Reputation: 718

AES Encryption between iOS and C#

I am using FBEncryptor Library for encryption and decryption. If I encrypt data from iOS, it will easily decrypt on C# server side. But while decrypting the first 10 characters from original data get corrupted.

Example :
Received data From C# : 0Nwr30kSkJxGCYiFg8TUrfW51587SUkS8lQ7Uno7gglxjVGW5gR4MA+isTknjXzK

Key uses for encryption : e64f9fa01f0418

Decrypted data from iOS : gZUUTabcdefghijklmnopqrstuvwxyz"}

Expected Decrypted data : {"Successeed" : "abcdefghijklmnopqrstuvwxyz"}

iOS side code:

encryptedios = "0Nwr30kSkJxGCYiFg8TUrfW51587SUkS8lQ7Uno7gglxjVGW5gR4MA+isTknjXzK"
let decryptedString = FBEncryptorAES.decryptBase64String(encryptedios , keyString: "e64f9fa01f0418")

C# code:

public RijndaelManaged GetRijndaelManaged(String secretKey)
    {
        var keyBytes = new byte[16];
        var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
        Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
        return new RijndaelManaged
        {
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7,
            KeySize = 128,
            BlockSize = 128,
            Key = keyBytes,
            IV = keyBytes
        };
    }

    public byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
    {
        return rijndaelManaged.CreateEncryptor()
            .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
    }

    public byte[] Decrypt(byte[] encryptedData, RijndaelManaged rijndaelManaged)
    {
        return rijndaelManaged.CreateDecryptor()
            .TransformFinalBlock(encryptedData, 0, encryptedData.Length);
    }

    /// <summary>
    /// Encrypts plaintext using AES 128bit key and a Chain Block Cipher and returns a base64 encoded string
    /// </summary>
    /// <param name="plainText">Plain text to encrypt</param>
    /// <param name="key">Secret key</param>
    /// <returns>Base64 encoded string</returns>
    public String Encrypt(String plainText, String key)
    {
        var plainBytes = Encoding.UTF8.GetBytes(plainText);
        return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
    }

    /// <summary>
    /// Decrypts a base64 encoded string using the given key (AES 128bit key and a Chain Block Cipher)
    /// </summary>
    /// <param name="encryptedText">Base64 Encoded String</param>
    /// <param name="key">Secret Key</param>
    /// <returns>Decrypted String</returns>
    public String Decrypt(String encryptedText, String key)
    {
        var encryptedBytes = Convert.FromBase64String(encryptedText);
        return Encoding.UTF8.GetString(Decrypt(encryptedBytes, GetRijndaelManaged(key)));
    }

Upvotes: 0

Views: 682

Answers (1)

Ebbe M. Pedersen
Ebbe M. Pedersen

Reputation: 7518

Your first block differs as you use different IV in the decrypt. In IOS decryptBase64String(..) don't take an IV as input, which triggers it to be initialized to all 0'es. In C# you initializes it to the same value as the key.

In general the IV need to be a random value generated at encryption time, and passed along with the encrypted data. Often it's prepended the encrypted data, so you easily can get it when you initializes your decryption library. Using all 0'es as IV is bad practice .. and the same goes for using the key as IV.

Upvotes: 1

Related Questions