无法在Java中获得公钥显示以匹配Adobe中的公钥显示 [英] can't get public key display in java to match those in Adobe
问题描述
我使用证书签署了pdf.在Java中,我处理pdf并提取证书详细信息.我将输出与该文档在Adobe中显示的证书详细信息进行比较.对于SerialNumber,我可以使它们看起来相同,但对于公共密钥则不能.任何帮助表示赞赏!
I sign a pdf using a certificate. In java I process the pdf and extract the certificate details. I compare the output against the certificate details shown in Adobe for that document. For SerialNumber I was able to make them look the same, but not for public key. Any help appreciated!
我调试了代码,尝试使用Hex.toHexString进行转换,并在stackoverflow中进行了谷歌搜索.但是没有运气
I debugged the code, tried to convert using Hex.toHexString, googled in stackoverflow. But no luck
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中,公钥显示如下:
In Adobe the public key is shown like this:
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在Java中为BigInteger,在Windows/Mac/Adobe中为十六进制值 它显示如下:
SerialNumber is BigInteger in java and hex value in Windows/Mac/Adobe it is shown like this:
03818d0030818902818100a8d152e72f58e8ae62f6c5772f78fa214651b5efa3a44ce2eebda08046b61d663701823f655d3b0be71108059440cff2efccbfd91af66f5b0e165f85c1f3d79dc8c6ef41097ca4c3d5ca1cf080e63fbad8698f676770fceb284859b34ff46b38e73b940f7cef2c02418a35a872dede78dded90ad5e25a371dd59951c5724c8b50203010001
对于SerialNumber,它可以正常工作. Java代码:
For SerialNumber it works fine. Java code:
System.out.println(certificateHolder.getSerialNumber().toString(16));
Java输出:
b27f048515c4f8e4
b27f048515c4f8e4
Adobe输出:
Adobe output:
00 B2 7F 04 85 15 C4 F8 E4
00 B2 7F 04 85 15 C4 F8 E4
非常感谢!
推荐答案
问题
区别在于Adobe显示完整的SubjectPublicKeyInfo
对象的十六进制转储(包括算法信息和密钥值的公钥),而您的代码仅转储RSAPublicKey
(密钥本身).
The Issue
The difference is that Adobe presents the hex dump of the complete SubjectPublicKeyInfo
object (the public key including the algorithm information and the key value) while your code only dumps the RSAPublicKey
(the key itself).
通过查看有关对象的ASN.1定义和两个数组的ASN.1转储,您可以更清楚地看到这一点:
You can see this clearer by looking at the ASN.1 definitions of the objects in question and an ASN.1 dump of both arrays:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
SubjectPublicKeyInfo
的Adobe转储
Adobe's Dump of the 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
转储
Your Dump of the 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
: . }
解决方案
解决方案很明显,而不是仅转储公钥数据
The solution
The solution is obvious, instead of dumping the public key data only
System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded()));
转储整个SubjectPublicKeyInfo
对象:
System.out.println(Hex.toHexString(certificateHolder.getSubjectPublicKeyInfo().getEncoded()));
这篇关于无法在Java中获得公钥显示以匹配Adobe中的公钥显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!