1

我在安全网站上问了这个问题,那里的人建议我应该把它贴在这里。

一些背景。我们有在专有操作系统上运行 c 的专有设备和在 Windows 操作系统上运行 ac# dll 的其他设备。两者都通过 TCP 连接联系我们的服务器,因为我们的服务器两种类型的请求是相同的。TCP 服务器通过 http 绑定将部分请求传输到自承载的 WCF 服务。请求被加密,如链接所示(就像 C# dll 加密它们一样)。

我正在尝试切断 TCP 服务器并将请求直接发送到 WCF 服务。

我的问题是 WCF 服务似乎接收到错误的请求字符串,并且无法解密它。

似乎服务器端接收字符串中还有额外的 \t \n 。除此之外,它看起来一样。

这是服务器端的解密代码:

            byte[] byteChiperText = Encoding.Default.GetBytes(input);

            if (k.Length != 16)
            {
                throw new Exception("Wrong key size exception");
            }
            TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

            des.Mode = CipherMode.ECB;
            des.Padding = PaddingMode.Zeros;
            des.Key = k;
            ICryptoTransform ic = des.CreateDecryptor();
            MemoryStream ms = new MemoryStream(byteChiperText);
            CryptoStream cStream = new CryptoStream(ms,
                 ic,
                 CryptoStreamMode.Read);
            StreamReader sReader = new StreamReader(cStream);
            byte[] data = new byte[byteChiperText.Length];
            int len = sReader.BaseStream.Read(data, 0, data.Length);
            output = Encoding.Default.GetString(data, 0, len);

            cStream.Close();
4

2 回答 2

6

好吧,这看起来很糟糕:

byte[] byteChiperText = Encoding.Default.GetBytes(input);

您将加密数据视为使用平台默认编码的文本编码。这是丢失数据的好方法。加密数据不是文本。它是任意二进制数据,应该这样对待。

相反,您应该使用 base64 将加密数据编码为文本 ( Convert.ToBase64String),然后Convert.FromBase64String稍后将其反转 ( ) 以返回原始密码文本。当然,这是假设您需要以文本形式开始。如果你一开始就可以通过它byte[],那就更好了。

另请注意,您获取文本的方法有些奇怪 - 您正在创建一个StreamReader, 然后仅使用基本流。最好使用:

// You should be using "using" statements for all your streams, by the way...
using (TextReader reader = new StreamReader(cStream))
{
    output = reader.ReadToEnd();
}

请注意,这将使用 UTF-8 而不是平台默认编码 - 但这是一件好事,只要您在加密代码中进行相应的更改。使用平台默认编码几乎总是一个错误——它可能不支持所有的 Unicode,而且它因机器而异。

于 2012-06-19T06:08:07.487 回答
2

问题可能出在Encoding.Default中,因为:

不同的计算机可以使用不同的编码作为默认值。

您应该使用给定的标准编码(UTF-8、UTF-16、..)。

于 2012-06-19T06:10:28.857 回答