`
sswh
  • 浏览: 163720 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

JAR数字签名格式解析示例

    博客分类:
  • java
 
阅读更多

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

 

0
1
分享到:
评论

相关推荐

    APK签名解析示例

    本文将深入探讨APK签名的概念、过程以及如何通过示例进行签名操作。我们将参考文章《APK签名流程详解》(http://blog.csdn.net/diaoxuesong/article/details/78668659)来展开讨论。 首先,我们要理解APK签名的含义...

    pdfbox所需jar包

    - PDF签名和验证:PDFBox支持对PDF文档进行数字签名和验证,确保文档未被篡改。 5. 示例代码: ```java import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; public ...

    icepdf图片查看依赖jar和示例代码

    2. **icepdf-extra.jar**: 该文件包含了IcePDF的扩展功能,如表单处理、数字签名验证等。这些功能可能不是所有应用都需要,但提供了更全面的PDF处理能力。 3. **icepdf-pro.jar**: 这可能是IcePDF的专业版或增强版...

    POI poi相关所有jar包 poi jar包 poi最全jar包

    5. **序列化和反序列化**:`poi-ooxml-security.jar` 提供了处理OOXML文件的安全性和数字签名相关功能。 6. **测试和示例**:虽然在实际开发中通常不会直接引用,但`poi-tests.jar` 包含了POI项目的测试类,可帮助...

    pdfbox-2.0.9.jar和fontbox-2.0.9.jar等,java解析pdf所有相关jar包

    5. **签名与安全**:PDFBox提供了对PDF数字签名的支持,可以验证签名的有效性,或者为PDF添加新的签名。`PDSignature`和`SignatureInterface`是处理签名的核心接口。 `fontbox-2.0.9.jar`则是PDFBox的字体处理模块...

    华信短信接口Java示例jar包.rar

    【华信短信接口Java示例jar包.rar】是一款由华信科技提供的用于短信接口调用的Java库。这个压缩包包含了一个名为`lib`的文件夹,通常在Java开发中,`lib`文件夹用于存放项目的依赖库。在这个案例中,`lib`可能包含了...

    applet签名 方法

    以下是对标题“applet签名方法”以及描述“applet签名 jar签名工具”的详细解析,涵盖相关知识点: ### Applet签名与安全性 Applet是一种小型应用程序,通常嵌入在网页中运行于用户的浏览器上,它通过Java虚拟机...

    mail.jar+activation.jar

    activation.jar则包含了对MIME类型数据的解析和生成能力。在JavaMail中,当处理复杂的邮件,比如带有附件或嵌入图片的邮件时,就需要JAF来解析这些MIME类型的结构。JAF定义了一套标准的接口,使得应用程序能够识别并...

    itext.jar 详细介绍 包含大量例子

    另外,"iText攻略.pdf"可能是关于iText库的详细教程或者参考指南,其中可能涵盖了更多高级特性和用法,如自定义字体、数字签名、PDF/A合规性、XML到PDF转换等。这是一份宝贵的资源,可以帮助开发者深入理解并熟练...

    pdf-renderer.jar

    值得注意的是,虽然`pdf-renderer.jar`提供了一套较为全面的PDF处理功能,但它可能并不支持所有PDF的高级特性,如加密、数字签名等。对于这些复杂需求,开发者可能需要寻找更专业的PDF处理库,如Apache PDFBox、...

    dex2jar-2.0.zip

    【dex2jar 2.0】是一款针对Android应用的反编译工具,它主要用于将APK文件中的.dex(Dalvik Executable)文件转换为.jar格式的Java字节码文件,以便开发者可以查看、分析或者逆向工程Android应用程序的源代码。...

    JAR命令详解

    - **安全性**:JAR文件可以通过数字签名增加安全性,确保代码的来源可信且未被篡改。 - **减少下载时间**:通过将多个文件打包进一个JAR文件,可以显著减少网络传输的时间。 - **压缩**:JAR文件支持压缩功能,有助...

    操作PDF的jar包

    - `bcprov-jdk15on.jar`:这是Bouncy Castle加密库的一个版本,用于支持PDF的安全功能,如数字签名和加密。 - `fontbox.jar`:iText的字体处理模块,用于处理PDF中的字体和字符编码。 - `pdfbox.jar`:虽然不是iText...

    Java解析apk所需jar包

    Java解析APK所需Jar包是Java开发者在处理Android应用程序(APK)时不可或缺的工具。APK文件本质上是包含Android应用所有组件、资源和配置的压缩格式,它使用Dalvik或ART虚拟机运行。要对APK进行解析,通常是为了提取...

    jasper report用到的5个jar包

    iText还支持添加书签、超链接、数字签名等功能,增强了PDF报表的交互性和安全性。 3. **poi-3.0.1-FINAL-20070705.jar**:Apache POI是一个用于处理Microsoft Office格式文件(如Excel)的Java库。在JasperReport中...

    iText-5.0.2 JAR包

    此外,还可以创建和处理PDF表单,提取和修改文档元数据,甚至进行数字签名和安全加密。 6. 开源许可证:iText遵循AGPL(GNU Affero General Public License)许可证,这意味着任何使用iText的项目,如果涉及到...

    JAVA JAR 转DELPHI源码 PAS

    JAR文件可以被Java虚拟机(JVM)直接执行,也可以包含清单文件、数字签名等,以支持安全性和版本控制。 在Delphi环境中,开发者使用Pascal语言编写代码。Pascal是一种强大的、结构化的编程语言,拥有丰富的内置类型...

    Android反编译并签名打包需要的文件

    - 使用工具如`Apktool`,它能够解析APK的资源文件和二进制XML,将其转换为人类可读的格式。首先,你需要下载并安装Apktool,然后运行相应的命令来解包APK。 - 命令示例:`apktool d yourapk.apk -o output_...

    itext+jar+文档

    此外,它还支持表单处理、数字签名、PDF/A合规性等功能,为PDF文档的创建提供了全面的支持。5.0.1版本是一个较早的版本,但仍然广泛使用,因为它稳定且功能丰富。 iTextAsian.jar是iText库的扩展,专门针对东亚语言...

Global site tag (gtag.js) - Google Analytics