ホームページ バックエンド開発 Python チュートリアル python有证书的加密解密实现方法

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

Jun 10, 2016 pm 03:18 PM
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程序设计有所帮助。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPとPythonの選択:ガイド PHPとPythonの選択:ガイド Apr 18, 2025 am 12:24 AM

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

PHPとPython:彼らの歴史を深く掘り下げます PHPとPython:彼らの歴史を深く掘り下げます Apr 18, 2025 am 12:25 AM

PHPは1994年に発信され、Rasmuslerdorfによって開発されました。もともとはウェブサイトの訪問者を追跡するために使用され、サーバー側のスクリプト言語に徐々に進化し、Web開発で広く使用されていました。 Pythonは、1980年代後半にGuidovan Rossumによって開発され、1991年に最初にリリースされました。コードの読みやすさとシンプルさを強調し、科学的コンピューティング、データ分析、その他の分野に適しています。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Sublime Code Pythonを実行する方法 Sublime Code Pythonを実行する方法 Apr 16, 2025 am 08:48 AM

PythonコードをSublimeテキストで実行するには、最初にPythonプラグインをインストールし、次に.pyファイルを作成してコードを書き込み、Ctrl Bを押してコードを実行する必要があります。コードを実行すると、出力がコンソールに表示されます。

vscodeでコードを書く場所 vscodeでコードを書く場所 Apr 15, 2025 pm 09:54 PM

Visual Studioコード(VSCODE)でコードを作成するのはシンプルで使いやすいです。 VSCODEをインストールし、プロジェクトの作成、言語の選択、ファイルの作成、コードの書き込み、保存して実行します。 VSCODEの利点には、クロスプラットフォーム、フリーおよびオープンソース、強力な機能、リッチエクステンション、軽量で高速が含まれます。

Golang vs. Python:パフォーマンスとスケーラビリティ Golang vs. Python:パフォーマンスとスケーラビリティ Apr 19, 2025 am 12:18 AM

Golangは、パフォーマンスとスケーラビリティの点でPythonよりも優れています。 1)Golangのコンピレーションタイプの特性と効率的な並行性モデルにより、高い並行性シナリオでうまく機能します。 2)Pythonは解釈された言語として、ゆっくりと実行されますが、Cythonなどのツールを介してパフォーマンスを最適化できます。

メモ帳でPythonを実行する方法 メモ帳でPythonを実行する方法 Apr 16, 2025 pm 07:33 PM

メモ帳でPythonコードを実行するには、Python実行可能ファイルとNPPEXECプラグインをインストールする必要があります。 Pythonをインストールしてパスを追加した後、nppexecプラグインでコマンド「python」とパラメーター "{current_directory} {file_name}"を構成して、メモ帳のショートカットキー「F6」を介してPythonコードを実行します。

See all articles