Я могу успешно выполнить проверку ссылочной ссылки (канонизировать каждый ссылочный элемент -> SHA1 -> Base64 -> проверить, совпадает ли это с содержимым DigestValue), но я терпеть неудачу с проверкой SignatureValue. Вот SignedInfo канонизировать и хэш:Ручная проверка XML-подписи
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#element-1-1291739860070-11803898">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>d2cIarD4atw3HFADamfO9YTKkKs=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#timestamp">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>YR/fZlwJdw+KbyP24UYiyDv8/Dc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
Атер удаления всех пробелов между тегами (и поэтому получать весь элемент на одной линии), я получаю эту sha1 переваривать (в Base64):
6l26iBH7il/yrCQW6eEfv/VqAVo =
Теперь я ожидаю, чтобы найти тот же переваривать после расшифровки содержания SignatureValue, но я получаю Differente и больше значение:
MCEwCQYFKw4DAhoFAAQ U3M24VwKG02yUu6jlEH + u6R4N8Ig =
Вот некоторые Java-код для decyption:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new File(inputFilePath));
NodeList nl = doc.getElementsByTagName("ds:SignatureValue");
if (nl.getLength() == 0) {
throw new Exception("Cannot find SignatureValue element");
}
String signature = "OZg96GMrGh0cEwbpHwv3KDhFtFcnzPxbwp9Xv0pgw8Mr9+NIjRlg/G1OyIZ3SdcOYqqzF4/TVLDi5VclwnjBAFl3SEdkyUbbjXVAGkSsxPQcC4un9UYcecESETlAgV8UrHV3zTrjAWQvDg/YBKveoH90FIhfAthslqeFu3h9U20=";
X509Certificate cert = X509Certificate.getInstance(new FileInputStream(<a file path>));
PublicKey pubkey = cert.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA","SunJCE");
cipher.init(Cipher.DECRYPT_MODE, pubkey);
byte[] decodedSignature = Base64Coder.decode(signature);
cipher.update(decodedSignature);
byte[] sha1 = cipher.doFinal();
System.out.println(Base64Coder.encode(sha1));
Дело в том, что меня смущает многое, что два дайджесты имеют разный размер, но я, конечно, также необходимо получить точно такое же значение из двух расчетов. Какие-либо предложения? Спасибо.
«Атер, удаляющий все промежутки между тегами» ... это правильно? Глядя на http://www.w3.org/TR/2001/REC-xml-c14n-20010315#Example-WhitespaceInContent, похоже, что вы удаляете слишком много пробелов. –
Спасибо за ответ. Я понимаю вашу точку зрения, но, как я сказал в начале вопроса, я могу успешно выполнить проверку ссылок (две ссылки, это не может быть случайностью) одного и того же сообщения SOAP, и только путем удаления этих пространств, поэтому я должен предположить это верно. – Johnca
Канонизация - это гораздо больше, чем удаление пробелов. Он обрабатывает проблемы с префиксом пространства имен, упорядочивание атрибутов и, как правило, все, что изменяет порядок байтов файла phisicaly (и, следовательно, хеш-дайджест), но не изменяет XML-информацию (== смысл полезной нагрузки XML) – m0sa