python有证书的加密解密实现方法
本文实例讲述了python有证书的加密解密实现方法。分享给大家供大家参考。具体实现方法如下:
最近在做python的加解密工作,同时加完密的串能在php上能解出来,网上也找了一些靠谱的资料,刚好也有时间我就总结了一下python在加密与解密这块的代码,今后可能还能用的上。相对于php而言python这块加解密组件较多的,分别是:
python-crypto-这个组件是基本组件,使用的函式相对比较复杂。
ezPyCrypto-相对简单,但他作出来的公私钥无法与其他程序相兼容 SSLCrypto-与ezPyCrypto是相同一个作者开发,效率上要比ezPyCrypto好。但一样不能与其它程序相兼容。
pyopenssl-似乎是用在https通讯上的,而我找不到加解密的用法。
M2Crypto-终于让我找到了,但它有一大缺点,它底层是用SWIG与OpenSSL交接的。
在Windows安装SWIG程序是非常难的。
我选择使用的是M2Crypto,公钥与私钥证书生成有两个方式,一种采用RSA生成,另一种是X509生成。我就把这两种加解密代码分享出来,供大家参考,但转载或使用时请写明出处。
一、RSA标准方式生成的证书
1.加密解密、加密签名、验证加密签名
#encoding:utf8
importos
importM2Crypto
#随机数生成器(1024位随机)
M2Crypto.Rand.rand_seed(os.urandom(1024))
#生成一个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("这是一个秘密消息,只能用私钥进行解密",M2Crypto.RSA.pkcs1_oaep_padding)
print"加密的串是:"
printCipherText.encode('base64')
#对加密串进行签名
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"签名的串是:"
printSignature.encode('base64')
#使用私钥证书解密开始
ReadRSA=M2Crypto.RSA.load_key('jb51.net-private.pem')
try:
PlainText=ReadRSA.private_decrypt(CipherText,M2Crypto.RSA.pkcs1_oaep_padding)
except:
print"解密错误"
PlainText=""
ifPlainText:
print"解密出来的串是:"
printPlainText
#验证加密串的签名
MsgDigest=M2Crypto.EVP.MessageDigest('sha1')
MsgDigest.update(CipherText)
#提示,如果是用私钥签名的那就用公钥验证
#VerifyRSA=M2Crypto.RSA.load_pub_key('Alice-public.pem')
#VerifyRSA.verify_rsassa_pss(MsgDigest.digest(),Signature)
ifGeekso.verify_rsassa_pss(MsgDigest.digest(),Signature)==1:
print"签名正确"
else:
print"签名不正确"
2.字符串生成签名、验证签名
#用私钥签名
SignEVP=M2Crypto.EVP.load_key('jb51.net-private.pem')
SignEVP.sign_init()
SignEVP.sign_update('来自这一客(https://www.nhooo.com)的签名串')
StringSignature=SignEVP.sign_final()
print"签名串是:"
printStringSignature.encode('base64')
#用公钥验证签名
PubKey=M2Crypto.RSA.load_pub_key('jb51.net-public.pem')
VerifyEVP=M2Crypto.EVP.PKey()
VerifyEVP.assign_rsa(PubKey)
VerifyEVP.verify_init()
VerifyEVP.verify_update('来自这一客(https://www.nhooo.com)的签名串')
ifVerifyEVP.verify_final(StringSignature)==1:
print"字符串被成功验证。"
else:
print"字符串验证失败!"
3.给证书加上密码
给证书加密码的好处是即使证书被人拿了,没有密码也用不了。
defpassphrase(v): return'4567890'
生成证书时用
Geekso.save_key('jb51.net-private.pem',callback=passphrase)使用证书时用
ReadRSA=RSA.load_key('jb51.net-private.pem',passphrase)二、X509标准方式生成的证书
1.生成证书、公钥文件、私钥文件
importtime
fromM2CryptoimportX509,EVP,RSA,ASN1
defissuer_name():
"""
证书发行人名称(专有名称)。
Parameters:
none
Return:
X509标准的发行人obj.
"""
issuer=X509.X509_Name()
issuer.C="CN" #国家名称
issuer.CN="*.jb51.net" #普通名字
issuer.ST="HunanChangsha"
issuer.L="HunanChangsha"
issuer.O="GeeksoCompanyLtd"
issuer.OU="GeeksoCompanyLtd"
issuer.Email="123456@qq.com"
returnissuer
defmake_request(bits,cn):
"""
创建一个X509标准的请求。
Parameters:
bits=证书位数
cn=证书名称
Return:
返回X509request与privatekey(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')
returnreq,pk
defmake_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)
defmake_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')
returncert,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.用证书加密、私钥文件解密
defgeekso_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()#getRSAforencryption
message=base64.b64encode(message)
try:
encrypted=puk.public_encrypt(message,RSA.pkcs1_padding)
exceptRSA.RSAErrorase:
return"ERRORencrypting"+e.message
returnencrypted
encrypted=geekso_encrypt_with_certificate('www.nhooo.com','jb51.net-cret.pem')
print'加密串',encrypted
defgeekso_decrypt_with_private_key(message,pk_loc):
"""
私钥解密证书生成的加密串
Parameters:
message=加密的串
pk_loc=私钥路径
Return:
解密串or异常串
"""
pk=RSA.load_key(pk_loc)#loadRSAfordecryption
try:
decrypted=pk.private_decrypt(message,RSA.pkcs1_padding)
decrypted=base64.b64decode(decrypted)
exceptRSA.RSAErrorase:
return"ERRORdecrypting"+e.message
returndecrypted
print'解密串',geekso_decrypt_with_private_key(encrypted,'jb51.net-private.pem')
3.用私钥加密、证书解密
defgeekso_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)
exceptRSA.RSAErrorase:
return"ERRORencrypting"+e.message
returnencrypted
encrypted=geekso_encrypt_with_private_key('www.nhooo.com','jb51.net-private.pem')
printencrypted
defgeekso_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)
exceptRSA.RSAErrorase:
return"ERRORdecrypting"+e.message
returndecrypting
decrypting=geekso_decrypt_with_certificate(encrypted,'jb51.net-cret.pem')
printdecrypting
4.用私钥签名、证书验证签名
defgeekso_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()
exceptEVP.EVPErrorase:
return"ERRORsignature"+e.message
returnsignature.encode('base64')ifbase64isTrueelsesignature.encode('hex')
signature=geekso_sign_with_private_key('www.nhooo.com','jb51.net-private.pem')
printsignature
defgeekso_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')ifbase64isTrueelsesignature.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)
ifverifysign==1:
return'成功'
else:
return'失败'
exceptEVP.EVPErrorase:
return"ERRORVerifySign"+e.message
printgeekso_verifysign_with_certificate('www.nhooo.com',signature,'jb51.net-cret.pem')
希望本文所述对大家的Python程序设计有所帮助。