Bad Data with Cryptography.RC2

257 Views Asked by At

There is a special working progress where we encrypt and decrypt an input. Suddenly, yesterday, there was an encrypted string we weren't able to decrypt.

It seems my cryptographic knowledge aren't good enough to solve this problem.

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Crypto
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class Crypto
{

    public static void Main()
    {
        //String NotWorking_dec = "鈦ꧪ㧘聯ꢮ玗硴廜᭮⸂濅�";

        String enc ="mIAU::__*?";
        //String dec = "砿첩뜞ꦽ嶾蝡泛ɝࠪ塤偏ꍨ";
        Console.WriteLine(decrypt(dec));
        //writeFile(encrypt(enc));
        Console.ReadLine();
    }
    private static string key = "ZlKMpRwoPLmNXEpCLxEa6g==";
    private static string iv = "U5ZB4W4bQqg=";

    private static ICryptoTransform enc;
    private static ICryptoTransform dec;

    static Crypto()
    {
        RC2 rc = System.Security.Cryptography.RC2.Create();
        enc = rc.CreateEncryptor(Convert.FromBase64String(key), Convert.FromBase64String(iv));
        dec = rc.CreateDecryptor(Convert.FromBase64String(key), Convert.FromBase64String(iv));
    }

    public static String encrypt(String value)
    {
        byte[] input = toBytes(value);
        return toString(enc.TransformFinalBlock(input, 0, input.Length));
    }

    public static String decrypt(String value)
    {
        byte[] input = toBytes(value);
        Console.WriteLine(input.Length);
        return toString(dec.TransformFinalBlock(input, 0, input.Length));

    }

    private static void writeFile(String value)
    {
        try
        {
            StreamWriter sw = new StreamWriter("output.tmp", true);
            sw.WriteLine(value);
            sw.Close();
        }
        catch (Exception ex) { }
    }

    private static byte[] toBytes(String value)
    {
        return Encoding.Unicode.GetBytes(value);
    }

    private static String toString(byte[] value)
    {
        return Encoding.Unicode.GetString(value);
    }
}
 }

This working progress works for months. You are able to test it with the input

mIAU::__*?

you get

砿첩뜞ꦽ嶾蝡泛ɝࠪ塤偏ꍨ

decrypt it and you get again

mIAU::__*?

But the encrypted String "鈦ꧪ㧘聯ꢮ玗硴廜᭮⸂濅�" throws errors: (Of course we used the same key and iv)

BAD DATA

   bei System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   bei System.Security.Cryptography.Utils._DecryptData(SafeKeyHandle hKey, Byte[] data, Int32 ib, Int32 cb, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode PaddingMode, Boolean fDone)
   bei System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   bei Crypto.Crypto.decrypt(String value) in c:\Users\Td\Documents\Visual Studio 2013\Projects\Crypto\Crypto\Program.cs:Zeile 56.
   bei Crypto.Crypto.Main() in c:\Users\Td\Documents\Visual Studio 2013\Projects\Crypto\Crypto\Program.cs:Zeile 23.
   bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   bei System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   bei System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
   bei System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
   bei System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
   bei System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
   bei System.Activator.CreateInstance(ActivationContext activationContext)
   bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
   bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   bei System.Threading.ThreadHelper.ThreadStart()
1

There are 1 best solutions below

1
On

You cannot simply convert random bytes to strings and back. Not all bytes are valid character encodings. You need to apply for instance base 64 encoding to your binary ciphertext if you require text. Otherwise you will loose data, depending on the value of the ciphertext. And the ciphertext will contain random byte values. So it may fail now and then, as you are currently experiencing.

Java silently converts unknown bytes to characters by default, for instance it will create a character if it cannot convert byte(s) to a character. This is why this particular string fails.

Besides that, Unicode contains a lot of characters that are not easily printable, and even characters that can be created using either two Unicode code points or a single one. So a Unicode string may have multiple possible encodings, so it is doubly unsuitable for conveying binary data.

All in all, text should not be directly used to convey binary data. The data needs to be encoded first.