JAR文件数字签名后在META-INF下产生两个文件,以JCE Unlimited 6为例,两个文件为JCE_RSA.SF文件和JCE_RSA.RSA文件。
jce_policy-6文件下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JCE_RSA.SF文件是对MANIFEST.MF文件的消息摘要;
JCE_RSA.RSA文件是对JCE_RSA.SF文件进行数字签名后的结果,签名文件内容遵循加密消息语法标准PKCS#7,按DER进行编码。
DER格式编码我们借助 bouncycastle来分析。比较有用的方法ASN1Dump.dumpAsString();
PKCS#7数据对应于org.bouncycastle.asn1.pkcs.SignedData类。
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16</artifactId> <version>1.46</version> </dependency>
X509证书可以用Windows的证书管理器(certmgr.msc)来查看证书细节,对照分析结果;
另外,也可以导出对应的证书进行分析。
import java.io.FileInputStream; import java.io.InputStream; import java.security.MessageDigest; import java.security.Security; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.util.ASN1Dump; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; public class DerDemo { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); InputStream in = new FileInputStream("test.cer"); byte[] content = new byte[in.available()]; in.read(content); in.close(); ASN1InputStream asnin = new ASN1InputStream(content); ASN1Sequence cert = (ASN1Sequence) asnin.readObject(); asnin.close(); //第一段:证书内容 ASN1Sequence tbsCertificate = (ASN1Sequence) cert.getObjectAt(0); System.out.println(new String(Hex.encode(tbsCertificate.getDEREncoded()))); for (int i = 0; i < tbsCertificate.size(); i++) { DEREncodable info = tbsCertificate.getObjectAt(i); System.out.println(new String(Hex.encode(info.getDERObject().getDEREncoded()))); System.out.println(ASN1Dump.dumpAsString(info, true)); } //第二段签名算法 ASN1Sequence signatureAlgorithm = (ASN1Sequence) cert.getObjectAt(1); System.out.println(new String(Hex.encode(signatureAlgorithm.getDEREncoded()))); System.out.println(ASN1Dump.dumpAsString(signatureAlgorithm, true)); //第三段证书签名 DEREncodable signatureValue = cert.getObjectAt(2); System.out.println(new String(Hex.encode(signatureValue.getDERObject().getDEREncoded()))); System.out.println(ASN1Dump.dumpAsString(signatureValue, true)); //证书指纹计算 MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(/*tbsCertificate.getDEREncoded()*/content); byte[] digest = md.digest(); System.out.println(new String(Hex.encode(digest))); } }
import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.RSAPublicKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; public class X509Demo { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); InputStream in = new FileInputStream("test.cer"); byte[] content = new byte[in.available()]; in.read(content); in.close(); CertificateFactory factory = CertificateFactory.getInstance("X.509"); System.out.println(factory.getProvider()); X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(content)); // 证书 System.out.println(cert); // 证书内容:也是被发行者签名的部分 System.out.println("证书内容:" + new String(Hex.encode(cert.getTBSCertificate()))); PublicKey publickey = cert.getPublicKey(); // 公钥DER编码(包含公钥算法、RSA模数和RSA公钥指数,windows证书查看器显示的公钥编码不含算法部分) System.out.println("公钥DER编码:" + new String(Hex.encode(publickey.getEncoded()))); RSAPublicKeySpec rsapublic = KeyFactory.getInstance("RSA").getKeySpec(publickey, RSAPublicKeySpec.class); System.out.println("RSA模数:" + rsapublic.getModulus()); System.out.println("RSA公钥指数:" + rsapublic.getPublicExponent()); } }
import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.math.BigInteger; import java.security.MessageDigest; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.pkcs.ContentInfo; import org.bouncycastle.asn1.pkcs.SignedData; import org.bouncycastle.asn1.pkcs.SignerInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; public class PKCS7Demo { static Map<String, String> OIDS = new HashMap<String, String>(); static { OIDS.put("1.3.14.3.2.26", "SHA1"); OIDS.put("1.2.840.113549.1.1.1", "RSA"); } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); InputStream in = new FileInputStream("JCE_RSA.RSA"); byte[] content = new byte[in.available()]; in.read(content); in.close(); ASN1InputStream asnin = new ASN1InputStream(content); ASN1Sequence asndata = (ASN1Sequence) asnin.readObject(); asnin.close(); DERTaggedObject tag0 = (DERTaggedObject) asndata.getObjectAt(1); SignedData pkcs7 = SignedData.getInstance(tag0.getObject()); System.out.println("版本:" + pkcs7.getVersion()); System.out.println("消息摘要算法:" + pkcs7.getDigestAlgorithms()); ContentInfo contentInfo = pkcs7.getContentInfo(); System.out.println("数据类型:" + contentInfo.getContentType()); System.out.println("数据正文:" + contentInfo.getContent()); for (ASN1Encodable certNode : pkcs7.getCertificates().toArray()) { System.out.println("证书:" + new String(Hex.encode(certNode.getDEREncoded()))); } System.out.println("作废证书:" + pkcs7.getCRLs()); for (ASN1Encodable signerNode : pkcs7.getSignerInfos().toArray()) { SignerInfo signer = SignerInfo.getInstance(signerNode); System.out.println("签名者信息:" + new String(Hex.encode(signerNode.getDEREncoded()))); System.out.println("版本:" + signer.getVersion()); System.out.println("证书发行者:" + signer.getIssuerAndSerialNumber().getName()); System.out.println("证书序列号:" + signer.getIssuerAndSerialNumber().getCertificateSerialNumber()); System.out.println("消息摘要算法:" + signer.getDigestAlgorithm().getAlgorithm()); System.out.println("签名时间:" + signer.getAuthenticatedAttributes()); System.out.println("签名算法:" + signer.getDigestEncryptionAlgorithm().getAlgorithm()); System.out.println("签名:" + signer.getEncryptedDigest()); } System.out.println("-----验证签名-----"); SignerInfo signer = SignerInfo.getInstance(pkcs7.getSignerInfos().getObjectAt(0)); X500Principal issuer = new X500Principal(signer.getIssuerAndSerialNumber().getName().getDEREncoded()); BigInteger sn = signer.getIssuerAndSerialNumber().getCertificateSerialNumber().getValue(); CertificateFactory factory = CertificateFactory.getInstance("X.509"); X509Certificate cert = null; for (ASN1Encodable certNode : pkcs7.getCertificates().toArray()) { X509Certificate acert = (X509Certificate) factory.generateCertificate(// new ByteArrayInputStream(certNode.getDEREncoded())); if (issuer.equals(acert.getIssuerX500Principal()) && sn.equals(acert.getSerialNumber())) { cert = acert; break; } } System.out.println("签名证书:" + cert.getIssuerX500Principal()); System.out.println("证书序号:" + cert.getSerialNumber()); String signerAlgorithm = OIDS.get(signer.getDigestEncryptionAlgorithm().getAlgorithm().getId()); System.out.println("签名算法:" + signerAlgorithm); Cipher cipher = Cipher.getInstance(signerAlgorithm); cipher.init(Cipher.DECRYPT_MODE, cert.getPublicKey()); cipher.update(signer.getEncryptedDigest().getOctets()); byte[] derDecrypt = cipher.doFinal(); System.out.println("DER格式的解密签名:" + new String(Hex.encode(derDecrypt))); asnin = new ASN1InputStream(derDecrypt); ASN1Sequence derDecryptSeq = (ASN1Sequence) asnin.readObject(); asnin.close(); System.out.println("解密签名中的消息摘要算法:" + ((ASN1Sequence) derDecryptSeq.getObjectAt(0)).getObjectAt(0)); String digestAlgorithm = OIDS.get(// ((ASN1ObjectIdentifier) // ((ASN1Sequence) derDecryptSeq.getObjectAt(0)).getObjectAt(0)// ).getId()// ); System.out.println("解密签名中的消息摘要算法::" + digestAlgorithm); byte[] decryptDigest = ((ASN1OctetString) derDecryptSeq.getObjectAt(1)).getOctets(); System.out.println("解密的消息摘要:" + new String(Hex.encode(decryptDigest))); in = new FileInputStream("JCE_RSA.SF"); byte[] raw = new byte[in.available()]; in.read(raw); in.close(); MessageDigest md = MessageDigest.getInstance(digestAlgorithm); md.update(raw); byte[] rawDigest = md.digest(); System.out.println("明文消息摘要:" + new String(Hex.encode(rawDigest))); System.out.println("验证通过:" + Arrays.equals(decryptDigest, rawDigest)); } }
相关推荐
本文将深入探讨APK签名的概念、过程以及如何通过示例进行签名操作。我们将参考文章《APK签名流程详解》(http://blog.csdn.net/diaoxuesong/article/details/78668659)来展开讨论。 首先,我们要理解APK签名的含义...
- PDF签名和验证:PDFBox支持对PDF文档进行数字签名和验证,确保文档未被篡改。 5. 示例代码: ```java import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; public ...
2. **icepdf-extra.jar**: 该文件包含了IcePDF的扩展功能,如表单处理、数字签名验证等。这些功能可能不是所有应用都需要,但提供了更全面的PDF处理能力。 3. **icepdf-pro.jar**: 这可能是IcePDF的专业版或增强版...
5. **序列化和反序列化**:`poi-ooxml-security.jar` 提供了处理OOXML文件的安全性和数字签名相关功能。 6. **测试和示例**:虽然在实际开发中通常不会直接引用,但`poi-tests.jar` 包含了POI项目的测试类,可帮助...
5. **签名与安全**:PDFBox提供了对PDF数字签名的支持,可以验证签名的有效性,或者为PDF添加新的签名。`PDSignature`和`SignatureInterface`是处理签名的核心接口。 `fontbox-2.0.9.jar`则是PDFBox的字体处理模块...
【华信短信接口Java示例jar包.rar】是一款由华信科技提供的用于短信接口调用的Java库。这个压缩包包含了一个名为`lib`的文件夹,通常在Java开发中,`lib`文件夹用于存放项目的依赖库。在这个案例中,`lib`可能包含了...
以下是对标题“applet签名方法”以及描述“applet签名 jar签名工具”的详细解析,涵盖相关知识点: ### Applet签名与安全性 Applet是一种小型应用程序,通常嵌入在网页中运行于用户的浏览器上,它通过Java虚拟机...
activation.jar则包含了对MIME类型数据的解析和生成能力。在JavaMail中,当处理复杂的邮件,比如带有附件或嵌入图片的邮件时,就需要JAF来解析这些MIME类型的结构。JAF定义了一套标准的接口,使得应用程序能够识别并...
另外,"iText攻略.pdf"可能是关于iText库的详细教程或者参考指南,其中可能涵盖了更多高级特性和用法,如自定义字体、数字签名、PDF/A合规性、XML到PDF转换等。这是一份宝贵的资源,可以帮助开发者深入理解并熟练...
值得注意的是,虽然`pdf-renderer.jar`提供了一套较为全面的PDF处理功能,但它可能并不支持所有PDF的高级特性,如加密、数字签名等。对于这些复杂需求,开发者可能需要寻找更专业的PDF处理库,如Apache PDFBox、...
【dex2jar 2.0】是一款针对Android应用的反编译工具,它主要用于将APK文件中的.dex(Dalvik Executable)文件转换为.jar格式的Java字节码文件,以便开发者可以查看、分析或者逆向工程Android应用程序的源代码。...
- **安全性**:JAR文件可以通过数字签名增加安全性,确保代码的来源可信且未被篡改。 - **减少下载时间**:通过将多个文件打包进一个JAR文件,可以显著减少网络传输的时间。 - **压缩**:JAR文件支持压缩功能,有助...
- `bcprov-jdk15on.jar`:这是Bouncy Castle加密库的一个版本,用于支持PDF的安全功能,如数字签名和加密。 - `fontbox.jar`:iText的字体处理模块,用于处理PDF中的字体和字符编码。 - `pdfbox.jar`:虽然不是iText...
Java解析APK所需Jar包是Java开发者在处理Android应用程序(APK)时不可或缺的工具。APK文件本质上是包含Android应用所有组件、资源和配置的压缩格式,它使用Dalvik或ART虚拟机运行。要对APK进行解析,通常是为了提取...
iText还支持添加书签、超链接、数字签名等功能,增强了PDF报表的交互性和安全性。 3. **poi-3.0.1-FINAL-20070705.jar**:Apache POI是一个用于处理Microsoft Office格式文件(如Excel)的Java库。在JasperReport中...
此外,还可以创建和处理PDF表单,提取和修改文档元数据,甚至进行数字签名和安全加密。 6. 开源许可证:iText遵循AGPL(GNU Affero General Public License)许可证,这意味着任何使用iText的项目,如果涉及到...
JAR文件可以被Java虚拟机(JVM)直接执行,也可以包含清单文件、数字签名等,以支持安全性和版本控制。 在Delphi环境中,开发者使用Pascal语言编写代码。Pascal是一种强大的、结构化的编程语言,拥有丰富的内置类型...
- 使用工具如`Apktool`,它能够解析APK的资源文件和二进制XML,将其转换为人类可读的格式。首先,你需要下载并安装Apktool,然后运行相应的命令来解包APK。 - 命令示例:`apktool d yourapk.apk -o output_...
此外,它还支持表单处理、数字签名、PDF/A合规性等功能,为PDF文档的创建提供了全面的支持。5.0.1版本是一个较早的版本,但仍然广泛使用,因为它稳定且功能丰富。 iTextAsian.jar是iText库的扩展,专门针对东亚语言...