1. 程式人生 > >python實現aes加密解密,RSA簽名和驗籤,RSA加密解密,並呼叫介面

python實現aes加密解密,RSA簽名和驗籤,RSA加密解密,並呼叫介面

用python實現呼叫介面的示例程式碼,過程涉及到很多的加密演算法,值得分享一下。
首先公鑰和私鑰如何生成,並且能相容java平臺,嘗試了很多方法。最終決定用openssl命令
前提,需要安裝openssl,Crypto庫
生成公鑰私鑰對過程:
生成私鑰:

  1. openssl genrsa -out rsa_private_key.pem 1024
根據私鑰生成公鑰:

  1. openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
這時候的私鑰還不能直接被使用,需要進行PKCS#8編碼


  1. openssl pkcs8 -topk8 -
    in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt

命令中指明瞭輸入私鑰檔案為rsa_private_key.pem,輸出私鑰檔案為pkcs8_rsa_private_key.pem,不採用任何二次加密(-nocrypt)
這時候就獲得了一對公鑰和私鑰,只要拿到對方的公鑰,用自己的公鑰的格式替換就可以使用啦~~ 

我們最好把全域性變數給提出來,便於管理。這樣子就不用改程式碼都改一遍了


檔案Gl.py


  1. #!-*- coding:utf--*- 
  2. ''
  3. Created on 2013-6-15 
  4. @author: shangwei 
  5. ''' 
  6. ''
  7. 全域性變數 
  8. ''' 
  9. from Crypto.PublicKey import RSA 
  10. ''
  11. publickey為對方的公鑰 
  12. privatekey為商戶自己的私鑰 
  13. ''' 
  14. publickey = RSA.importKey(open('rsa_public_key.pem','r').read()) 
  15. privatekey=RSA.importKey(open('pkcs8_rsa_private_key.pem','r').read()) 
  16. merchantaccount='YB010000000xx' 
  17. URL='xxx.xxx.com'


  1. #!-*- coding:
    utf--*- 
  2.     ''
  3.     Created on 2013-5-24 
  4.     @author: shangwei 
  5.     ''' 
  6.     from Crypto import Random 
  7.     from Crypto.Cipher import PKCS1_v1_5 
  8.     from Crypto.Hash import SHA 
  9.     from hashlib import sha1 
  10.     from rsa import key, common, encrypt 
  11.     from urllib import urlencode 
  12.     import base64 
  13.     import hmac 
  14.     from Crypto.PublicKey import RSA 
  15.     import urllib 
  16.     import urllib2 
  17.     import time 
  18.     import json 
  19.     from Crypto.Signature import PKCS1_v1_5 as pk 
  20.     import Gl 
  21.     class MerchantAPI: 
  22.         def doPost(self,url,values): 
  23.             ''
  24.             post請求 
  25.             引數URL 
  26.             字典型別的引數 
  27.             ''' 
  28.             req = urllib2.Request(url) 
  29.             data = urllib.urlencode(values) 
  30.             res = urllib2.urlopen(req, data) 
  31.             ret = res.read() 
  32.             return ret 
  33.         def doGet(self,url,values): 
  34.             ''
  35.             get請求 
  36.             引數URL 
  37.             字典型別的引數 
  38.             ''' 
  39.             REQUEST = url + "?" + urllib.urlencode(values) 
  40.             ret = urllib2.urlopen(REQUEST).read() 
  41.             return ret 
  42.         @staticmethod 
  43.         def _pkcs7padding(data): 
  44.             ""
  45.             對齊塊 
  46.             size 16 
  47.             999999999=>9999999997777777 
  48.             """ 
  49.             size = AES.block_size 
  50.             count = size - len(data)%size 
  51.             if count: 
  52.                 data+=(chr(count)*count) 
  53.             return data 
  54.         @staticmethod 
  55.         def _depkcs7padding(data): 
  56.             ""
  57.             反對齊 
  58.             """ 
  59.             newdata = '' 
  60.             for c in data: 
  61.                 if ord(c) > AES.block_size: 
  62.                     newdata+=
  63.             return newdata 
  64.         ''
  65.         aes加密base64編碼 
  66.         ''' 
  67.         def aes_base64_encrypt(self,data,key): 
  68.             ""
  69.             @summary: 
  70.                 1. pkcs7padding 
  71.                 2. aes encrypt 
  72.                 3. base64 encrypt 
  73.             @return: 
  74.                 string 
  75.             """ 
  76.             cipher = AES.new(key) 
  77.             return base64.b64encode(cipher.encrypt(self._pkcs7padding(data))) 
  78.         def base64_aes_decrypt(self,data,key): 
  79.             ""
  80.             1. base64 decode 
  81.             2. aes decode 
  82.             3. dpkcs7padding 
  83.             """ 
  84.             cipher = AES.new(key) 
  85.             return self._depkcs7padding(cipher.decrypt(base64.b64decode(data))) 
  86.         ''
  87.         rsa加密 
  88.         ''' 
  89.         def rsa_base64_encrypt(self,data,key): 
  90.             ''
  91.             1. rsa encrypt 
  92.             2. base64 encrypt 
  93.             ''' 
  94.             cipher = PKCS1_v1_5.new(key) 
  95.             return base64.b64encode(cipher.encrypt(data)) 
  96.         ''
  97.         rsa解密 
  98.         ''' 
  99.         def rsa_base64_decrypt(self,data,key): 
  100.             ''
  101.             1. base64 decrypt 
  102.             2. rsa decrypt 
  103.             示例程式碼 
  104.            key = RSA.importKey(open('privkey.der').read()) 
  105.             >>> 
  106.             >>> dsize = SHA.digest_size 
  107.             >>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15 
  108.             >>> 
  109.             >>> cipher = PKCS1_v1_5.new(key) 
  110.             >>> message = cipher.decrypt(ciphertext, sentinel) 
  111.             >>> 
  112.             >>> digest = SHA.new(message[:-dsize]).digest() 
  113.             >>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel 
  114.             >>> print "Encryption was correct." 
  115.             >>> else: 
  116.             >>> print "Encryption was not correct." 
  117.             ''
  118.             cipher = PKCS1_v1_5.new(key) 
  119.             return cipher.decrypt(base64.b64decode(data), Random.new().read(15+SHA.digest_size)) 
  120.         ''' 
  121.         RSA簽名 
  122.         ''
  123.         def sign(self,signdata): 
  124.             ''' 
  125.             @param signdata: 需要簽名的字串 
  126.             ''
  127.             h=SHA.new(signdata) 
  128.             signer = pk.new(Gl.privatekey) 
  129.             signn=signer.sign(h) 
  130.             signn=base64.b64encode(signn) 
  131.             return signn 
  132.         ''' 
  133.         RSA驗籤 
  134.         結果:如果驗籤通過,則返回The signature is authentic 
  135.              如果驗籤不通過,則返回"The signature is not authentic." 
  136.         ''
  137.         def checksign(self,rdata): 
  138.             signn=base64.b64decode(rdata.pop('sign')) 
  139.             signdata=self.sort(rdata) 
  140.             verifier = pk.new(Gl.publickey) 
  141.             if verifier.verify(SHA.new(signdata), signn): 
  142.                 print "The signature is authentic." 
  143.             else: 
  144.                 print "The signature is not authentic." 
  145.         def sort(self,mes): 
  146.             ''' 
  147.             作用類似與java的treemap, 
  148.             取出key值,按照字母排序後將value拼接起來 
  149.             返回字串 
  150.             ''
  151.             _par = [] 
  152.             keys=mes.keys() 
  153.             keys.sort() 
  154.             for v in keys: 
  155.                 _par.append(str(mes[v])) 
  156.             sep='
  157.             message=sep.join(_par) 
  158.             return message 
  159.         ''' 
  160.         請求介面前的加密過程 
  161.         ''
  162.         def requestprocess(self,mesdata): 
  163.             ''' 
  164.             加密過程: 
  165.             1、將需要的引數mes取出key排序後取出value拼成字串signdata 
  166.             2、用signdata對商戶私鑰進行rsa簽名,生成簽名signn,並轉base64格式 
  167.             3、將簽名signn插入到mesdata的最後生成新的data 
  168.             4、用encryptkey16位常量對data進行AES加密後轉BASE64,生成機密後的data 
  169.             5、用對方公鑰publickey對encryptkey16位常量進行RSA加密BASE64編碼,生成加密後的encryptkey 
  170.             ''
  171.             signdata=self.sort(mesdata) 
  172.             print '需要簽名的排序後的字串為:'+signdata 
  173.             signn=self.sign(signdata) 
  174.             mesdata['sign']=signn 
  175.             print mesdata 
  176.             encryptkey = '1234567890123456
  177.             data=self.aes_base64_encrypt(json.dumps(mesdata),encryptkey) 
  178.             print '加密後的data='+data 
  179.             values={} 
  180.             values['merchantaccount']=Gl.merchantaccount 
  181.             values['data']=data 
  182.             values['encryptkey']=self.rsa_base64_encrypt(encryptkey,Gl.publickey) 
  183.             return values 
  184.         ''' 
  185.         對返回結果進行解密後輸出 
  186.         ''
  187.         def result_decrypt(self,result): 
  188.             ''' 
  189.             1、返回的結果json傳給data和encryptkey兩部分,都為加密後的 
  190.             2、用商戶私鑰對encryptkey進行RSA解密,生成解密後的encryptkey。參考方法:rsa_base64_decrypt 
  191.             3、用解密後的encryptkey對data進行AES解密。參考方法:base64_aes_decrypt 
  192.             ''
  193.             result=json.loads(result) 
  194.             kdata=result['data'] 
  195.             kencryptkey=result['encryptkey'] 
  196.             print '返回的加密後的data='+kdata 
  197.             print '返回的加密後的encryptkey='+kencryptkey 
  198.             cryptkey=self.rsa_base64_decrypt(kencryptkey,Gl.privatekey) 
  199.             print '解密後的encryptkey='+cryptkey 
  200.             rdata=self.base64_aes_decrypt(kdata,cryptkey) 
  201.             print '解密後的data='+rdata 
  202.             return rdata 
  203.         def testCreditPayAsync(self): 
  204.             ''' 
  205.             生成公鑰私鑰對過程: 
  206.             生成私鑰:openssl genrsa -out rsa_private_key.pem 1024 
  207.             根據私鑰生成公鑰: openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout 
  208.             這時候的私鑰還不能直接被使用,需要進行PKCS#8編碼: 
  209.             openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt 
  210.             命令中指明瞭輸入私鑰檔案為rsa_private_key.pem,輸出私鑰檔案為pkcs8_rsa_private_key.pem,不採用任何二次加密(-nocrypt) 
  211.             加密過程: 
  212.             1、將需要的引數mes取出key排序後取出value拼成字串signdata 
  213.             2、用signdata對商戶私鑰進行rsa簽名,生成簽名signn,並轉base64格式 
  214.             3、將簽名signn插入到mes的最後生成新的data 
  215.             4、用encryptkey16位常量對data進行AES加密後轉BASE64,生成機密後的data 
  216.             5、用對方公鑰publickey對encryptkey16位常量進行RSA加密BASE64編碼,生成加密後的encryptkey 
  217.             6、將merchantaccount,第四部加密後的data,第五步加密後的encryptkey作為引數post請求給URL http://xxxx/xxx/api/xxx/xxx/xxx/xxx 
  218.             7、返回的結果json傳給data和encryptkey兩部分,都為加密後的 
  219.             8、用商戶私鑰對encryptkey進行RSA解密,生成解密後的encryptkey。參考方法:rsa_base64_decrypt 
  220.             9、用解密後的encryptkey對data進行AES解密。參考方法:base64_aes_decrypt 
  221.             ''
  222.             transtime=int(time.time()) 
  223.             od=str(random.randint(10, 100000)) 
  224.             mesdata={"merchantaccount":Gl.merchantaccount,"cardno":"xxxx758xxxx23xxxx","validthru":"04xx","cvv2":"200","phone":"1581xxxxxxx", 
  225.     "orderid":"33hhkssseef3u"+od,"transtime":transtime,"currency":156,"amount":2,"productcatalog":"1","productname":"","productdesc":"", 
  226.     "userip":"192.168.5.251","identityid":"ee","identitytype":6,"other":"","callbackurl":"http://IP/webtest/callback.do"} 
  227.             values=self.requestprocess(mesdata) 
  228.             url='http://'+Gl.URL+'/xxxx
  229.             print url 
  230.             result=self.doPost(url, values) 
  231.             print result 
  232.             rdata=json.loads(self.result_decrypt(result)) 
  233.             self.checksign(rdata) 
  234.     if __name__=='__main__

知識點:
除錯程式碼的時候也遇到了一些小問題和技巧
import的時候,如果有同名的類可以起個別名。不然會有報錯,告訴這個類找不到某個方法from Crypto.Cipher import PKCS1_v1_5,from Crypto.Signature import PKCS1_v1_5 as pk,這個需要注意一下
另外,如果想將字典內的單引號都變為雙引號,可以用json.dumps方法

相關推薦

python實現aes加密解密RSA簽名RSA加密解密呼叫介面

用python實現呼叫介面的示例程式碼,過程涉及到很多的加密演算法,值得分享一下。首先公鑰和私鑰如何生成,並且能相容java平臺,嘗試了很多方法。最終決定用openssl命令前提,需要安裝openssl,Crypto庫生成公鑰私鑰對過程:生成私鑰: openssl ge

Python實現MD5&RSA簽名

用pem檔案 pub_key.pem -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChNn3wKRtPmxaKq2dKsfMn6sO6AKxvtxZgNdh7 HBWq

非對稱加密簽名加密解密的Java語言實現

本文采用java.security包的簽名和驗籤。採用A的私鑰簽名傳送至B,B採用A的公鑰進行驗籤。 加解密可以私鑰加密、公鑰解密(或者公鑰加密、私鑰解密)。 一般用於銀行報文傳輸、支付寶、微信、銀行以及各大銀行的資料交換。 package com.example.demo; impo

微信小程式-RSA簽名加密解密

title: 【小程式】RSA簽名 type: categories date: 2017-05-27 17:01:15 categories: 小程式 tags: [RSA, 簽名] 一個適用於微信小程式的RSA簽名加密庫。 使

Python與Java之間的簽名問題

// 最新碰到一個需求, 需要同java下的簽名做驗籤, 感覺有必要總結下: // 整個過程碰到以下幾個問題: /* 1、如何生成指定的公私鑰? # 使用linux指令openssl, openssl這個東西是真的強, (證書問題, 加解密問題, 公私鑰問題等)都

小王的尷尬日常(四)--openssl 實現國密演算法(簽名

昨天呢,更新了加密和解密的實現,今天我們接著來簽名和驗籤。 還是按照王氏慣例先說一下這個理論知識: 下列符號適用於本部分。 A,B:使用公鑰密碼系統的兩個使用者。 a,b: Fq中的元素,它們定義Fq上的一條橢圓曲線E。 2dA:使用

CSP應用開發-簽名

下面程式碼實現了呼叫CSP實現資料的簽名和驗籤,函式中有些細節沒有處理好,但總體流程上應該是沒有問題的,測試通過: //本程式通過呼叫CSP實現簽名及驗籤功能 #include "stdafx.h" #include <windows.h> #include

深入淺出數字簽名

數字簽名是什麼?1.鮑勃(伺服器)有兩把鑰匙,一把是公鑰,另一把是私鑰。2.鮑勃把公鑰送給他的朋友們----帕蒂(客戶端1)、道格(客戶端2)、蘇珊(客戶端3)----每人一把。3.蘇珊(客戶端3)給鮑勃(伺服器)寫信,寫完後用鮑勃的公鑰加密,達到保密的效果。4.鮑勃收信後,

iOS中使用Openssl X509證書進行字串簽名

利用openssl 和x509證書對字串進行簽名和驗籤 //簽名 -(NSString *)rsaSignStringwithString:(NSString *)stringToSign { _signErrorMessage = [[NSStringalloc]ini

Python實現AES加密解密

import base64 from Crypto.Cipher import AES def aes_encrypt(value): ''' >>> aes_en

python 實現AES加密解密

aes port 加密算 偏移量 blog utf-8 加密和解密 sda return 參考 https://blog.csdn.net/zhchs2012/article/details/79032656 AES加密算法是一種對稱加密算法, 他有一個密匙, 即用來加密,

C#自定義RSA加密解密RSA簽名驗證類實例

狀態 share normal evel thumb weight encrypt security clas 本文實例講述了C#自定義RSA加密解密及RSA簽名和驗證類。分享給大家供大家參考。具體分析如下: 這個C#類自定義RSA加密解密及RSA簽名和驗證,包含了RSA

RSA加密解密簽名的原理及方法

二、RSA加密、簽名區別   加密和簽名都是為了安全性考慮,但略有不同。常有人問加密和簽名是用私鑰還是公鑰?其實都是對加密和簽名的作用有所混淆。簡單的說,加密是為了防止資訊被洩露,而簽名是為了防止資訊被篡改。這裡舉2個例子說明。 第一個場景:戰場上,B要給A傳遞一條訊息,內容為某一指令。 RSA的加密過

Python實現AES加密(對稱加密)

from Cryptodome.Cipher import AES from binascii import b2a_hex,a2b_hex from Cryptodome import Random class AesEncryption(object):

C# RSA加密解密、加簽、、支援JAVA格式公鑰私鑰、PEM格式公鑰私鑰、.NET格式公鑰私鑰 -變態模式【支援私鑰加密公鑰解密】(二)

RSA變態模式:【私鑰加密,公鑰解密】 一般這種寫法都是JAVA弄的。.NET原生不支援。為啥,我也不清楚,大概是因為安全性問題吧,畢竟公鑰是人人都可是持有的。私鑰只有自己擁有。 簽名一直都是【私鑰加簽、公鑰驗籤】只為證明該訊息是你發出來的。 這裡使用了BouncyC

C# RSA加密解密RSA簽名驗證

using System; using System.Text; using System.Security.Cryptography; namespace DotNet.Utilities { /// <summary> /// RSA加密解密及R

C# RSA加密解密、加簽、、支援JAVA格式公鑰私鑰、PEM格式公鑰私鑰、.NET格式公鑰私鑰、一般模式【支援公鑰加密私鑰解密】(一)

2017-12-04日更新:增加支援微信支付。程式碼註釋中//☆☆☆☆.NET 4.6以後特有☆☆☆☆的別用,那個不對。 RSA非對稱加密。簡明扼要吧,直說乾貨。(在此特別感謝下貳進位制,提供JAVA版的公鑰私鑰) C#RSA加簽解籤加密比較常見,一般遇到的問題是非.NET

RSA用祕鑰簽名 加密解密

一 .下載openssl檔案 匯入二.新建類程式碼如下#import <Foundation/Foundation.h>typedefenum {    KeyTypePublic = 0,

【HAVENT原創】前端使用 jsrsasign 進行 RSA 加密解密簽名

最近因專案需求,需要配合 JAVA 後端返回的簽名,在 H5 網頁中做驗籤功能。網上搜了一下發現了 

PYTHON自動化Day6-函式多個返回值匿名函式、列表生成式三元運算子os模組sys模組時間模組字典排序資料庫操作加密(md5)

一.函式多個返回值和匿名函式 #函式返回多個值,用一個變數接收 def say(): num1=1 num2=2 num3=3 return num1,num2,num3 res=say() print(res) #打印出來是元組。 函式如果返回多個值的話,會把返回的