我现在手头在做一个项目的统一认证登录接口接口数据的加密方式是base64(3des(code));对称算法模式是CBC填充模式PKCS7对方是用JAVA的,我这边是用C#进行开发的。 我这边使用的3DES方法如下
#region 3DES加解密
    /// <summary>
    /// 3DES解密
    /// </summary>
    /// <param name="a_strString"></param>
    /// <param name="a_strKey"></param>
    /// <returns></returns>
    public string Decrypt3DES(string a_strString, string a_strKey)
    {
        TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();
        provider.KeySize = 192;
        provider.Key = KeyBytes();
        provider.IV = Encoding.UTF8.GetBytes("12345678");
        provider.Mode = CipherMode.CBC;
        provider.Padding = PaddingMode.PKCS7;
        ICryptoTransform transform = provider.CreateDecryptor();
        string str = "";
        try
        {
            byte[] inputBuffer = Convert.FromBase64String(a_strString);
            str = Encoding.UTF8.GetString(transform.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length));
        }
        catch (Exception e)
        {
            MessageHelper.Alert(e.Message);
        }
        return str;
    }    /// <summary>
    /// 3DES加密
    /// </summary>
    /// <param name="a_strString"></param>
    /// <param name="a_strKey"></param>
    /// <returns></returns>
    public string Encrypt3DES(string a_strString, string a_strKey)
    {
        TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();
        provider.KeySize = 192;
        provider.Key = KeyBytes();
        provider.IV = Encoding.UTF8.GetBytes("12345678");
        provider.Mode = CipherMode.CBC;
        provider.Padding = PaddingMode.PKCS7;
        ICryptoTransform transform = provider.CreateEncryptor();
        byte[] bytes = Encoding.UTF8.GetBytes(a_strString);
        return Convert.ToBase64String(transform.TransformFinalBlock(bytes, 0, bytes.Length));
    }
    #endregion密钥是对方给的48个字符(16进制的)所以上述代码中我将之转换成了字节数组。可是加密出来的和对方的一直对不上 我这边base64(3des("a"))的结果="qq84WJTIZcc="而对方的base64(3des("a"))的结果却="uZqJ8b6Lu90="请问是我的代码有问题吗?

解决方案 »

  1.   

    从你代码看密钥长度192,也就是24字节,而给出的字符串48位,需要成24位的字节,应该是每两个字符串转换为一个字节。
    不知道你KeyBytes()怎么实现的,貌似你的密钥a_strKey也没用到。下面给你一段代码,我之前做加密用的。
    /// <summary>
    /// 把字符串转换为字节数组
    /// </summary>
    /// <param name="strKey">源串</param>
    public static byte[] covertStringToHex(string strKey)
    {
    int strLen = strKey.Length;
    //字节长度是字符串的一半
    int byLen = strKey.Length >> 1; byte[] key = new byte[byLen];
    for (int i = 0, j = 0; i < byLen && j < strLen; i++)
    {
    key[i] = (byte)(convertCharToHex(strKey[j++]) << 4);
    key[i] += (byte)(convertCharToHex(strKey[j++]) & 0xF);
    }
    return key;
    } /// <summary>
    /// 
    /// </summary>
    /// <param name="ch"></param>
    /// <returns></returns>
    public static int convertCharToHex(char ch)
    {
    if ((ch >= '0') && (ch <= '9'))
    return ch - 0x30;
    else if ((ch >= 'A') && (ch <= 'F'))
    return ch - 'A' + 10;
    else if ((ch >= 'a') && (ch <= 'f'))
    return ch - 'a' + 10;
    else
    return -1;
    }
      

  2.   

    貌似 CBC 跟 3DES 是两种完全不同的加密算法来的。。得出不同的结果是理所当然的吧。。
      

  3.   

    我是通过这个方法将16进制的字符串转化成字节数组的 /// <summary>
        /// KEY
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static byte[] GetKeyBytes(string hex)
        {
            byte[] bytes = new byte[hex.Length / 2];        for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。                            bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message. 
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }
            return bytes;
        }
      

  4.   


    3DES算法中,C#创建加密的时候可以指定模式的代码中有体现 provider.Mode = CipherMode.CBC;因为3DES算法可以指定某种对称算法模式在CBC模式中则一定要指定一个初始向量IV如果是EBC的话似乎可以不用指定的
    我是第一次接触C#的3DES算法,以上说法如果有错误的话请指正
    还请各位高手多多指教
      

  5.   

    在反复尝试无效后,我又找了一个3DES的加密方法
    其实总的来说都差不多,只是传进去的值是BYTE[]而已结果出来的base64(3des("a"))的结果还是="qq84WJTIZcc="附3DES代码
    #region CBC模式**
        /// <summary>  
        /// DES3 CBC模式加密  
        /// </summary>  
        /// <param name="key">密钥</param>  
        /// <param name="iv">IV</param>  
        /// <param name="data">明文的byte数组</param>  
        /// <returns>密文的byte数组</returns>  
        public static byte[] Des3EncodeCBC(byte[] key, byte[] iv, byte[] data)
        {
            //复制于MSDN  
            try
            {
                // Create a MemoryStream.  
                MemoryStream mStream = new MemoryStream();
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.CBC;             //默认值  
                tdsp.Padding = PaddingMode.PKCS7;       //默认值  
                // Create a CryptoStream using the MemoryStream   
                // and the passed key and initialization vector (IV).  
                CryptoStream cStream = new CryptoStream(mStream,
                    tdsp.CreateEncryptor(key, iv),
                    CryptoStreamMode.Write);
                // Write the byte array to the crypto stream and flush it.  
                cStream.Write(data, 0, data.Length);
                cStream.FlushFinalBlock();
                // Get an array of bytes from the   
                // MemoryStream that holds the   
                // encrypted data.  
                byte[] ret = mStream.ToArray();
                // Close the streams.  
                cStream.Close();
                mStream.Close();
                // Return the encrypted buffer.  
                return ret;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
                return null;
            }
        }
        /// <summary>  
        /// DES3 CBC模式解密  
        /// </summary>  
        /// <param name="key">密钥</param>  
        /// <param name="iv">IV</param>  
        /// <param name="data">密文的byte数组</param>  
        /// <returns>明文的byte数组</returns>  
        public static byte[] Des3DecodeCBC(byte[] key, byte[] iv, byte[] data)
        {
            try
            {
                // Create a new MemoryStream using the passed   
                // array of encrypted data.  
                MemoryStream msDecrypt = new MemoryStream(data);
                TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
                tdsp.Mode = CipherMode.CBC;
                tdsp.Padding = PaddingMode.PKCS7;
                // Create a CryptoStream using the MemoryStream   
                // and the passed key and initialization vector (IV).  
                CryptoStream csDecrypt = new CryptoStream(msDecrypt,
                    tdsp.CreateDecryptor(key, iv),
                    CryptoStreamMode.Read);
                // Create buffer to hold the decrypted data.  
                byte[] fromEncrypt = new byte[data.Length];
                // Read the decrypted data out of the crypto stream  
                // and place it into the temporary buffer.  
                csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
                //Convert the buffer into a string and return it.  
                return fromEncrypt;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
                return null;
            }
        }
        #endregion
    附参数
                byte[] b = Encoding.UTF8.GetBytes(Source);
                byte[] IV = Encoding.UTF8.GetBytes("12345678");
                byte[] Key = KeyBytes;
    由于测试用密钥始终是一个值,就做成了BYTE[]常量之前有怀疑过是不是密钥解出来的字节数组与对方不一致结果我使用二楼的仁兄提供的方法得到的值与对方对比了一下,发现是一样的