pyasn1及pyasn1-modules解析DER格式证书、私钥及公钥
PEM转DER
DER格式是证书、私钥、公钥等按ASN.1编码后序列化生成的二进制格式。
我们可以从PEM格式中得到DER格式:例如:
import base64
# PEM转DER格式
def pem2der(pem: bytes) -> bytes:
return base64.b64decode(b''.join(pem.strip().split(b'\n')[1:-1]))
# 使用方法
pem = b"""-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILb9XVRPCaPgtmBLTfusYmTDBzACWEIMP7G47ttUSgcZoAoGCCqGSM49
AwEHoUQDQgAEIL5WxHjk/yCczEPlMxcLSSYqsOs4uhGzlq0FQnIx4uJrvDaIq6ht
+tdT2VAnfDTNbyhkJWWfCCpe9meVIQj6hQ==
-----END EC PRIVATE KEY-----"""
der = pem2der(pem)
pyasn1-modules介绍
我们可以使用三方包pyasn1结合pyasn1-modules来解析DER格式的证书、私钥或公钥
pyasn1-modules中包含了各种RFC格式标准,常见对应关系为:
名称 | 对应PEM标识 | 对应pyasn1-modules模块 |
---|---|---|
X.509证书证书 | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- |
rfc5280.Certificate() |
PKCS#1格式RSA私钥 | -----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY----- |
rfc2437.RSAPrivateKey() |
PKCS#13格式EC私钥 | -----BEGIN EC PRIVATE KEY---- - ... -----END EC PRIVATE KEY----- |
rfc5915.ECPrivateKey() |
PKCS#8格式私钥 | -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- |
rfc5208.PrivateKeyInfo() |
PKCS#1格式RSA公钥 | -----BEGIN RSA PUBLIC KEY---- - ... -----END RSA PUBLIC KEY----- |
rfc2437.RSAPublicKey() |
X.509证书扩展标准公钥 | -----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY----- |
rfc5280.SubjectPublicKeyInfo() |
安装pyasn1及pyasn1-modules:
pip install pyasn1 pyasn1-modules
pyasn1解析X.509证书
import base64
from pyasn1_modules import rfc5280
from pyasn1.codec.der import decoder
cert_pem = b"""-----BEGIN CERTIFICATE-----
MIICeDCCAh6gAwIBAgIDCQiGMAoGCCqGSM49BAMCMIGKMQswCQYDVQQGEwJDTjEQ
MA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEfMB0GA1UEChMWd3gt
b3JnMS5jaGFpbm1ha2VyLm9yZzESMBAGA1UECxMJcm9vdC1jZXJ0MSIwIAYDVQQD
ExljYS53eC1vcmcxLmNoYWlubWFrZXIub3JnMB4XDTIyMDYxMDA3MTczNloXDTI3
MDYwOTA3MTczNlowgZExCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAw
DgYDVQQHEwdCZWlqaW5nMR8wHQYDVQQKExZ3eC1vcmcxLmNoYWlubWFrZXIub3Jn
MQ8wDQYDVQQLEwZjbGllbnQxLDAqBgNVBAMTI2NsaWVudDEuc2lnbi53eC1vcmcx
LmNoYWlubWFrZXIub3JnMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKQK43j7b
gR5l7w6lksM39GPKouVG1APdU2dRSElnGleAwSE6462wcCec/z/X9oLltEH+N7J+
PU6QqNlfdBhdHaNqMGgwDgYDVR0PAQH/BAQDAgbAMCkGA1UdDgQiBCAQI/im5dGN
IruXfy+9prPBpczEAv2pS33Sgf+XZdr8azArBgNVHSMEJDAigCBRi9kSGe5qMbTj
pim5j+50x7ezC5oDQVzXHSLlNIF6czAKBggqhkjOPQQDAgNIADBFAiEApxk8gCH0
uvnkjjO+uI80fWUBmHIkJ2GRIUD1tvyf0FACIDhPPc0j2DjsAg61hlD5682/jwqV
ne776zZIIkR4uZ2r
-----END CERTIFICATE-----"""
cert_der = base64.b64decode(b''.join(cert_pem.strip().split(b'\n')[1:-1]))
cert_asn1, _ = decoder.decode(cert_der, asn1Spec=rfc5280.Certificate())
print(cert_asn1)
运行输出如下:
Certificate:
tbsCertificate=TBSCertificate:
version=v3
serialNumber=592006
signature=AlgorithmIdentifier:
algorithm=1.2.840.10045.4.3.2
issuer=Name:
rdnSequence=RDNSequence:
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.6
value=0x1302434e
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.8
value=0x13074265696a696e67
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.7
value=0x13074265696a696e67
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.10
value=0x131677782d6f7267312e636861696e6d616b65722e6f7267
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.11
value=0x1309726f6f742d63657274
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.3
value=0x131963612e77782d6f7267312e636861696e6d616b65722e6f7267
validity=Validity:
notBefore=Time:
utcTime=220610071736Z
notAfter=Time:
utcTime=270609071736Z
subject=Name:
rdnSequence=RDNSequence:
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.6
value=0x1302434e
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.8
value=0x13074265696a696e67
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.7
value=0x13074265696a696e67
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.10
value=0x131677782d6f7267312e636861696e6d616b65722e6f7267
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.11
value=0x1306636c69656e74
RelativeDistinguishedName:
AttributeTypeAndValue:
type=2.5.4.3
value=0x1323636c69656e74312e7369676e2e77782d6f7267312e636861696e6d616b65722e6f7267
subjectPublicKeyInfo=SubjectPublicKeyInfo:
algorithm=AlgorithmIdentifier:
algorithm=1.2.840.10045.2.1
parameters=0x06082a8648ce3d030107
subjectPublicKey=55779132873014641108130266260472839497975468217640857856750433988938929633576622657740176654462346264703467078471547264813561565822596758191598956130622749
extensions=Extensions:
Extension:
extnID=2.5.29.15
critical=True
extnValue=0x030206c0
Extension:
extnID=2.5.29.14
extnValue=0x04201023f8a6e5d18d22bb977f2fbda6b3c1a5ccc402fda94b7dd281ff9765dafc6b
Extension:
extnID=2.5.29.35
extnValue=0x30228020518bd91219ee6a31b4e3a629b98fee74c7b7b30b9a03415cd71d22e534817a73
signatureAlgorithm=AlgorithmIdentifier:
algorithm=1.2.840.10045.4.3.2
signature=182167519797223616245780807420810240526974425761200836157439988500509352020551959734678505313271993580132937884358276032972632671108045842029750887163059365127858740108715
pyasn1解析PCKS#1-RSA私钥
import base64
from pyasn1_modules import rfc2437
from pyasn1.codec.der import decoder
private_key_pem = b"""-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA57b1SHQKXl47qa/35WaX3UNI/UTBIPxcJjJIW84hYBOMDWGw
BQHE1n+l+b9FctQXRIpB/DBPasRvg8YfUSN05Rexv3/s+Z/nIXXlVaatwBV+tCb9
7iqKurYJpMuxJmOhe68ENgFGZkUfAMvByHfPVfzKg2y8gZmsxyfPnZ0dPZpm/xSz
dceNI49iWLFvCARkKEjuO0rjL8tqk3cxY5uTDSov68UEbyhQOYTodLlByY9uwzQO
F74TUWV7ZiEfDoFwaiJi7Q+60wQm9oPS/XeoE97IfA9tEKe7kKmBQZxoI8vyStPU
Q1WEFn+wtcB67pS9dEpTRWBgmQYtLtkq4lcHRQIDAQABAoIBAQCcJrKzaefW4oAo
gTp4sKOk64QTkbLozMg4wWf73jSlr2aRWgSpyyBgQNOUM67UjFNF0DpZfiD23Xwc
/HX8Uv2iqU4StF35dyXmabHr/5BVwuaI90Hmr2qgGq7zDIXMThXz6OTYlBFiODCF
c8qakwr5cory+GMsn2hNKeoC2G9tJAirf+5Bj5xDx5JTwtggUr5NUR37fyeAa2Wh
atqY5cb2k3MEqr6p1zZZ5GLNADvgzXWK+XeDNA/x8AqwHM6ETpljwBd8Rx5EHwjd
6tj7K1oBW43s5lMBe4K0cOgLAGpK48Ck0DZ++8CovqQSQUe7OsIY1MX5ZSrwpKuh
vyjiDMehAoGBAP7rtxozJkhXP899UZsB9q5QuRMLTZruFNFEgjRRsEc+Qr6O25qf
cEzE3yO2EpAmSMS570eK596SvjO6Jd1GM/e/AUnGlOJ3fEOt58ICNWV9V3RdhFwi
Nmmqj3yXhiSsQU695+1NwFViajaXTDjXP/LskJP2hLpolIrkwOanKryZAoGBAOiy
F4zP/RdbhM1CjkyJXHaG8Uru/jimOuKSHhpHnANeNQrMylM4IYH33/GFIIS7hsJg
9ohH5XMnslp1CjbEvjDXuurJx5TFBMFCPy3LppQDKZBLnWyNGBsSDu6/oq+/ozIA
KVTEGlQvqZDQCaxXwvxHFB1w+xlHXAdsY0TVL7+NAoGAVXwEHeQTLWUcv969c+aX
q2LkfU9oCdFW58o6g4L1Qx7M0Qwk9lgLF6NZVKdk2DQOaPIVHH+nO8snvz7oHajC
Go1RyESwfrUk1alGs5d8AnmizyHhFehfKNYKYfSKBlhBWj9yu/A71CY5ie74n4MH
LdZIsWWUotIZJe6KBY7/VNkCgYEAscHaW6dHH+C5wlNlgPItwB21lhib+4qA0TPt
6wVpGOmOe4GVzZzDfBVu7YFVJhBbEYIg0lqZ3S4mARQHiW8iGw2xrEoYPH2E9F03
BjTcO5Vu2tvollPyZjuVTKz4CmnKsReOe0KTGlyOnCFQQmeIfE+P/i2go97vXnxe
GOcCYsECgYEAhB0srmyo49HErxPBzVKN1bVz1GczVtUUVx0tJLhvdM43vTZeXMnl
EstwZWXf3UB5FRsmHSZoBhRmkNzFQ54pM/hlGaGrirgYowMfe5j0Zd0jZBQqpApW
YET1/PeQXaF1V9k8wmmZHuLdgo8tw90x0GVCcmxs3UHlGsEJ0ggnCOk=
-----END RSA PRIVATE KEY-----"""
private_key_der = base64.b64decode(b"".join(private_key_pem.strip().split(b"\n")[1:-1]))
private_key_asn1, _ = decoder.decode(private_key_der, asn1Spec=rfc2437.RSAPrivateKey())
print(private_key_asn1)
运行输出如下:
RSAPrivateKey:
version=0
modulus=29251268466961495515231372053385573035557384464172735010401614432483825817069065134216395234281996254699424021256355341131983291857177682722346666485636608978170690388127041330853005158984937654841701450083007946451017278020077371099290901323186077610409089863566614014876287906018236397588473477911080707564663343710640573037793994443721208516459214603050807450018876235614286592128971472399939405937824179326202712715422179853542382632375121164999622864151600512254702385441589120043203914553310287472567550480071947761578908479979477695682249475708285623845365952983861483247840983904791189780312972719365050271557
publicExponent=65537
privateExponent=19712258294449768061250797972714250470961317803075954678035114536989001132350508287725515289410018227700383934247630096603354472814932822030798488263700517807054160870830687708883881972726395341960781612568717609213256299247092742948261022886896152061640255944343187939133790917638820978981261442420966468553309333300831019860719226985672896951420320512362483168228723053579083209171274606579718510320975038655697547301178385870610542263045282099094618903834479420547657350795038030554807361588336209946728670621034426088896430152818286774372468243737595530907990335033759644709589989333890062536967115311619827877793
prime1=179011447260068655973124186182614568979533154120320070113226307098867181415537548658298491022619534789937302538473860746108091719620047075412832650019339010689809055924802197544449368830521374894873231868641326454768801343430962780662734215543338611513801337035057715177833684998244785547570241642848471137433
prime2=163404457729818349624425585059376297638550566587001375236662658903455722737484101678581659602043971868350768323052069253427654248129269653305480600170973654074078888238525688298133917251945706616440907845196427203153244396250721179435943398060774062957241903685529550129728817507810911682415235634930964742029
exponent1=60029213672193247361358472919653331438167754521907841080280979463689275462246802674266840673270206388428705889620215109285098978013790295197336209308863900360558671011175029303055736130557826206030624178359254032019377559616434518373207651479255270537845979889519865212982756232455340524878331333214533014745
exponent2=124825377600220117728874414306614812471983697233801316048160266038155657157474465819865300613649227270352821540889555443544899557171426155043495746936228771801649228081443307733917885061894957902337574352837541106530113179637397273712270477448076547414305791630870369374471573610495528975516675417354834961089
coefficient=92773579829798681364932858735394964473766250124853828149170174032722412637938403258313692804149389727272097569239655966328782774259608204560835938769655914373875441609947759091235368799025836346621444197945955486577885636949863610961921831595069239745885167171853656756901878283745710333645530928800135055593
pyasn1解析PKCS#13-EC私钥
import base64
from pyasn1_modules import rfc5915
from pyasn1.codec.der import decoder
private_key_pem = b"""-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILb9XVRPCaPgtmBLTfusYmTDBzACWEIMP7G47ttUSgcZoAoGCCqGSM49
AwEHoUQDQgAEIL5WxHjk/yCczEPlMxcLSSYqsOs4uhGzlq0FQnIx4uJrvDaIq6ht
+tdT2VAnfDTNbyhkJWWfCCpe9meVIQj6hQ==
-----END EC PRIVATE KEY-----"""
private_key_der = base64.b64decode(b"".join(private_key_pem.strip().split(b"\n")[1:-1]))
private_key_asn1, _ = decoder.decode(private_key_der, asn1Spec=rfc5915.ECPrivateKey())
print(private_key_asn1)
运行后输出如下:
ECPrivateKey:
version=ecPrivkeyVer1
privateKey=0xb6fd5d544f09a3e0b6604b4dfbac6264c307300258420c3fb1b8eedb544a0719
parameters=ECParameters:
namedCurve=1.2.840.10045.3.1.7
publicKey=55346148566235007019366148145582934212029111162400636479433293193372440464815863465406199677738031681986384378401592422838283150086311760450437229027326597
pyasn1解析PKCS#8格式私钥
import base64
from pyasn1_modules import rfc5208
from pyasn1.codec.der import decoder
private_key_pem = b"""-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgtv1dVE8Jo+C2YEtN
+6xiZMMHMAJYQgw/sbju21RKBxmhRANCAAQgvlbEeOT/IJzMQ+UzFwtJJiqw6zi6
EbOWrQVCcjHi4mu8NoirqG3611PZUCd8NM1vKGQlZZ8IKl72Z5UhCPqF
-----END PRIVATE KEY-----"""
private_key_der = base64.b64decode(b"".join(private_key_pem.strip().split(b"\n")[1:-1]))
private_key_asn1, _ = decoder.decode(private_key_der, asn1Spec=rfc5208.PrivateKeyInfo())
print(private_key_asn1)
运行后输出如下:
PrivateKeyInfo:
version=v1
privateKeyAlgorithm=AlgorithmIdentifier:
algorithm=1.2.840.10045.2.1
parameters=0x06082a8648ce3d030107
privateKey=0x306b0201010420b6fd5d544f09a3e0b6604b4dfbac6264c307300258420c3fb1b8eedb544a0719a1440342000420be56c478e4ff209ccc43e533170b49262ab0eb38ba11b396ad05427231e2e26bbc3688aba86dfad753d950277c34cd6f286425659f082a5ef667952108fa85
pyasn1解析PKCS#1-RSA公钥
import base64
from pyasn1_modules import rfc2437
from pyasn1.codec.der import decoder
public_key_pem = b"""-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA57b1SHQKXl47qa/35WaX3UNI/UTBIPxcJjJIW84hYBOMDWGwBQHE
1n+l+b9FctQXRIpB/DBPasRvg8YfUSN05Rexv3/s+Z/nIXXlVaatwBV+tCb97iqK
urYJpMuxJmOhe68ENgFGZkUfAMvByHfPVfzKg2y8gZmsxyfPnZ0dPZpm/xSzdceN
I49iWLFvCARkKEjuO0rjL8tqk3cxY5uTDSov68UEbyhQOYTodLlByY9uwzQOF74T
UWV7ZiEfDoFwaiJi7Q+60wQm9oPS/XeoE97IfA9tEKe7kKmBQZxoI8vyStPUQ1WE
Fn+wtcB67pS9dEpTRWBgmQYtLtkq4lcHRQIDAQAB
-----END RSA PUBLIC KEY-----"""
public_key_der = base64.b64decode(b"".join(public_key_pem.strip().split(b"\n")[1:-1]))
public_key_asn1, _ = decoder.decode(public_key_der, asn1Spec=rfc2437.RSAPublicKey())
print(public_key_asn1)
运行后输出:
RSAPublicKey:
modulus=29251268466961495515231372053385573035557384464172735010401614432483825817069065134216395234281996254699424021256355341131983291857177682722346666485636608978170690388127041330853005158984937654841701450083007946451017278020077371099290901323186077610409089863566614014876287906018236397588473477911080707564663343710640573037793994443721208516459214603050807450018876235614286592128971472399939405937824179326202712715422179853542382632375121164999622864151600512254702385441589120043203914553310287472567550480071947761578908479979477695682249475708285623845365952983861483247840983904791189780312972719365050271557
publicExponent=65537
pyasn1解析X.509证书扩展标准公钥
import base64
from pyasn1_modules import rfc5280
from pyasn1.codec.der import decoder
public_key_pem = b"""-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEP9eQZFl3j5zZX8bmYYEznA0z3/X+
TooIQ11rxFcPZsTvJPLCUY7NHasUenXJngmvRXSnP4odegaoe4usLDv/3A==
-----END PUBLIC KEY-----"""
public_key_der = base64.b64decode(b"".join(public_key_pem.strip().split(b"\n")[1:-1]))
public_key_asn1, _ = decoder.decode(public_key_der, asn1Spec=rfc5280.SubjectPublicKeyInfo())
print(public_key_asn1)
运行后输出:
SubjectPublicKeyInfo:
algorithm=AlgorithmIdentifier:
algorithm=1.2.840.10045.2.1
parameters=0x06082a8648ce3d030107
subjectPublicKey=56974911032227708264759981020117277404936519642271304916201176657575037021527157268002695854599777213392117837220543419196532676177287273127953450086957020