传递带有数字数据的文本时,我的加密和解密功能无效

时间:2016-12-30 15:34:23

标签: c# .net cryptography

当我将正常字母传递给我的加密和解密函数时,它按预期工作,但是当我传递字母数字文本加密和解密函数时,它就无法正常工作。

当我通过encrypt(“test1”)或解密(“test1”)时,它就无法正常工作。特别解密不使用字母数字的情况。

我想重构我的加密和解密功能,无论我传递的功能是什么值都可以。假设我可以传递具有特殊字符的字母数字数据。所以plerase看到代码并带有纠正的版本。

加密/解密的小包装

   private string encrypt(string message)
    {
        EncryptClass.EncryptClass ec = new EncryptClass.EncryptClass();
        string encryStr = ec.custEncrypt(message);
        return encryStr;
    }

    private string decrypt(string message)
    {
        EncryptClass.EncryptClass ec = new EncryptClass.EncryptClass();
        string decryptStr = message;
        return ec.custDecrypt(decryptStr);
    }

加密和解密的完整代码

public class EncryptClass
{
    DESCryptoServiceProvider rj;
    byte[] key = new byte[] { 11, 9, 3, 4, 1, 8, 12, 7 };
    byte[] IV = new byte[] { 1, 8, 7, 16, 1, 9, 0, 3 };
    public EncryptClass()
    {
        //
        // TODO: Add constructor logic here
        //
        rj = new DESCryptoServiceProvider();
    }

    // for encryption
    public string custEncrypt(string message)
    {
        //create a memory stream
        MemoryStream ciphertextmem = new MemoryStream();
        //create a crypto stream in write mode
        CryptoStream crystm = new CryptoStream(ciphertextmem, rj.CreateEncryptor(key, IV), CryptoStreamMode.Write);
        //Encode the passed plain text string into Unicode byte stream
        Byte[] plaintextbyte = new UnicodeEncoding().GetBytes(message);
        //Write the plaintext byte stream to CryptoStream
        crystm.Write(plaintextbyte, 0, plaintextbyte.Length);
        //don't forget to close the stream
        crystm.Close();
        //Extract the ciphertext byte stream and close the MemoryStream
        Byte[] ciphertextbyte = ciphertextmem.ToArray();
        ciphertextmem.Close();
        //Encode the ciphertext byte into Unicode string
        string ciphertext = new UnicodeEncoding().GetString(ciphertextbyte);
        return ciphertext;
        //return "encry " + message;


    }

    // for decryption
    public string custDecrypt(string message)
    {
        //Create a memory stream from which CryptoStream will read the cipher text
        MemoryStream ciphertextmem = new MemoryStream(new UnicodeEncoding().GetBytes(message));

        //Create a CryptoStream in Read Mode; initialise with the Rijndael's Decryptor ICryptoTransform
        CryptoStream crystm = new CryptoStream(ciphertextmem, rj.CreateDecryptor(key, IV), CryptoStreamMode.Read);

        //Create a temporary memory stream to which we will copy the 
        //plaintext byte array from CryptoStream

        MemoryStream plaintextmem = new MemoryStream();
        do
        {
            //Create a byte array into which we will read the plaintext 
            //from CryptoStream
            Byte[] buf = new Byte[100];

            //read the plaintext from CryptoStream
            int actualbytesread = crystm.Read(buf, 0, 100);

            //if we have reached the end of stream quit the loop
            if (0 == actualbytesread)
                break;

            //copy the plaintext byte array to MemoryStream
            plaintextmem.Write(buf, 0, actualbytesread);

        } while (true);

        //don't forget to close the streams
        crystm.Close();
        ciphertextmem.Close();

        //Extract the plaintext byte stream and close the MemoryStream
        Byte[] plaintextbyte = plaintextmem.ToArray();
        plaintextmem.Close();

        //Encode the plaintext byte into Unicode string
        string plaintext = new UnicodeEncoding().GetString(plaintextbyte);

        return plaintext;

        //return "decry "+ message;
    }
}

请查看我的代码并修正区域,因此如果我只传递文字或传递带有数字数据或带有特殊字符的字母数字的文字,它应该可以正常工作

寻求帮助。

1 个答案:

答案 0 :(得分:0)

有更简单的方法可以做到这一点,并且在您的实施中存在一些严重的缺陷:

  1. 使用相同的IV和静态密钥并没有太大的保护
  2. 结果不能表示为文本字符串,这可能是进行往返的核心问题
  3. 可以使用CryptoStream,但除非您输出到流,否则只会使事情变得复杂。
  4. 我试图修改你的代码,但最终只是重新开始:

    public class EncryptClass
    {
        const int hashCount = 21569;
    
        public static string EncryptString(string message, string pass)
        {
            using (RijndaelManaged rij = new RijndaelManaged())
            {
                rij.GenerateIV();
                rij.Key = HashPassword(pass);
    
                using (ICryptoTransform cryptor = rij.CreateEncryptor())
                {
                    var data = Encoding.Unicode.GetBytes(message);
                    var buff = cryptor.TransformFinalBlock(data, 0, data.Length);
                    // concat to the IV for the other side
                    // crypto data is binary - use Base64 for text encoding
                    return Convert.ToBase64String(rij.IV.Concat(buff).ToArray());
                }
            }
        }
    
        private static byte[] HashPassword(string thePW)
        {
            // originally from RNGCryptoServiceProvider.GetRandomBytes
            byte[] salt = new byte[] { 96, 248, 204, 72, 177, 214, 251, 82, 174, 
                            90, 82, 90, 111, 76, 146, 172 };
    
            using (var hasher = new Rfc2898DeriveBytes(thePW, salt, hashCount))
            {
                return hasher.GetBytes(32);
            }
        }
    

    这使用RijndaelManaged作为加密提供程序。如您所见,它非常简单。一些关键点:

    • 方法是静态的
    • 每次都会生成一个新的IV。
    • 生成的加密输出连接到IV,因此它可供Decryptor使用。如果要加密文件流,请将它们写入裸FileStream
    • 此版本使用PBKDF哈希密码,一些初始随机盐和大量迭代
    • 由于它只是一个字符串,因此只需加TransformFinalBlock即可
    • 结果编码为Base64

    我不确定你为什么使用Unicode编码,所以我把它留在了里面。解密也很简单:

    public static string DecryptString(string crypted, string pass)
    {
        byte[] data = Convert.FromBase64String(crypted);
        using (RijndaelManaged rij = new RijndaelManaged())
        {
            int size = (int)(rij.BlockSize / 8);
            byte[] iv = new byte[size];
    
            // copy the iv to the array
            Array.Copy(data, 0, iv, 0, size);
    
            rij.IV = iv;
            rij.Key = HashPassword(pass);
    
            using (ICryptoTransform cryptor = rij.CreateDecryptor())
            {
                var buff = cryptor.TransformFinalBlock(data, size, data.Length - size);
                return Encoding.Unicode.GetString(buff);
            }
        }
    }
    

    将Base64字符串转换回字节后,从字节数组中取出IV,并将TransformFinalBlock的偏移量放入数组中以说明IV。使用和测试:

    string msg = "This is some text 123 1 87  45";
    
    string crypto = EncryptClass.EncryptString(msg, "I Like Pi");
    Console.WriteLine(crypto);
    string retVal = EncryptClass.DecryptString(crypto, "I Like Pi");
    Console.WriteLine(retVal);
    

    结果:

      

    mIfpIkTVC7mI5R1hlIIpVs63N / j4LN + p2pGPuo90eEPWvW + sqSiBIDjto1 + E1p0umdI1hDnkxa2droAbuAFwPzuNK3gABrFjsNpi6FXwGOw =

         

    这是一些文字123 1 87 45

    顶行是加密数据的Base64形式;第二个是解密输出。