这不是微不足道的。
您正在调用cert.public_bytes(Encoding.PEM),其源代码如下:
def public_bytes(self, encoding):
bio = self._backend._create_mem_bio_gc()
if encoding is serialization.Encoding.PEM:
res = self._backend._lib.PEM_write_bio_X509(bio, self._x509)
elif encoding is serialization.Encoding.DER:
res = self._backend._lib.i2d_X509_bio(bio, self._x509)
else:
raise TypeError("encoding must be an item from the Encoding enum")
self._backend.openssl_assert(res == 1)
return self._backend._read_mem_bio(bio)
转到PEM_write_bio_X509,它实际上是用 C 语言实现并通过 CFFI 访问的。
传递给它的参数,._x509 只是一个数据块:
In [25]: c._x509
Out[25]: <cdata 'X509 *' 0x7f8608d08890>
这意味着要修改现有对象中的签名,您必须找到内存位置并覆盖该内存位置...
这样就大错特错了。
您看,cryptography 是底层库(如 OpenSSL)上的薄垫片。默认情况下,它不会向您提供所有详细信息。正确的方法是将证书的 X.509 表示分解为一堆字段,然后添加、删除、修改这些字段,然后将其回滚到 X.509。
但是,由于这太难了,请注意:
pd # PEM data as a string
'-----BEGIN CERTIFICATE-----\nMIIC [snip] 1Q=\n-----END CERTIFICATE-----\n'
b64 = "".join([bit for bit in pd.split() if "---" not in bit])
pemdata = binascii.a2b_base64(b64)
cert.signature in pemdata
True
所以,恰好证书签名在 cert blob 中占用了一个字节范围,所以,让我们尝试更改它:
pemdata.find(cert.signature)
423
len(cert.signature)
128
fakesig = b"\x42" * len(cert.signature)
fakecertdata = pemdata[:423] + fakesig + pemdata[423 + 128:]
with open("fake.pem", "wb") as fout:
fout.write(b"-----BEGIN CERTIFICATE-----\n")
fout.write(base64.encodebytes(fakecertdata))
fout.write(b"-----END CERTIFICATE-----\n")
你瞧!
> openssl x509 -in fake.pem -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number: [snip]
Signature Algorithm: sha1WithRSAEncryption
Issuer: [snip]
Validity [snip]
Subject: [snip]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00: [snip] :55
Exponent: 65537 (0x10001)
Signature Algorithm: sha1WithRSAEncryption
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:42:
42:42