Простите за длинную настройку здесь, но я подумал, что может помочь контекст...
Я реализую собственный метод проверки цифровой подписи как часть службы WCF. Мы используем специальный метод из-за различных интерпретаций некоторых отраслевых стандартов, но детали здесь не так важны.
В этом конкретном сценарии я получаю закодированный запрос MTOM/XOP, в котором корневая часть MIME содержит цифровую подпись, а части DigestValue и SignatureValue подписи разделены на отдельные части MIME.
Части MIME, которые содержат данные подписи DigestValue и SignatureValue, закодированы в двоичном формате, поэтому это буквально набор необработанных байтов в веб-запросе, например:
Content-Id: <[email protected]>
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 или она ведет себя не так, как я ожидал.