神级程序员带来:用python有证书的加密解密实现方法!

本文实例讲述了python有证书的加密解密实现方法。分享给大家供大家参考。具体实现方法如下:

最近在做python的加解密工作,同时加完密的串能在php上能解出来,网上也找了一些靠谱的资料,刚好也有时间我就总结了一下python在加密与解密这块的代码,今后可能还能用的上。相对于php而言python这块加解密组件较多的,分别是:

 

一、 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 = "[email protected]"

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程序设计有所帮助。

欢迎加入我的千人交流学习答疑群:125240963

猜你喜欢

转载自www.cnblogs.com/Python1234/p/9146747.html
今日推荐