从加密值转换时出错

时间:2012-11-23 06:47:34

标签: c# .net encryption cryptography

我有一个加密方法GetDecryptedSSN()。我通过以下测试测试了它的正确性。它工作正常

        //////////TEST 2//////////
        byte[] encryptedByteWithIBMEncoding2 = DecryptionServiceHelper.GetEncryptedSSN("123456789");
        string clearTextSSN2 = DecryptionServiceHelper.GetDecryptedSSN(encryptedByteWithIBMEncoding2);

但是当我转换为ASCII String然后返回时,它无法正常工作。转换逻辑有什么问题?

        //////////TEST 1////////// 
        //String  -- > ASCII Byte --> IBM Byte -- > encryptedByteWithIBMEncoding
        byte[] encryptedByteWithIBMEncoding = DecryptionServiceHelper.GetEncryptedSSN("123456789");

        //encryptedByteWithIBMEncoding -->  Encrypted Byte ASCII
        string EncodingFormat = "IBM037";
        byte[] encryptedByteWithASCIIEncoding = Encoding.Convert(Encoding.GetEncoding(EncodingFormat), Encoding.ASCII,
                encryptedByteWithIBMEncoding);


        //Encrypted Byte ASCII - ASCII Encoded string 
        string encodedEncryptedStringInASCII = System.Text.ASCIIEncoding.ASCII.GetString(encryptedByteWithASCIIEncoding);
        //UpdateSSN(encodedEncryptedStringInASCII);

        byte[] dataInBytesASCII = System.Text.ASCIIEncoding.ASCII.GetBytes(encodedEncryptedStringInASCII);
        byte[] bytesInIBM = Encoding.Convert(Encoding.ASCII, Encoding.GetEncoding(EncodingFormat),
                dataInBytesASCII);
        string clearTextSSN = DecryptionServiceHelper.GetDecryptedSSN(bytesInIBM);

助手类

 public static class DecryptionServiceHelper
{
    public const string EncodingFormat = "IBM037";
    public const string SSNPrefix = "0000000";
    public const string Encryption = "E";
    public const string Decryption = "D";

    public static byte[] GetEncryptedSSN(string clearTextSSN)
    {
        return GetEncryptedID(SSNPrefix + clearTextSSN);
    }

    public static string GetDecryptedSSN(byte[] encryptedSSN)
    {
        return GetDecryptedID(encryptedSSN);
    }

    private static byte[] GetEncryptedID(string id)
    {
        ServiceProgram input = new ServiceProgram();
        input.RequestText = Encodeto64(id);
        input.RequestType = Encryption;

        ProgramInterface inputRequest = new ProgramInterface();
        inputRequest.Test__Request = input;

        using (MY_Service operation = new MY_Service())
        {
            return ((operation.MY_Operation(inputRequest)).Test__Response.ResponseText);
        }
    }


    private static string GetDecryptedID(byte[] id)
    {
        ServiceProgram input = new ServiceProgram();
        input.RequestText = id;
        input.RequestType = Decryption;

        ProgramInterface request = new ProgramInterface();
        request.Test__Request = input;

        using (MY_Service operationD = new MY_Service())
        {
            ProgramInterface1 response = operationD.MY_Operation(request);
            byte[] encodedBytes = Encoding.Convert(Encoding.GetEncoding(EncodingFormat), Encoding.ASCII,
                response.Test__Response.ResponseText);

            return System.Text.ASCIIEncoding.ASCII.GetString(encodedBytes);
        }
    }

    private static byte[] Encodeto64(string toEncode)
    {
        byte[] dataInBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
        Encoding encoding = Encoding.GetEncoding(EncodingFormat);
        return Encoding.Convert(Encoding.ASCII, encoding, dataInBytes);
    }

}

参考

  1. Getting incorrect decryption value using AesCryptoServiceProvider

2 个答案:

答案 0 :(得分:1)

这是问题,我怀疑:

string encodedEncryptedStringInASCII = 
    System.Text.ASCIIEncoding.ASCII.GetString(encryptedByteWithASCIIEncoding);

(由于事先对编码的所有混乱,这并不完全清楚,这对我来说似乎毫无意义,但是......)

加密的结果是不是“用ASCII编码的文本” - 所以你不应该试着这样对待它。 (你还没有说过你正在使用什么样的加密技术,但是生成ASCII文本它会非常非常。)

它只是一个任意字节数组。为了仅使用ASCII字符集在文本中表示,最常用的方法是使用base64。所以上面的代码将成为:

string encryptedText = Convert.ToBase64(encryptedByteWithIBMEncoding);

然后,您将它转换回准备解密的字节数组:

encryptedByteWithIBMEncoding = Convert.FromBase64String(encryptedText);

我会强烈建议你尽量避免乱搞这样的编码,如果你能帮助它的话。目前尚不清楚为什么ASCII需要参与所有。如果确实希望在加密之前将原始文本编码为IBM037,则应该使用:

Encoding encoding = Encoding.GetEncoding("IBM037");
string unencryptedBinary = encoding.GetBytes(textInput);

就我个人而言,我通常使用UTF-8作为一种编码,可以处理任何字符数据,而不仅仅是一个有限的子集,但这取决于你。我认为你使整个事情变得比它需要的复杂得多。

典型的“加密字符串,获取字符串结果”工作流程为:

  1. 使用UTF-8将输入文本转换为字节。结果是一个字节数组。
  2. 加密步骤1的结果。结果是一个字节数组。
  3. 将步骤2的结果转换为base64。结果是一个字符串。
  4. 要解密:

    1. 从 base64转换字符串。结果是一个字节数组。
    2. 解密步骤1的结果。结果是一个字节数组。
    3. 使用与加密过程的第1步相同的编码将步骤2的结果转换回字符串。

答案 1 :(得分:0)

在DecryptionServiceHelper.GetEncryptedSSN中,您在加密前编码IBM037格式的文本。

所以下面的代码不正确,因为您将加密的字节转换为ASCII,假设它是IBM037格式。这是错误的,因为加密的字节不是IBM037格式(文本在加密之前编码)

//encryptedByteWithIBMEncoding -->  Encrypted Byte ASCII
string EncodingFormat = "IBM037";
byte[] encryptedByteWithASCIIEncoding = Encoding.Convert(Encoding.GetEncoding(EncodingFormat), Encoding.ASCII,
        encryptedByteWithIBMEncoding);

一种可能的解决方案是使用IBM037格式对加密文本进行编码,这应该可以解决我想到的问题。