1

Here's a decryption method I'm using inside Unity3d. It works perfectly when I call it with 128 byte sized portions but fails when it gets say 256 bytes at a time. Should I call it in blocksize-chunks only?

After further analysis, I thought that the PKCS7 padding didn't get removed with said accelerated speed. However it's not the same bytes so the padding-removal is ruled out. However I don't know where those 24 additional bytes come from. For one thing, you can see that there's nothing missing in the decrypted text. So where the hell do they come from? The debug view of the decrypted array at the bottom has this content when a big chunk is decoded:

1------3895-------/home/max/PycharmProjects/RealityShell/Backend\r\n\xx2\xx2\xx2\xx2\xx2\xx2\xx2 \xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\"\xx2neL\xx2\xx2\xx2\xx2\xx2{2------3895-------/home/max /PycharmProjects/RealityShell/Backend\r\n\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2tC; \xx2VCY3\xx2Z?r\xx2\xx2\xx2f3------3895-------/home/max/PycharmProjects/RealityShell/Backend\r\n\xx2 \xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2\xx2neWc\xx2\xx2\xx2\xx2+ \xx2\xx2L;M4------3895-------/home/max/PycharmProjects/RealityShell/Backend\r\n\

So my test content are the lines "1------3895-------/home/max/PycharmProjects/RealityShell/Backend\r\n\" etc while the \xx2 bytes are inexplicable and constitute the problem.

public static string DecryptStringFromBytes_Aes(string serversays, string Key)
{

Debug.Log ("Decrypt incoming length:" + serversays.Length.ToString ());
byte[] cipherText = Convert.FromBase64String(serversays);
byte[] keystring = Encoding.UTF8.GetBytes(Key);

using (Aes aesAlg = Aes.Create())
{
    aesAlg.Key = keystring;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.BlockSize = 128;
    aesAlg.Padding = PaddingMode.PKCS7;

    byte[] cipherText_only = new byte[cipherText.Length - aesAlg.IV.Length];
    byte[] IV = new byte[aesAlg.IV.Length];

    Array.Copy(cipherText, 0, IV, 0, aesAlg.IV.Length);
    Array.Copy(cipherText, aesAlg.IV.Length, cipherText_only, 0, cipherText_only.Length);

    aesAlg.IV = IV;

    using (MemoryStream ms = new MemoryStream())
    {
        using (ICryptoTransform decryptor = aesAlg.CreateDecryptor())
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
            {
                cs.Write(cipherText_only, 0, cipherText_only.Length);
                //cs.FlushFinalBlock();

                byte[] decrypted = ms.ToArray();
                string decr_serverSays = Encoding.UTF8.GetString (decrypted);
                Debug.Log (decr_serverSays + "..." + decr_serverSays.Length.ToString());
                return decr_serverSays;
            }
        }
    }
}
}

Here's the Python encrypt method:

def encrypt(self, key, raw):
    encoder = PKCS7Encoder()
    #mac = HMAC.new(raw, digestmod=SHA256)
    raw_pad = encoder.encode(raw)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv)
    encry_cipher = iv + cipher.encrypt(raw_pad)
    encry = base64.b64encode(encry_cipher)
    #print(len(encry), len(encry_cipher), len(raw_pad))
    return encry
  • 1
    *"but fails when it gets say 256 bytes at a time"* - How does it fail? Are there exceptions? Do you observe strange outputs? If so, what are those and what did you expect? – Artjom B. Jul 09 '17 at 21:14
  • There are no exceptions but the failure is the added bytes inbetween the returning cleartext which you can see in the debug view I posted, first blockquote, bytes which are not padding. As written, this happens only when it gets 256 bytes at a time. – Tshosh Harris Jul 09 '17 at 21:16

1 Answers1

0

Not exactly sure how to interpret that debug output, but there is a problem with your code: you're reading the entire MemoryStream before the CryptoStream has been flushed. The best thing you can do is move ms.ToArray() outside the inner usings:

using (MemoryStream ms = new MemoryStream())
{
    using (ICryptoTransform decryptor = aesAlg.CreateDecryptor())
    using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
    {
        cs.Write(cipherText_only, 0, cipherText_only.Length);
    }

    byte[] decrypted = ms.ToArray();
    string decr_serverSays = Encoding.UTF8.GetString(decrypted);
    Debug.Log (decr_serverSays + "..." + decr_serverSays.Length.ToString());
    return decr_serverSays;
}
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • Thanks already for that, will test this. On the debug output: my cleartext test content are the lines "1------3895-------/home/max/PycharmProjects/RealityShell/Backend\r\n\" etc while the \xx2 bytes are inexplicable and constitute the problem. – Tshosh Harris Jul 09 '17 at 21:30