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进阶教程之函数参数的多种传递方法
Aug 30 Python
Python open()文件处理使用介绍
Nov 30 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
Feb 19 Python
对Python3 解析html的几种操作方式小结
Feb 16 Python
利用python计算时间差(返回天数)
Sep 07 Python
python 变量初始化空列表的例子
Nov 28 Python
pytorch查看torch.Tensor和model是否在CUDA上的实例
Jan 03 Python
浅谈spring boot 集成 log4j 解决与logback冲突的问题
Feb 20 Python
TensorFlow的reshape操作 tf.reshape的实现
Apr 19 Python
scrapy结合selenium解析动态页面的实现
Sep 28 Python
详解Selenium 元素定位和WebDriver常用方法
Dec 04 Python
python中K-means算法基础知识点
Jan 25 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个人网站架设连环讲(一)
2006/10/09 PHP
php 数组二分法查找函数代码
2010/02/16 PHP
PHP调用Twitter的RSS的实现代码
2010/03/10 PHP
php统计时间和内存使用情况示例分享
2014/03/13 PHP
PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
php文件管理基本功能简单操作
2017/01/16 PHP
PHP文件系统管理(实例讲解)
2017/09/19 PHP
javascript之大字符串的连接的StringBuffer 类
2007/05/08 Javascript
(function($){...})(jQuery)的意思
2010/07/22 Javascript
js实现右下角可关闭最小化div(可用于展示推荐内容)
2013/06/24 Javascript
盘点javascript 正则表达式中 中括号的【坑】
2016/03/16 Javascript
使用bootstrap typeahead插件实现输入框自动补全之问题及解决办法
2016/07/07 Javascript
利用jQuery对无序列表排序的简单方法
2016/10/16 Javascript
nodejs mysql 实现分页的方法
2017/06/06 NodeJs
JavaScript实现数值自动增加动画
2017/12/28 Javascript
原生JS实现手动轮播图效果实例代码
2018/11/22 Javascript
微信小程序按钮点击跳转页面详解
2019/05/06 Javascript
Vue 页面权限控制和登陆验证功能的实例代码
2019/06/20 Javascript
Vue 使用Props属性实现父子组件的动态传值详解
2019/11/13 Javascript
小谈angular ng deploy的实现
2020/04/07 Javascript
详解vue 组件
2020/06/11 Javascript
[01:01:31]2018DOTA2亚洲邀请赛3月29日小组赛B组 Mineski VS paiN
2018/03/30 DOTA
Pyqt5如何让QMessageBox按钮显示中文示例代码
2019/04/11 Python
python批量下载抖音视频
2019/06/17 Python
python在新的图片窗口显示图片(图像)的方法
2019/07/11 Python
window7下的python2.7版本和python3.5版本的opencv-python安装过程
2019/10/24 Python
pd.DataFrame统计各列数值多少的实例
2019/12/05 Python
tensorflow mnist 数据加载实现并画图效果
2020/02/05 Python
读取nii或nii.gz文件中的信息即输出图像操作
2020/07/01 Python
python进度条显示-tqmd模块的实现示例
2020/08/23 Python
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
市场营销专业毕业生自荐信
2013/11/02 职场文书
银行自荐信怎么写
2015/03/05 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
Pytorch反向传播中的细节-计算梯度时的默认累加操作
2021/06/05 Python
Windows Server 2019 配置远程控制以及管理方法
2022/04/28 Servers