Как рассчитать отпечаток SHA-1 сертификата X.509? - PullRequest
16 голосов
/ 26 января 2011

Я пытаюсь реализовать генератор сертификатов X.509 с нуля (знаю о существующих, но мне нужен еще один).Я не могу понять, как рассчитать SHA-1 (или любой другой) отпечаток сертификата.

RFC5280 говорит, что вход для функции подписи - это tbsCertificate с кодировкой DER.поле.К сожалению, хеш, который я вычисляю, отличается от хеша, созданного OpenSSL.Вот пошаговый пример.

  1. сгенерируйте сертификат с помощью инструмента OpenSSL x509 (в двоичной форме DER, не ASCII PEM)
  2. вычислениеего хэш SHA-1 с использованием openssl x509 -fingerprint
  3. извлекает поле TBS с помощью dd (или чего-либо еще) и сохраняет его в отдельном файле;вычислите его хэш с помощью утилиты sha1sum

Теперь хэши, которые я получаю на шагах 2 и 3, отличаются.Может кто-нибудь подсказать, что я могу делать не так?

Ответы [ 2 ]

19 голосов
/ 28 января 2011

Хорошо, так что оказалось, что отпечаток пальца, вычисленный OpenSSL, является просто хэшем над целым сертификатом (в двоичном кодировании DER, не ASCII PEM!),не только часть TBS, как я думал.

Для тех, кому небезразлично вычислять дайджест сертификата, это делается по-другому: хэш рассчитывается по DER-кодированию (опять же, не строка PEM) TBS part only , включая заголовок ASN.1 (идентификатор 0x30 == ASN1_SEQUENCE | ASN1_CONSTRUCTED и поле длины).Обратите внимание, что заголовок сертификата ASN.1 не учитывается.

2 голосов
/ 13 января 2015

Отпечаток пальца похож на термин «Отпечаток пальца» в .net.Ниже приведен фрагмент кода, который поможет вам вычислить отпечаток пальца:

    public String generateFingerPrint(X509Certificate cert) throws CertificateEncodingException,NoSuchAlgorithmException {

MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hash = digest.digest(cert.getEncoded[]);

final char delimiter = ':';
// Calculate the number of characters in our fingerprint
      // ('# of bytes' * 2) chars + ('# of bytes' - 1) chars for delimiters
      final int len = hash.length * 2 + hash.length - 1;
      // Typically SHA-1 algorithm produces 20 bytes, i.e. len should be 59
      StringBuilder fingerprint = new StringBuilder(len);

      for (int i = 0; i < hash.length; i++) {
         // Step 1: unsigned byte
         hash[i] &= 0xff;

         // Steps 2 & 3: byte to hex in two chars
         // Lower cased 'x' at '%02x' enforces lower cased char for hex value!
         fingerprint.append(String.format("%02x", hash[i]));

         // Step 4: put delimiter
         if (i < hash.length - 1) {
            fingerprint.append(delimiter);
         }
      }

      return fingerprint.toString();


    }
...