python有證書的加密解密實(shí)現(xiàn)方法
本文實(shí)例講述了python有證書的加密解密實(shí)現(xiàn)方法。分享給大家供大家參考。具體實(shí)現(xiàn)方法如下:
最近在做python的加解密工作,同時(shí)加完密的串能在php上能解出來,網(wǎng)上也找了一些靠譜的資料,剛好也有時(shí)間我就總結(jié)了一下python在加密與解密這塊的代碼,今后可能還能用的上。相對(duì)于php而言python這塊加解密組件較多的,分別是:
python-crypto - 這個(gè)組件是基本組件,使用的函式相對(duì)比較復(fù)雜。
ezPyCrypto - 相對(duì)簡(jiǎn)單,但他作出來的公私鑰無法與其他程序相兼容 SSLCrypto - 與 ezPyCrypto 是相同一個(gè)作者開發(fā),效率上要比ezPyCrypto 好。但一樣不能與其它程序相兼容。
pyopenssl - 似乎是用在https 通訊上的,而我找不到加解密的用法。
M2Crypto - 終于讓我找到了,但它有一大缺點(diǎn),它底層是用 SWIG 與 OpenSSL 交接的。
在Windows安裝SWIG 程序是非常難的。
我選擇使用的是M2Crypto,公鑰與私鑰證書生成有兩個(gè)方式,一種采用RSA生成,另一種是X509生成。我就把這兩種加解密代碼分享出來,供大家參考,但轉(zhuǎn)載或使用時(shí)請(qǐng)寫明出處。
一、 RSA標(biāo)準(zhǔn)方式生成的證書
1.加密解密、加密簽名、驗(yàn)證加密簽名
import os
import M2Crypto
#隨機(jī)數(shù)生成器(1024位隨機(jī))
M2Crypto.Rand.rand_seed(os.urandom(1024))
#生成一個(gè)1024位公鑰與私密鑰證書
Geekso = M2Crypto.RSA.gen_key(1024, 65537)
Geekso.save_key('jb51.net-private.pem', None)
Geekso.save_pub_key('jb51.net-public.pem')
#使用公鑰證書加密開始
WriteRSA = M2Crypto.RSA.load_pub_key('jb51.net-public.pem')
CipherText = WriteRSA.public_encrypt("這是一個(gè)秘密消息,只能用私鑰進(jìn)行解密",M2Crypto.RSA.pkcs1_oaep_padding)
print "加密的串是:"
print CipherText.encode('base64')
#對(duì)加密串進(jìn)行簽名
MsgDigest = M2Crypto.EVP.MessageDigest('sha1')
MsgDigest.update(CipherText)
#提示,這里也可以使用私鑰簽名
#WriteRSA = M2Crypto.RSA.load_key ('jb51.net-private.pem')
#Signature = WriteRSA.sign_rsassa_pss(MsgDigest.digest())
Signature = Geekso.sign_rsassa_pss(MsgDigest.digest())
print "簽名的串是:"
print Signature.encode('base64')
#使用私鑰證書解密開始
ReadRSA = M2Crypto.RSA.load_key ('jb51.net-private.pem')
try:
PlainText = ReadRSA.private_decrypt (CipherText, M2Crypto.RSA.pkcs1_oaep_padding)
except:
print "解密錯(cuò)誤"
PlainText = ""
if PlainText :
print "解密出來的串是:"
print PlainText
# 驗(yàn)證加密串的簽名
MsgDigest = M2Crypto.EVP.MessageDigest('sha1')
MsgDigest.update(CipherText)
#提示,如果是用私鑰簽名的那就用公鑰驗(yàn)證
#VerifyRSA = M2Crypto.RSA.load_pub_key('Alice-public.pem')
#VerifyRSA.verify_rsassa_pss(MsgDigest.digest(), Signature)
if Geekso.verify_rsassa_pss(MsgDigest.digest(), Signature) == 1:
print "簽名正確"
else:
print "簽名不正確"
2.字符串生成簽名、驗(yàn)證簽名
SignEVP = M2Crypto.EVP.load_key('jb51.net-private.pem')
SignEVP.sign_init()
SignEVP.sign_update('來自這一客(http://www.dbjr.com.cn)的簽名串')
StringSignature = SignEVP.sign_final()
print "簽名串是:"
print StringSignature.encode('base64')
#用公鑰驗(yàn)證簽名
PubKey = M2Crypto.RSA.load_pub_key('jb51.net-public.pem')
VerifyEVP = M2Crypto.EVP.PKey()
VerifyEVP.assign_rsa(PubKey)
VerifyEVP.verify_init()
VerifyEVP.verify_update('來自這一客(http://www.dbjr.com.cn)的簽名串')
if VerifyEVP.verify_final(StringSignature) == 1:
print "字符串被成功驗(yàn)證。"
else:
print "字符串驗(yàn)證失敗!"
3.給證書加上密碼
給證書加密碼的好處是即使證書被人拿了,沒有密碼也用不了。
return '4567890'
生成證書時(shí)用
使用證書時(shí)用
二、 X509標(biāo)準(zhǔn)方式生成的證書
1.生成證書、公鑰文件、私鑰文件
from M2Crypto import X509, EVP, RSA, ASN1
def issuer_name():
"""
證書發(fā)行人名稱(專有名稱)。
Parameters:
none
Return:
X509標(biāo)準(zhǔn)的發(fā)行人obj.
"""
issuer = X509.X509_Name()
issuer.C = "CN" # 國(guó)家名稱
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):
"""
創(chuàng)建一個(gè)X509標(biāo)準(zhǔn)的請(qǐng)求。
Parameters:
bits = 證書位數(shù)
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):
"""
從當(dāng)前時(shí)間算起證書有效期幾天。
Parameters:
cert = 證書obj
days = 證書過期的天數(shù)
Return:
none
"""
t = long(time.time()) # 獲取當(dāng)前時(shí)間
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):
"""
創(chuàng)建證書
Parameters:
bits = 證快的位數(shù)
Return:
證書, 私鑰 key (EVP) 與 公鑰 key (EVP).
"""
req, pk = make_request(bits, "localhost")
puk = req.get_pubkey()
cert = X509.X509()
cert.set_serial_number(1) # 證書的序例號(hào)
cert.set_version(1) # 證書的版本
cert.set_issuer(issuer_name()) # 發(fā)行人信息
cert.set_subject(issuer_name()) # 主題信息
cert.set_pubkey(puk)
make_certificate_valid_time(cert, 365) # 證書的過期時(shí)間
cert.sign(pk, 'sha256')
return cert, pk, puk
# 開始創(chuàng)建
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.用證書加密、私鑰文件解密
"""
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.dbjr.com.cn','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.用私鑰加密、證書解密
"""
私鑰加密
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.dbjr.com.cn', '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.用私鑰簽名、證書驗(yàn)證簽名
"""
私鑰簽名
Parameters:
message = 待簽名的串
pk_loc = 私鑰路徑
base64 = True(bease64處理) False(16進(jìn)制處理)
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.dbjr.com.cn','jb51.net-private.pem')
print signature
def geekso_verifysign_with_certificate(message, signature, cert_loc, base64 = True):
"""
證書驗(yàn)證簽名
Parameters:
message = 原來簽名的串
signature = 簽名后的串
cert_loc = 證書路徑文件
base64 = True(bease64處理) False(16進(jìn)制處理)
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.dbjr.com.cn', signature, 'jb51.net-cret.pem')
希望本文所述對(duì)大家的Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
運(yùn)用Python的webbrowser實(shí)現(xiàn)定時(shí)打開特定網(wǎng)頁(yè)
今天小編就為大家分享一篇運(yùn)用Python的webbrowser實(shí)現(xiàn)定時(shí)打開特定網(wǎng)頁(yè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-02-02Django Rest framework認(rèn)證組件詳細(xì)用法
這篇文章主要介紹了Django Rest framework認(rèn)證組件詳細(xì)用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07python將txt等文件中的數(shù)據(jù)讀為numpy數(shù)組的方法
今天小編就為大家分享一篇python將txt等文件中的數(shù)據(jù)讀為numpy數(shù)組的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12selenium+python實(shí)現(xiàn)自動(dòng)登陸QQ郵箱并發(fā)送郵件功能
這篇文章主要介紹了selenium+python實(shí)現(xiàn)自動(dòng)登陸QQ郵箱并發(fā)送郵件功能,本文給大家分享完整實(shí)例代碼,需要的朋友可以參考下2019-12-12使用keras實(shí)現(xiàn)BiLSTM+CNN+CRF文字標(biāo)記NER
這篇文章主要介紹了使用keras實(shí)現(xiàn)BiLSTM+CNN+CRF文字標(biāo)記NER,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06Python使用百度API上傳文件到百度網(wǎng)盤代碼分享
這篇文章主要介紹了Python使用百度API上傳文件到百度網(wǎng)盤代碼分享,本文使用了一個(gè)第三方庫(kù)poster,在文中給出了鏈接,需要的朋友可以參考下2014-11-11Python3實(shí)現(xiàn)爬蟲爬取趕集網(wǎng)列表功能【基于request和BeautifulSoup模塊】
這篇文章主要介紹了Python3實(shí)現(xiàn)爬蟲爬取趕集網(wǎng)列表功能,結(jié)合實(shí)例形式分析了Python3基于request和BeautifulSoup模塊的網(wǎng)站頁(yè)面爬取相關(guān)操作技巧,需要的朋友可以參考下2018-12-12Python使用cx_Oracle庫(kù)連接Oracle數(shù)據(jù)庫(kù)指南
這篇文章主要為大家介紹了Python使用cx_Oracle庫(kù)連接Oracle數(shù)據(jù)庫(kù)指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12