对CERT.RSA进行详细解析

本文介绍了一种通过Java代码从签名后的APK包中提取并解析公钥的方法。利用PKCS7处理CERT.RSA文件,并展示如何获取公钥、发行人及主题详情,同时提供了完整的十六进制编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
注: App解析得到的文件时十六进制显示的,而Java解析得到的结果却是十进制显示的。
 
附件中CERT.RSA是签名后的apk包解压在META-INF目录下签名文件
 
获取公钥可以使用java工程代码实现,见附件(Test.java)实现代码如下:
 
package ceshi;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;
 
import sun.misc.BASE64Encoder;
import sun.security.pkcs.PKCS7;
 
 
public class Test {
 
public static void main(String[] args) throws CertificateException,
IOException {
 
PublicKey pk;
FileInputStream fis = new FileInputStream("E:/CERT.RSA");
PKCS7 pkcs7 = new PKCS7(fis);
X509Certificate publicKey = pkcs7.getCertificates()[0];
pk = publicKey.getPublicKey();
 
BASE64Encoder bse = new BASE64Encoder();
System.out.println("pk:" + bse.encode(pk.getEncoded()));
 
byte[] ecode = pk.getEncoded();
System.out.println("issuer1:" + publicKey.getIssuerDN());
System.out.println("subject2:" + publicKey.getSubjectDN());
System.out.println(publicKey.getPublicKey());
 
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < ecode.length; i++) {
if ((ecode[i] & 0xff) < 0x10) {// 0~F前面不零
hexString.append("0");
}
hexString.append(Integer.toHexString(0xFF & ecode[i]));
hexString.append(":");
}
 
System.out.println(hexString.toString());
 
输出的结果:
 
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg3MUZxiXd+88iR8l95/SSr1lDISB3QWa
zypMKzgD7mPF4NHaVeOo6bgjsWk5YPy0mp+WfAH3NHIwltHCnqwOLb1JAdhJFk8QVcnda5i3js+K
76ZaIyxYibKkW6HHOMUDLaiA6Q65TCpLWQWjAofXZ79jjAoKSWcUOmVyvxJoXUCRt3cjD44K4iaR
1D3so4QTCmwV0LSUd/eqztnuVyO/h+YavLz4CYrbNezfWX9qhQS7D8HDuKc2AVX87tHMdEO92XGq
qydGR8XsaWV/fdQW3AqEh0s2LYiP5sQssU0339kD8AMhAIOrRFTR+QPQK7y+PKVTpQ63+ZYocVKZ
b193iQIDAQAB
issuer1:OU=hengbao
subject2:OU=hengbao
Sun RSA public key, 2048 bits
  modulus: 16593965864720895347096434199492838173371792286694613986873147773534355257208465003725167605143928942119164172396315316414706451899739004077145074314922253452766715261486558090967339242546324731392434573627827874949059378931716791574127022949320063683355579876895800702247260749515558149736409900183412762117231397532151334490980004096672565724638612858088772776008860162173946450836266510994531532667269288112245822936219200531988158667119337184317889244667597229190157140295298800606336441116787571541040036467536969259272887118029370150852090534562510684935539403389718093619240221037937029257859189546238112397193
  public exponent: 65537
30:82:01:22:30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:00:03:82:01:0f:00:30:82:01:0a:02:82:01:01:00:83:73:14:67:18:97:77:ef:3c:89:1f:25:f7:9f:d2:4a:bd:65:0c:84:81:dd:05:9a:cf:2a:4c:2b:38:03:ee:63:c5:e0:d1:da:55:e3:a8:e9:b8:23:b1:69:39:60:fc:b4:9a:9f:96:7c:01:f7:34:72:30:96:d1:c2:9e:ac:0e:2d:bd:49:01:d8:49:16:4f:10:55:c9:dd:6b:98:b7:8e:cf:8a:ef:a6:5a:23:2c:58:89:b2:a4:5b:a1:c7:38:c5:03:2d:a8:80:e9:0e:b9:4c:2a:4b:59:05:a3:02:87:d7:67:bf:63:8c:0a:0a:49:67:14:3a:65:72:bf:12:68:5d:40:91:b7:77:23:0f:8e:0a:e2:26:91:d4:3d:ec:a3:84:13:0a:6c:15:d0:b4:94:77:f7:aa:ce:d9:ee:57:23:bf:87:e6:1a:bc:bc:f8:09:8a:db:35:ec:df:59:7f:6a:85:04:bb:0f:c1:c3:b8:a7:36:01:55:fc:ee:d1:cc:74:43:bd:d9:71:aa:ab:27:46:47:c5:ec:69:65:7f:7d:d4:16:dc:0a:84:87:4b:36:2d:88:8f:e6:c4:2c:b1:4d:37:df:d9:03:f0:03:21:00:83:ab:44:54:d1:f9:03:d0:2b:bc:be:3c:a5:53:a5:0e:b7:f9:96:28:71:52:99:6f:5f:77:89:02:03:01:00:01:
 
 
ASN.1编码的十六进制描述:  


30:82:01:22:   //290个字节


30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:


00:03:82:01:0f:


00:30:82:01:0a: //266个字节


02:82:01:01:
//Modulus (2048 bit)   128位便是rsa公钥的N值
00:83:73:14:67:18:97:77:ef:3c:89:1f:25:f7:9f:
d2:4a:bd:65:0c:84:81:dd:05:9a:cf:2a:4c:2b:38:
03:ee:63:c5:e0:d1:da:55:e3:a8:e9:b8:23:b1:69:
39:60:fc:b4:9a:9f:96:7c:01:f7:34:72:30:96:d1:
c2:9e:ac:0e:2d:bd:49:01:d8:49:16:4f:10:55:c9:
dd:6b:98:b7:8e:cf:8a:ef:a6:5a:23:2c:58:89:b2:
a4:5b:a1:c7:38:c5:03:2d:a8:80:e9:0e:b9:4c:2a:
4b:59:05:a3:02:87:d7:67:bf:63:8c:0a:0a:49:67:
14:3a:65:72:bf:12:68:5d:40:91:b7:77:23:0f:8e:
0a:e2:26:91:d4:3d:ec:a3:84:13:0a:6c:15:d0:b4:
94:77:f7:aa:ce:d9:ee:57:23:bf:87:e6:1a:bc:bc:
f8:09:8a:db:35:ec:df:59:7f:6a:85:04:bb:0f:c1:
c3:b8:a7:36:01:55:fc:ee:d1:cc:74:43:bd:d9:71:
aa:ab:27:46:47:c5:ec:69:65:7f:7d:d4:16:dc:0a:
84:87:4b:36:2d:88:8f:e6:c4:2c:b1:4d:37:df:d9:
03:f0:03:21:00:83:ab:44:54:d1:f9:03:d0:2b:bc:
be:3c:a5:53:a5:0e:b7:f9:96:28:71:52:99:6f:5f:
77:89:


02:03:


 01:00:01  rsa公钥的E值   Exponent: 65537 (0x10001)
 

<think>嗯,用户问的是关于RSA证书公钥参数通过ASN.1如何解析的问题。首先,我需要回顾一下RSA公钥的结构和ASN.1的相关知识。RSA的公钥通常包含模数(n)和公开指数(e),这些参数在X.509证书中是以ASN.1 DER编码格式存储的。 接下来,用户可能是在处理证书解析,或者编写解析工具时需要了解具体的结构。我需要先确认他们是否了解ASN.1的基本概念,可能需要先简单介绍一下ASN.1和DER编码。不过用户直接询问解析方法,可能已经有基础,所以应该直接深入结构。 RSA公钥在证书的SubjectPublicKeyInfo字段中。这个结构包含算法标识符和公钥的位串。算法标识符是rsaEncryption(OID 1.2.840.113549.1.1.1),而公钥位串本身又是一个ASN.1序列,包含模数n和指数e,都是整数。 要具体解析的话,可能需要分步骤说明。例如,从DER编码开始,如何拆解每一层结构。可能需要提到使用工具如OpenSSL的asn1parse,或者手动解析各层的TLV(类型、长度、值)结构。 另外,需要注意整数的大端表示,以及可能的填充问题,比如模数前面可能补零的情况。还有可能用户会遇到解析错误,例如长度不正确或者标签不符的情况,如何处理这些异常。 可能还需要举一个例子,比如具体的DER编码字节序列,展示如何逐步分解出n和e。或者给出一个ASN.1的结构图,帮助理解嵌套层次。 同时,用户可能需要知道如何在编程语言中实现解析,比如使用Python的asn1crypto库或者cryptography库,或者用Java的Bouncy Castle库。这时候需要说明库函数的使用方法,或者手动解析的步骤。 另外,可能会涉及到Base64解码的问题,因为证书中的公钥通常是PEM格式,需要先转换到DER。这也是解析过程中的一个步骤。 最后,总结一下解析的关键点:找到SubjectPublicKeyInfo,提取算法OID,确认是RSA后,解析BIT STRING中的ASN.1序列,分解出n和e。同时注意各种编码细节,确保正确读取长度和数值。</think>RSA 证书的公钥参数通过 ASN.1(Abstract Syntax Notation One)进行结构化编码,通常遵循 X.509 标准和 PKCS#1 规范。以下是解析 RSA 公钥参数的步骤和关键结构: --- ### **1. ASN.1 基本结构** RSA 公钥在 X.509 证书中存储在 `SubjectPublicKeyInfo` 字段中,其 ASN.1 结构如下: ```asn1 SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, -- 标识算法(如 RSA 的 OID 是 1.2.840.113549.1.1.1) parameters ANY OPTIONAL } ``` --- ### **2. 解析公钥的 BIT STRING** `subjectPublicKey` 是一个 BIT STRING,其实际内容是一个嵌套的 ASN.1 结构(根据 PKCS#1): ```asn1 RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- 模数 n(大整数) publicExponent INTEGER -- 公开指数 e(通常为 65537) } ``` --- ### **3. 具体解析步骤** 假设已从证书中提取出公钥的二进制 DER 编码数据,解析流程如下: #### **步骤 1:解析外层 SubjectPublicKeyInfo** - **类型标签**:`SEQUENCE`(0x30) - 包含两个字段: 1. **AlgorithmIdentifier**:标识算法为 RSA(OID `1.2.840.113549.1.1.1`)。 2. **subjectPublicKey**:BIT STRING(类型 `0x03`),需进一步解析。 #### **步骤 2:解析 BIT STRING 内容** - 移除 BIT STRING 的头部标签和长度字段。 - 剩余数据是 `RSAPublicKey` 的 DER 编码,结构为 `SEQUENCE`。 #### **步骤 3:解析 RSAPublicKey** - **类型标签**:`SEQUENCE`(0x30) - 包含两个 INTEGER 字段: 1. **modulus (n)**:大端表示的整数,通常是 2048/4096 位。 2. **publicExponent (e)**:常见值为 `0x010001`(即 65537)。 --- ### **4. 示例解析(简化的字节流)** 假设 DER 编码的 BIT STRING 内容为以下十六进制(仅为示例): ``` 30 82 01 0A 02 82 01 01 00 AB CD ... (modulus) ... 02 03 01 00 01 ``` - **分解**: - `30`: SEQUENCE 标签。 - `82 01 0A`: 长度字段(表示后续数据长度)。 - `02 82 01 01`: INTEGER 标签(0x02),长度 0x0101 字节,后跟模数 `n`。 - `02 03 01 00 01`: INTEGER 标签(0x02),长度 0x03 字节,指数 `e = 0x010001`。 --- ### **5. 工具辅助解析** - **OpenSSL**:使用命令解析证书公钥: ```bash openssl asn1parse -in certificate.pem -i -strparse 19 # 需定位到 BIT STRING 的位置 ``` - **Python 库**:如 `asn1crypto` 或 `cryptography`: ```python from cryptography.x509 import load_pem_x509_certificate cert = load_pem_x509_certificate(pem_data) public_key = cert.public_key() n = public_key.public_numbers().n e = public_key.public_numbers().e ``` --- ### **6. 注意事项** - **编码规则**:ASN.1 使用 DER(Distinguished Encoding Rules),需严格处理长度和标签。 - **大整数表示**:INTEGER 类型以大端格式存储,且需处理可能的前导零。 - **嵌套结构**:注意逐层解析 SEQUENCE 和 BIT STRING。 --- 通过以上步骤,可以准确提取 RSA 公钥的模数(n)和公开指数(e),从而用于加密或验证签名。实际应用中建议使用成熟的密码学库,避免手动解析错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值