Вопрос

Я могу успешно сделать руководственную справочную проверку (Canonicalize каждый элемент ссылки -> SHA1 -> Base64 -> Проверьте, если это то же самое содержимое дизначейства), но я терпит неудачу с проверкой подписивера. Вот вывеска для канонизации и хеш:

<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>

Ater Удаление всех пробелов между тегами (и поэтому получая весь элемент на одну строку), я получаю эту Diagest Sha1 (в Base64):

6L26IBH7IL / YRCQW6EEFV / VQAVO =

Теперь я ожидаю найти тот же дайджест после дешифрования содержания подписивале, но я получаю отличную и дольше стоимость:

Mcewcqyfkw4dahofaaqu3m24vwkg02yuu6jleh + U6R4n8ig =

Вот какой-то код Java для дециплинга:

      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));

Дело в том, что у меня смущает, что два дайджета имеют разные размеры, но, конечно, мне также нужно получить точно такое же значение из двух расчетов. Какие-либо предложения? Спасибо.

Это было полезно?

Решение

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH+u6R4N8Ig= Является ли BASE64 кодировкой для DER-кодированной структуры ASN.1: SEQUENCE содержащий первый ан AlgorithmIdentifier (который заявляет, что это SHA-1, без параметров, поскольку SHA-1 не принимает), то OCTET STRING который содержит фактическое 20 байтовое значение. В шестнадцатеричном значении значение: dccdb8570286d36c94bba8e5107faee91e0df088.

Эта структура ASN.1 является частью стандарта Подпись RSA механизм. Вы используете RSA дешифрование Для доступа к этой структуре, нестандартной. Вам на самом деле повезло что-нибудь вообще, так как Rsa шифрование а также Подпись RSA два отдельных алгоритма. Это так бывает, что они оба кормят в одном и том же клавишевых парах, и что «старый стиль» (AKA «PKCS # 1 V1.5»), и схемы шифрования и шифрования используют аналогичные методы заполнения (аналогичные, но не одинаковые; Уже немного удивительно, что реализация Java RSA не задыхается от подписи при подписи при использовании в режиме дешифрования).

В любом случае, 6l26iBH7il/yrCQW6eEfv/VqAVo= Кодировка Base64 для 20-байтового значения, которое, в шестнадцатеричном, является: ea5dba8811fb8a5ff2ac2416e9e11fbff56a015a. Отказ Это то, что вы получаете, используя структуру XML, вы показываете выше, после удаления всех пробелов между тегами. Удаление всех пробелов нет правильная канонизация. На самом деле, насколько я знаю, пробел влияет только между атрибутами в рамках тегов, но внешнее пробеловое пространство должно быть не изменено (за исключением нормализации линии [LF / CR + LF]).

Значение, которое использовалось для генерации подписи ( dccdb85...) можно получить с помощью объекта XML, который вы показываете, и удалив ведущие пробелы. Чтобы быть понятным: вы копируете + вставьте XML в файл, затем удалите ведущие пробелы (от 0 до 3 пробелов) на каждой строке. Вы убедитесь, что все в конце концов используют один LF (байт 0x0a), и вы удаляете окончательный LF (то, что сразу после </ds:SignedInfo>). Полученный файл должен иметь длину 930 байтов, а его хеш SHA-1 ожидается dccdb85... стоимость.

Другие советы

Глядя на ваш конкретный токен XML, я могу сказать вам несколько вещей.

  • Вы используете метод канонизации Эксклюзивная XML Canonicalization версии 1.0. Отказ Это очень ВАЖНЫЙ Фактор обеспечения того, чтобы вы создали правильные значения дайджеста и подпись.

  • Вы используете тот же метод канонизации как для вычисления ссылочных данных, так и для канонизации SignedInfo.перед произведением подписи.

Спецификация для эксклюзивной XML Canonicalizaiton версии 1.0 производится на W3C и может быть найдена в соответствующем Рекомендация W3C. Отказ Если вы вычисляете свои значения вручную, будьте уверены, что вы точно соответствуете спецификации, поскольку Canonicalization - это трудное, что нужно правильно, и очень важно сделать это правильно, в противном случае ваши значения будут неверными.

Я только что написал обширную статью, описывающую процесс проверки подписи XML. Статья находится в мой блог. Отказ Он описывает процесс гораздо более подробно, чем мой ответ, так как есть много тонкостей для подписи XML. Он также содержит ссылки на распространенные спецификации и RFC.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top