python有证书的加密解密实现方法
程序员文章站
2023-12-26 12:44:57
本文实例讲述了python有证书的加密解密实现方法。分享给大家供大家参考。具体实现方法如下:
最近在做python的加解密工作,同时加完密的串能在php上能解出来,网上也...
本文实例讲述了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
import os
import m2crypto
#随机数生成器(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 "加密的串是:"
print ciphertext.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 "签名的串是:"
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 "解密错误"
plaintext = ""
if plaintext :
print "解密出来的串是:"
print plaintext
# 验证加密串的签名
msgdigest = m2crypto.evp.messagedigest('sha1')
msgdigest.update(ciphertext)
#提示,如果是用私钥签名的那就用公钥验证
#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 "签名不正确"
import os
import m2crypto
#随机数生成器(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 "加密的串是:"
print ciphertext.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 "签名的串是:"
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 "解密错误"
plaintext = ""
if plaintext :
print "解密出来的串是:"
print plaintext
# 验证加密串的签名
msgdigest = m2crypto.evp.messagedigest('sha1')
msgdigest.update(ciphertext)
#提示,如果是用私钥签名的那就用公钥验证
#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.字符串生成签名、验证签名
复制代码 代码如下:
#用私钥签名
signevp = m2crypto.evp.load_key('jb51.net-private.pem')
signevp.sign_init()
signevp.sign_update('来自这一客(//www.jb51.net)的签名串')
stringsignature = signevp.sign_final()
print "签名串是:"
print stringsignature.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('来自这一客(//www.jb51.net)的签名串')
if verifyevp.verify_final(stringsignature) == 1:
print "字符串被成功验证。"
else:
print "字符串验证失败!"
signevp = m2crypto.evp.load_key('jb51.net-private.pem')
signevp.sign_init()
signevp.sign_update('来自这一客(//www.jb51.net)的签名串')
stringsignature = signevp.sign_final()
print "签名串是:"
print stringsignature.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('来自这一客(//www.jb51.net)的签名串')
if verifyevp.verify_final(stringsignature) == 1:
print "字符串被成功验证。"
else:
print "字符串验证失败!"
3.给证书加上密码
给证书加密码的好处是即使证书被人拿了,没有密码也用不了。
复制代码 代码如下:
def passphrase(v):
return '4567890'
return '4567890'
生成证书时用
复制代码 代码如下:
geekso.save_key('jb51.net-private.pem',callback=passphrase)
使用证书时用
复制代码 代码如下:
readrsa = rsa.load_key ('jb51.net-private.pem', passphrase)
二、 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')
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')
"""
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
"""
私钥加密
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')
"""
私钥签名
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')
希望本文所述对大家的python程序设计有所帮助。