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
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('来自这一客(http://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('来自这一客(http://www.jb51.net)的签名串')
if VerifyEVP.verify_final(StringSignature) == 1:
    print "字符串被成功验证。"
else:
    print "字符串验证失败!"

3.给证书加上密码

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

代码如下:

def passphrase(v):
    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')

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')

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

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')

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

(0)

相关推荐

  • 在Python中使用M2Crypto模块实现AES加密的教程

    AES(英文:Advanced Encryption Standard,中文:高级加密标准),是一种区块加密标准.AES将原始数据分成多个4×4字节矩阵来处理,通过预先定义的密钥对每个字节矩阵中的每个字节进行异或.替换.移位以及线性变换操作来达到加密的目的.密钥长度可以是128,192或256比特.     下面是一个利用Python M2Crypto库,并使用aes_128_ecb算法进行加密和解密的例子.首先介绍一下几个关键的点: 1.iv(Initialization vector),即初

  • Python AES加密模块用法分析

    本文实例讲述了Python AES加密模块用法.分享给大家供大家参考,具体如下: AES是新的一种加密模块.在上次介绍过在C语言中如何来OpenSSL中的DES.这次我们来看看Python自带的库如何来使用AES来加解密.其实二者的原理还是非常像,只是说在python中来做这个事情会比C语言要简单点,但是比起C#/Java还是有点点啰嗦.在C#/JAVA这种语言中,对于加密的源数据的处理,padding一般都会有完整的实现.我在上次C语言中也处理过这个问题.在python库中,也是需要自己来处理

  • python使用rsa加密算法模块模拟新浪微博登录

    PC登录新浪微博时,在客户端用js预先对用户名.密码都进行了加密,而且在POST之前会GET一组参数,这也将作为POST_DATA的一部分.这样,就不能用通常的那种简单方法来模拟POST登录(比如人人网). 通过爬虫获取新浪微博数据,模拟登录是必不可少的. 1.在提交POST请求之前,需要GET获取四个参数(servertime,nonce,pubkey和rsakv),不是之前提到的只是获取简单的servertime,nonce,这里主要是由于js对用户名.密码加密方式改变了. 1.1 由于加密

  • Python使用PyCrypto实现AES加密功能示例

    本文实例讲述了Python使用PyCrypto实现AES加密功能.分享给大家供大家参考,具体如下: #!/usr/bin/env python from Crypto.Cipher import AES import base64 import os # the block size for the cipher object; must be 16, 24, or 32 for AES BLOCK_SIZE = 32 # the character used for padding--with

  • python中的hashlib和base64加密模块使用实例

    看到好几位博主通过对模块的各个击破学习python,我也效法一下,本篇说一下python中加密涉及到的模块. hashlib hashlib模块支持的加密算法有md5 sha1 sha224 sha256 sha384 sha512(加密原理请参考此处),使用起来也很简单. 以md5加密为例,有两种方法: 一. 追加模式 代码示例: 复制代码 代码如下: import hashlib #引入hashlib模块    mm = hashlib.md5() #创建一个md5对象  mm.update

  • Python常见加密模块用法分析【MD5,sha,crypt模块】

    本文实例讲述了Python常见加密模块用法.分享给大家供大家参考,具体如下: 1. md5模块 md5.new([arg])     返回一个md5对象,如果给出参数,则相当于调用了update(arg) md5.update(arg)   用string参数arg更新md5对象 md5.digest()         返回16字节的摘要,由传给update的string生成,摘要没有ascii字符 md5.hexdigest()    以16进制的形式返回摘要 import md5 a =

  • Python使用MD5加密字符串示例

    Python加密模块有好几个,但无论是哪种加密方式都需要先导入相应的加密模块然后再使用模块对字符串加密. 先导入md5加密所需模块: 复制代码 代码如下: import hashlib 创建md5对象 复制代码 代码如下: m = hashlib.md5() 生成加密串,其中 password 是要加密的字符串 复制代码 代码如下: m.update('password') 获取加密串 复制代码 代码如下: psw = m.hexdigest() 输出 复制代码 代码如下: print psw

  • Python的加密模块md5、sha、crypt使用实例

    MD5(Message-Digest Algorithm 5) 模块用于计算信息密文(信息摘要),得出一个128位的密文.sha模块跟md5相似,但生成的是160位的签名.使用方法是相同的. 如下实例是使用md5的: 复制代码 代码如下: # /usr/bin/python # -*- coding:utf-8 -*- import base64 try:     import hashlib     hash = hashlib.md5() except ImportError:     #

  • Python使用Pycrypto库进行RSA加密的方法详解

    密码与通信 密码技术是一门历史悠久的技术.信息传播离不开加密与解密.密码技术的用途主要源于两个方面,加密/解密和签名/验签 在信息传播中,通常有发送者,接受者和窃听者三个角色.假设发送者Master想要写信给接受者Ghost,可是又不想信的内容被别人看到,因此Master需要先对信加密,而Ghost收到信之后又能解密.这样别的人即使窃听盗取了密文也无法解密.其次,如果窃听者并不像破译内容,而是伪造Master发消息给Ghost,那么Master发消息前就得先对机密内容进行签名. 密码技术 为了进

  • python文件的md5加密方法

    本文实例讲述了python文件的md5加密方法.分享给大家供大家参考,具体如下: 简单模式: from hashlib import md5 def md5_file(name): m = md5() a_file = open(name, 'rb') #需要使用二进制格式读取文件内容 m.update(a_file.read()) a_file.close() return m.hexdigest() if __main__ == '__init__': print md5_file('d:/

随机推荐