https://wenku.baidu.com/view/988c262aed630b1c59eeb56b.html
這篇講得很細
https://wyxwyx46941930.github.io/2019/01/22/X-509/ 這篇也可以
X509標准方式生成的證書
1.生成證書、公鑰文件、私鑰文件
import time from M2Crypto import X509, EVP, RSA, ASN1 def issuer_name(): """ 證書發行人名稱(專有名稱)。 Parameters: none Return: X509標准的發行人obj. """ issuer = X509.X509_Name() issuer.C = "CN" # 國家名稱 issuer.CN = "*.jb51.net" # 普通名字 issuer.ST = "Hunan Changsha" issuer.L = "Hunan Changsha" issuer.O = "Geekso Company Ltd" issuer.OU = "Geekso Company Ltd" issuer.Email = "123456@qq.com" return issuer def make_request(bits, cn): """ 創建一個X509標准的請求。 Parameters: bits = 證書位數 cn = 證書名稱 Return: 返回 X509 request 與 private key (EVP). """ rsa = RSA.gen_key(bits, 65537, None) pk = EVP.PKey() pk.assign_rsa(rsa) req = X509.Request() req.set_pubkey(pk) name = req.get_subject() name.C = "US" name.CN = cn req.sign(pk,'sha256') return req, pk def make_certificate_valid_time(cert, days): """ 從當前時間算起證書有效期幾天。 Parameters: cert = 證書obj days = 證書過期的天數 Return: none """ t = long(time.time()) # 獲取當前時間 time_now = ASN1.ASN1_UTCTIME() time_now.set_time(t) time_exp = ASN1.ASN1_UTCTIME() time_exp.set_time(t + days * 24 * 60 * 60) cert.set_not_before(time_now) cert.set_not_after(time_exp) def make_certificate(bits): """ 創建證書 Parameters: bits = 證快的位數 Return: 證書, 私鑰 key (EVP) 與 公鑰 key (EVP). """ req, pk = make_request(bits, "localhost") puk = req.get_pubkey() cert = X509.X509() cert.set_serial_number(1) # 證書的序例號 cert.set_version(1) # 證書的版本 cert.set_issuer(issuer_name()) # 發行人信息 cert.set_subject(issuer_name()) # 主題信息 cert.set_pubkey(puk) make_certificate_valid_time(cert, 365) # 證書的過期時間 cert.sign(pk, 'sha256') return cert, pk, puk # 開始創建 cert, pk, puk= make_certificate(1024) cert.save_pem('jb51.net-cret.pem') pk.save_key('jb51.net-private.pem',cipher = None, callback = lambda: None) puk.get_rsa().save_pub_key('jb51.net-public.pem')
2.用證書加密、私鑰文件解密
def geekso_encrypt_with_certificate(message, cert_loc): """ cert證書加密,可以用私鑰文件解密. Parameters: message = 要加密的串 cert_loc = cert證書路徑 Return: 加密串 or 異常串 """ cert = X509.load_cert(cert_loc) puk = cert.get_pubkey().get_rsa() # get RSA for encryption message = base64.b64encode(message) try: encrypted = puk.public_encrypt(message, RSA.pkcs1_padding) except RSA.RSAError as e: return "ERROR encrypting " + e.message return encrypted encrypted = geekso_encrypt_with_certificate('www.jb51.net','jb51.net-cret.pem') print '加密串',encrypted def geekso_decrypt_with_private_key(message, pk_loc): """ 私鑰解密證書生成的加密串 Parameters: message = 加密的串 pk_loc = 私鑰路徑 Return: 解密串 or 異常串 """ pk = RSA.load_key(pk_loc) # load RSA for decryption try: decrypted = pk.private_decrypt(message, RSA.pkcs1_padding) decrypted = base64.b64decode(decrypted) except RSA.RSAError as e: return "ERROR decrypting " + e.message return decrypted print '解密串',geekso_decrypt_with_private_key(encrypted, 'jb51.net-private.pem')
3.用私鑰加密、證書解密
def geekso_encrypt_with_private_key(message,pk_loc): """ 私鑰加密 Parameters: message = 加密的串 pk_loc = 私鑰路徑 Return: 加密串 or 異常串 """ ReadRSA = RSA.load_key(pk_loc); message = base64.b64encode(message) try: encrypted = ReadRSA.private_encrypt(message,RSA.pkcs1_padding) except RSA.RSAError as e: return "ERROR encrypting " + e.message return encrypted encrypted = geekso_encrypt_with_private_key('www.jb51.net', 'jb51.net-private.pem') print encrypted def geekso_decrypt_with_certificate(message, cert_loc): """ cert證書解密. Parameters: message = 要解密的串 cert_loc = cert證書路徑 Return: 解密后的串 or 異常串 """ cert = X509.load_cert(cert_loc) puk = cert.get_pubkey().get_rsa() try: decrypting = puk.public_decrypt(message, RSA.pkcs1_padding) decrypting = base64.b64decode(decrypting) except RSA.RSAError as e: return "ERROR decrypting " + e.message return decrypting decrypting = geekso_decrypt_with_certificate(encrypted, 'jb51.net-cret.pem') print decrypting
4.用私鑰簽名、證書驗證簽名
def geekso_sign_with_private_key(message, pk_loc, base64 = True): """ 私鑰簽名 Parameters: message = 待簽名的串 pk_loc = 私鑰路徑 base64 = True(bease64處理) False(16進制處理) Return: 簽名后的串 or 異常串 """ pk = EVP.load_key(pk_loc) pk.sign_init() try: pk.sign_update(message) signature = pk.sign_final() except EVP.EVPError as e: return "ERROR signature " + e.message return signature.encode('base64') if base64 is True else signature.encode('hex') signature = geekso_sign_with_private_key('www.jb51.net','jb51.net-private.pem') print signature def geekso_verifysign_with_certificate(message, signature, cert_loc, base64 = True): """ 證書驗證簽名 Parameters: message = 原來簽名的串 signature = 簽名后的串 cert_loc = 證書路徑文件 base64 = True(bease64處理) False(16進制處理) Return: 成功or失敗串 or 異常串 """ signature = signature.decode('base64') if base64 is True else signature.decode('hex') cert = X509.load_cert(cert_loc) puk = cert.get_pubkey().get_rsa() try: verifyEVP = EVP.PKey() verifyEVP.assign_rsa(puk) verifyEVP.verify_init() verifyEVP.verify_update(message) verifysign = verifyEVP.verify_final(signature) if verifysign == 1 : return '成功' else : return '失敗' except EVP.EVPError as e: return "ERROR Verify Sign " + e.message print geekso_verifysign_with_certificate('www.jb51.net', signature, 'jb51.net-cret.pem')