请原谅这里冗长的设置,但我认为了解上下文可能会有所帮助......
我正在作为 WCF 服务的一部分实现自定义数字签名验证方法。我们使用自定义方法是因为对某些行业标准的各种不同解释,但其中的细节并不那么相关。
在这个特定场景中,我收到一个 MTOM/XOP 编码请求,其中根 MIME 部分包含一个数字签名,并且签名 DigestValue 和 SignatureValue 片段被拆分为单独的 MIME 部分。
包含签名 DigestValue 和 SignatureValue 数据的 MIME 部分是二进制编码的,因此它实际上是 Web 请求中的一堆原始字节,如下所示:
Content-Id: <c18605af-18ec-4fcb-bec7-e3767ef6fe53@example.jaxws.sun.com>
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
[non-printable-binary-data-goes-here]
--uuid:eda4d7f2-4647-4632-8ecb-5ba44f1a076d
我正在将消息的内容作为字符串读取(使用默认的 UTF8 编码),如下所示(请参阅下面的 requestAsString 参数):
MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue);
try
{
using (MemoryStream mstream = new MemoryStream())
{
buffer.WriteMessage(mstream);
mstream.Position = 0;
using (StreamReader sr = new StreamReader(mstream))
{
requestAsString = sr.ReadToEnd();
}
request = buffer.CreateMessage();
}
}
在我读入 MTOM/XOP 消息后,我试图将多个 MIME 部分重新组织成一个 SOAP 消息,其中签名 DigestValue 和 SignatureValue 元素恢复到原始 SOAP 信封(而不是作为附件)。所以基本上我正在解码 MTOM/XOP 请求。
不幸的是,我无法正确阅读 DigestValue 和 SignatureValue 片段。我需要从消息中读取字节并获取该数据的 base64 字符串表示。
尽管有上述所有内容,但核心问题似乎是将二进制数据作为字符串(UTF8 编码)读取,然后将其转换为适当的 base64 表示。
这是我在测试代码中看到的:
这是我的示例 base64 字符串:
string base64String = "mowXMw68eLSv9J1W7f43MvNgCrc=";
然后我可以得到那个字符串的字节表示。这会产生一个 20 字节的数组:
byte[] base64Bytes = Convert.FromBase64String(base64String);
然后我得到这些字节的 UTF8 编码版本:
string decodedString = UTF8Encoding.UTF8.GetString(base64Bytes);
现在奇怪的部分......如果我将字符串转换回字节,如下所示,我得到一个 39 字节长的字节数组:
byte[] base64BytesBack = UTF8Encoding.UTF8.GetBytes(decodedString);
所以很明显在这一点上,当我转换回base64字符串时,它与原始值不匹配:
string base64StringBack = Convert.ToBase64String(base64BytesBack);
base64StringBack 设置为“77+977+9FzMO77+9eO+/ve+/ve+/vVbvv73vv703Mu+/vWAK77+9”
我在这里做错了什么?如果我切换到使用 UTF8Encoding.Unicode.GetString() 和 UTF8Encoding.Unicode.GetBytes(),它会按预期工作:
string base64String = "mowXMw68eLSv9J1W7f43MvNgCrc=";
// First get an array of bytes from the base64 string
byte[] base64Bytes = Convert.FromBase64String(base64String);
// Get the Unicode representation of the base64 bytes.
string decodedString = UTF8Encoding.Unicode.GetString(base64Bytes);
byte[] base64BytesBack = UTF8Encoding.Unicode.GetBytes(decodedString);
string base64StringBack = Convert.ToBase64String(base64BytesBack);
现在 base64StringBack 设置为 "mowXMw68eLSv9J1W7f43MvNgCrc=" 所以我似乎误用了 UTF8 编码,或者它的行为与我预期的不同。