не могу получить отображение открытого ключа в Java, чтобы соответствовать тем в Adobe - PullRequest
1 голос
/ 09 июня 2019

Я подписываю PDF, используя сертификат.В Java я обрабатываю PDF и извлекаю детали сертификата.Я сравниваю вывод с данными сертификата, показанными в Adobe для этого документа.Для SerialNumber я смог заставить их выглядеть одинаково, но не для открытого ключа.Любая помощь приветствуется!

Я отлаживал код, пытался конвертировать, используя Hex.toHexString, гуглил в stackoverflow.Но не повезло

System.out.println("signed? " + pdAcroForm.isSignaturesExist());
if (pdAcroForm.isSignaturesExist()) {
    PDSignatureField signatureField = (PDSignatureField) pdAcroForm.getField("signatureField");
    System.out.println("Name: " + signatureField.getSignature().getName());
    System.out.println("Name: " + signatureField.getSignature().getContactInfo());

    Security.addProvider(new BouncyCastleProvider());
    List<PDSignature> signatureDictionaries = document.getSignatureDictionaries();
    X509Certificate cert;
    Collection<X509Certificate> result = new HashSet<X509Certificate>();
    // Then we validate signatures one at the time.
    for (PDSignature signatureDictionary : signatureDictionaries) {
        // NOTE that this code currently supports only "adbe.pkcs7.detached", the most common signature /SubFilter anyway.
        byte[] signatureContent = signatureDictionary.getContents(new FileInputStream(signedFile));
        byte[] signedContent = signatureDictionary.getSignedContent(new FileInputStream(signedFile));
        // Now we construct a PKCS #7 or CMS.
        CMSProcessable cmsProcessableInputStream = new CMSProcessableByteArray(signedContent);
        try {
            CMSSignedData cmsSignedData = new CMSSignedData(cmsProcessableInputStream, signatureContent);
            Store<?> certStore = cmsSignedData.getCertificates();
            SignerInformationStore signers = cmsSignedData.getSignerInfos();
            Iterator<?> it = signers.getSigners().iterator();
            while (it.hasNext()) {
                SignerInformation signer = (SignerInformation) it.next();
                Collection<?> certCollection = certStore.getMatches(signer.getSID());
                Iterator<?> certIt = certCollection.iterator();
                while (certIt.hasNext()) {
                    X509CertificateHolder certificateHolder = (X509CertificateHolder) certIt.next();
                    System.out.println(certificateHolder.getSubjectPublicKeyInfo());
                    System.out.println(certificateHolder.getSubject());
                    System.out.println(certificateHolder.getIssuer());
                    System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded()));
                    // SerialNumber isi BigInteger in java and hex value in Windows/Mac/Adobe
                    System.out.println(certificateHolder.getSerialNumber().toString(16));

                    //result.add(new JcaX509CertificateConverter().getCertificate(certificateHolder));

                    /*PublicKey pkey = cert.getPublicKey();
                    System.out.println(pkey.toString());
                    System.out.println(cert.getNotBefore());
                    System.out.println(cert.getNotAfter());
                    System.out.println(cert.getSerialNumber());
                    System.out.println("issuer: " + cert.getIssuerDN());
                    System.out.println("subject:" + cert.getSubjectDN());
                    System.out.println("subject:" + cert.getSubjectDN());
                    System.out.println(cert.getSigAlgName());
                    */
                }
            }
        } catch (CMSException cmse) {
            cmse.printStackTrace();
        }
    }
}

В Adobe открытый ключ отображается следующим образом:

30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00 30 81 89 02 81 81 00 A8 D1 52 E7 2F 58 E8 AE 62 F6 C5 77 2F 78 FA 21 46 51 B5 EF A3 A4 4C E2 EE BD A0 80 46 B6 1D 66 37 01 82 3F 65 5D 3B 0B E7 11 08 05 94 40 CF F2 EF CC BF D9 1A F6 6F 5B 0E 16 5F 85 C1 F3 D7 9D C8 C6 EF 41 09 7C A4 C3 D5 CA 1C F0 80 E6 3F BA D8 69 8F 67 67 70 FC EB 28 48 59 B3 4F F4 6B 38 E7 3B 94 0F 7C EF 2C 02 41 8A 35 A8 72 DE DE 78 DD ED 90 AD 5E 25 A3 71 DD 59 95 1C 57 24 C8 B5 02 03 01 00 01

В Java, используя

System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded()));

SerialNumber равен BigInteger в Java ишестнадцатеричное значение в Windows / Mac / Adobe показывается так:

03818d0030818902818100a8d152e72f58e8ae62f6c5772f78fa214651b5efa3a44ce2eebda08046b61d663701823f655d3b0be71108059440cff2efccbfd91af66f5b0e165f85c1f3d79dc8c6ef41097ca4c3d5ca1cf080e63fbad8698f676770fceb284859b34ff46b38e73b940f7cef2c02418a35a872dede78dded90ad5e25a371dd59951c5724c8b50203010001

Для SerialNumber это работает нормально.Код Java:

System.out.println(certificateHolder.getSerialNumber().toString(16));

Вывод Java:

b27f048515c4f8e4

Вывод Adobe:

00 B2 7F 0485 15 C4 F8 E4

Большое спасибо заранее!

1 Ответ

1 голос
/ 13 июня 2019

Проблема

Разница в том, что Adobe представляет шестнадцатеричный дамп полного объекта SubjectPublicKeyInfo (открытый ключ, включая информацию об алгоритме и значение ключа), в то время как ваш код выводит только RSAPublicKey (сам ключ).

Вы можете увидеть это яснее, посмотрев определения ASN.1 рассматриваемых объектов и дамп ASN.1 обоих массивов:

SubjectPublicKeyInfo

   SubjectPublicKeyInfo  ::=  SEQUENCE  {
        algorithm            AlgorithmIdentifier,
        subjectPublicKey     BIT STRING  }

Дамп Adobe SubjectPublicKeyInfo

    <30 81 9F>
  0 159: SEQUENCE {
    <30 0D>
  3  13: . SEQUENCE {
    <06 09>
  5   9: . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
       : . . . (PKCS #1)
    <05 00>
 16   0: . . NULL
       : . . }
    <03 81 8D>
 18 141: . BIT STRING, encapsulates {
    <30 81 89>
 22 137: . . SEQUENCE {
    <02 81 81>
 25 129: . . . INTEGER    
       : . . . . 00 A8 D1 52 E7 2F 58 E8    ...R./X.
       : . . . . AE 62 F6 C5 77 2F 78 FA    .b..w/x.
       : . . . . 21 46 51 B5 EF A3 A4 4C    !FQ....L
       : . . . . E2 EE BD A0 80 46 B6 1D    .....F..
       : . . . . 66 37 01 82 3F 65 5D 3B    f7..?e];
       : . . . . 0B E7 11 08 05 94 40 CF    ......@.
       : . . . . F2 EF CC BF D9 1A F6 6F    .......o
       : . . . . 5B 0E 16 5F 85 C1 F3 D7    [.._....
       : . . . . 9D C8 C6 EF 41 09 7C A4    ....A.|.
       : . . . . C3 D5 CA 1C F0 80 E6 3F    .......?
       : . . . . BA D8 69 8F 67 67 70 FC    ..i.ggp.
       : . . . . EB 28 48 59 B3 4F F4 6B    .(HY.O.k
       : . . . . 38 E7 3B 94 0F 7C EF 2C    8.;..|.,
       : . . . . 02 41 8A 35 A8 72 DE DE    .A.5.r..
       : . . . . 78 DD ED 90 AD 5E 25 A3    x....^%.
       : . . . . 71 DD 59 95 1C 57 24 C8    q.Y..W$.
       : . . . . B5                         .
    <02 03>
157   3: . . . INTEGER 65537
       : . . . }
       : . . }
       : . }

RSAPublicKey

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

Ваш дамп RSAPublicKey

    <30 81 89>
  0 137: SEQUENCE {
    <02 81 81>
  3 129: . INTEGER    
       : . . 00 A8 D1 52 E7 2F 58 E8    ...R./X.
       : . . AE 62 F6 C5 77 2F 78 FA    .b..w/x.
       : . . 21 46 51 B5 EF A3 A4 4C    !FQ....L
       : . . E2 EE BD A0 80 46 B6 1D    .....F..
       : . . 66 37 01 82 3F 65 5D 3B    f7..?e];
       : . . 0B E7 11 08 05 94 40 CF    ......@.
       : . . F2 EF CC BF D9 1A F6 6F    .......o
       : . . 5B 0E 16 5F 85 C1 F3 D7    [.._....
       : . . 9D C8 C6 EF 41 09 7C A4    ....A.|.
       : . . C3 D5 CA 1C F0 80 E6 3F    .......?
       : . . BA D8 69 8F 67 67 70 FC    ..i.ggp.
       : . . EB 28 48 59 B3 4F F4 6B    .(HY.O.k
       : . . 38 E7 3B 94 0F 7C EF 2C    8.;..|.,
       : . . 02 41 8A 35 A8 72 DE DE    .A.5.r..
       : . . 78 DD ED 90 AD 5E 25 A3    x....^%.
       : . . 71 DD 59 95 1C 57 24 C8    q.Y..W$.
       : . . B5                         .
    <02 03>
135   3: . INTEGER 65537
       : . }

Решение

Решение очевидно, вместо выгрузки только данных открытого ключа

System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded()));

выгрузка всего объекта SubjectPublicKeyInfo:

System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getEncoded()));
...