python有证书的加密解密实现方法


Posted in Python onNovember 19, 2014

本文实例讲述了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('3water.com-private.pem', None)

Geekso.save_pub_key('3water.com-public.pem')

#使用公钥证书加密开始

WriteRSA = M2Crypto.RSA.load_pub_key('3water.com-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 ('3water.com-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 ('3water.com-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('3water.com-private.pem')

SignEVP.sign_init()

SignEVP.sign_update('来自这一客(https://3water.com)的签名串')

StringSignature = SignEVP.sign_final()

print "签名串是:"

print StringSignature.encode('base64')

#用公钥验证签名

PubKey = M2Crypto.RSA.load_pub_key('3water.com-public.pem')

VerifyEVP = M2Crypto.EVP.PKey()

VerifyEVP.assign_rsa(PubKey)

VerifyEVP.verify_init()

VerifyEVP.verify_update('来自这一客(https://3water.com)的签名串')

if VerifyEVP.verify_final(StringSignature) == 1:

    print "字符串被成功验证。"

else:

    print "字符串验证失败!"

3.给证书加上密码

给证书加密码的好处是即使证书被人拿了,没有密码也用不了。

def passphrase(v):

    return '4567890'

生成证书时用
Geekso.save_key('3water.com-private.pem',callback=passphrase)

使用证书时用
ReadRSA = RSA.load_key ('3water.com-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 = "*.3water.com"       # 普通名字

    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('3water.com-cret.pem')

pk.save_key('3water.com-private.pem',cipher = None, callback = lambda: None)

puk.get_rsa().save_pub_key('3water.com-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('3water.com','3water.com-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, '3water.com-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('3water.com', '3water.com-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, '3water.com-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('3water.com','3water.com-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('3water.com', signature, '3water.com-cret.pem')

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
进一步理解Python中的函数编程
Apr 13 Python
Python函数式编程指南(四):生成器详解
Jun 24 Python
Python实现基本线性数据结构
Aug 22 Python
详解python中的文件与目录操作
Jul 11 Python
Python内置模块ConfigParser实现配置读写功能的方法
Feb 12 Python
flask-restful使用总结
Dec 04 Python
Python爬取数据保存为Json格式的代码示例
Apr 09 Python
Python OpenCV实现鼠标画框效果
Aug 19 Python
python修改FTP服务器上的文件名
Sep 11 Python
在python tkinter界面中添加按钮的实例
Mar 04 Python
关于python scrapy中添加cookie踩坑记录
Nov 17 Python
Python-split()函数实例用法讲解
Dec 18 Python
Python采用socket模拟TCP通讯的实现方法
Nov 19 #Python
Python实现向QQ群成员自动发邮件的方法
Nov 19 #Python
python端口扫描系统实现方法
Nov 19 #Python
Python提示[Errno 32]Broken pipe导致线程crash错误解决方法
Nov 19 #Python
python中urllib模块用法实例详解
Nov 19 #Python
python统计一个文本中重复行数的方法
Nov 19 #Python
python通过zlib实现压缩与解压字符串的方法
Nov 19 #Python
You might like
php中批量删除Mysql中相同前缀的数据表的代码
2011/07/01 PHP
Joomla实现组件中弹出一个模式(modal)窗口的方法
2016/05/04 PHP
php文件上传类完整实例
2016/05/14 PHP
PHP用PDO如何封装简单易用的DB类详解
2017/07/30 PHP
PHP框架Laravel中使用UUID实现数据分表操作示例
2018/05/30 PHP
PDO::errorCode讲解
2019/01/28 PHP
PHP MVC框架中类的自动加载机制实例分析
2019/09/18 PHP
php利用ZipArchive类操作文件的实例
2020/01/21 PHP
cookie在javascript中的使用技巧以及隐私在服务器端的设置
2012/12/03 Javascript
jQuery实现 注册时选择阅读条款 左右移动
2013/04/11 Javascript
Table冻结表头示例代码
2013/08/20 Javascript
Javascript变量作用域详解
2013/12/06 Javascript
JS判断字符串字节数并截取长度的方法
2016/03/05 Javascript
javascript 继承学习心得总结
2016/03/17 Javascript
RequireJS多页面应用实例分析
2016/06/29 Javascript
原生js实现选项卡功能
2017/03/08 Javascript
关于Node.js中Buffer的一些你可能不知道的用法
2017/03/28 Javascript
详解http访问解析流程原理
2017/10/18 Javascript
JS中判断字符串存在和非空的方法
2018/09/12 Javascript
layui富文本编辑器前端无法取值的解决方法
2019/09/18 Javascript
vue和iview实现Scroll 数据无限滚动功能
2019/10/31 Javascript
如何用python写一个简单的词法分析器
2018/12/18 Python
python中for in的用法详解
2020/04/17 Python
python 使用openpyxl读取excel数据
2021/02/18 Python
css3实现波纹特效、H5实现动态波浪效果
2018/01/31 HTML / CSS
软件测试面试题
2015/10/21 面试题
会计专业自我评价
2014/02/12 职场文书
清明节网上祭英烈活动总结
2014/04/30 职场文书
2014年秋季开学演讲稿
2014/05/24 职场文书
经贸日语专业自荐信
2014/09/02 职场文书
信仰心得体会
2014/09/05 职场文书
2014县政府领导班子三严三实对照检查材料思想汇报
2014/09/26 职场文书
师德师风剖析材料
2014/09/30 职场文书
开展党的群众路线教育实践活动情况汇报
2014/11/05 职场文书
浅谈Redis存储数据类型及存取值方法
2021/05/08 Redis
深入解析MySQL索引数据结构
2021/10/16 MySQL