Слияние кода завершено, страница обновится автоматически
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 21 20:33:02 2015
@author: yhadmin
"""
from Crypto.PublicKey import RSA
import urllib
import urllib2
import time
import json
from Crypto.Signature import PKCS1_v1_5 as pk
from Crypto.Cipher import AES
import base64
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA
import random
#with open('./rsa_public_key.pem') as publicfile:
# keydata = publicfile.read()
# publickey = RSA.importKey(keydata)
# print publickey
publickey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIL3fhy0WrAw3PTWFJ8rv3HqAISZBO6zqNP0R2
xdaFAOmyUSIj9b68es63t4rIsvcTD3FvVtT5tH81aGOz60nI4UhjRuGZt6L7GkiB3ZMQnFyRg+tb
+wXZzN3GuK7IXuNO//8zXQe6ZpDe4nw0xS//OmDczkFAmaeL5J85FJYxNwIDAQAB
-----END PUBLIC KEY-----"""
privatekey = """-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDWx87eZx9W/fFrh0kvRdGWJ7ETDEGUFMzSjO+lFzvGS7SBmboy
bvKe1A4GRyRXu0Y+tQpSVzS9CZYpFdlBH7pgwGXrNoJ11xX0aObW5ZR6xCW3uYB6
F6SLKIKQLPWNMf2TKOI2lKq9xCuhRFCU6tnO+sl5i342SXQGZUsF0rWrtwIDAQAB
AoGAaZiQ551xthZiBIjd/WTpN1bKY2AKOeDEFtx90gALPmHoHDPVbIhJtrbxMjr1
7kA/uALQUU1Yu3wkHI0GZFNSEOqRqCfEAEJVGv8jTsiLPGlln7m6kBPpE/7mVrG4
ecP0YtY1U1xP2iYpOCp6UcZz0Jdqq7wjnb1I5LBOTGzR73kCQQD16ofR6IK4wzPT
qxFArGfWel+YkZmRQ2+AGD2y2D8cQ1YsCStxXhG0y0XtV3Qp09OqbrzMFnw5u2r2
BHrGqbfTAkEA35Zvh59L6yNJFA0cZfD0+mm7ft23lHT0qdGm3JvgAG7vmvhyMnD0
L5M4CrxckRXxb64Umz5+F6U0k1CUehuSDQJBAL+jhTSPfU9+z2Ska017DXCW7Oh4
jrQlWT75pRs6afQchYrLmo8+P44k2tmazWvLJ6gpo/dnjmdvJmuSEhu/JwECQAew
ltllQyktJ4BHCyj+Zo6OQGKWoY+7jgahLUn9GnEpX5hG3zaY5+0S9SR5Yf2jcZBT
vmWweom5pttCNDkW5akCQGhUBj3Sq7D//M0QobmGmzCLKMKHgwgVUCdMtTvr1gDL
dffae+QyKX+cCprS5irhq71T2qjbbvOfIx8kBn5t0js=
-----END RSA PRIVATE KEY-----"""
print privatekey
merchantaccount='YB010000000xx'
URL='www.ruyue.com'
GUIDS={}
class MerchantAPI:
def doPost(self,url,values):
'''
post请求
参数URL
字典类型的参数
'''
req = urllib2.Request(url)
data = urllib.urlencode(values)
res = urllib2.urlopen(req, data)
ret = res.read()
return ret
def doGet(self,url,values):
'''
get请求
参数URL
字典类型的参数
'''
REQUEST = url + "?" + urllib.urlencode(values)
ret = urllib2.urlopen(REQUEST).read()
return ret
@staticmethod
def _pkcs7padding(data):
"""
对齐块
size 16
999999999=>9999999997777777
"""
size = AES.block_size
count = size - len(data)%size
if count:
data+=(chr(count)*count)
return data
@staticmethod
def _depkcs7padding(data):
"""
反对齐
"""
newdata = ''
for c in data:
if ord(c) > AES.block_size:
newdata+=c
return newdata
'''
aes加密base64编码
'''
def aes_base64_encrypt(self,data,key):
"""
@summary:
1. pkcs7padding
2. aes encrypt
3. base64 encrypt
@return:
string
"""
cipher = AES.new(key)
return base64.b64encode(cipher.encrypt(self._pkcs7padding(data)))
def base64_aes_decrypt(self,data,key):
"""
1. base64 decode
2. aes decode
3. dpkcs7padding
"""
cipher = AES.new(key)
return self._depkcs7padding(cipher.decrypt(base64.b64decode(data)))
'''
rsa加密
'''
def rsa_base64_encrypt(self,data,key):
'''
1. rsa encrypt
2. base64 encrypt
'''
cipher = PKCS1_v1_5.new(key)
return base64.b64encode(cipher.encrypt(data))
'''
rsa解密
'''
def rsa_base64_decrypt(self,data,key):
'''
1. base64 decrypt
2. rsa decrypt
示例代码
key = RSA.importKey(open('privkey.der').read())
>>>
>>> dsize = SHA.digest_size
>>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15
>>>
>>> cipher = PKCS1_v1_5.new(key)
>>> message = cipher.decrypt(ciphertext, sentinel)
>>>
>>> digest = SHA.new(message[:-dsize]).digest()
>>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel
>>> print "Encryption was correct."
>>> else:
>>> print "Encryption was not correct."
'''
cipher = PKCS1_v1_5.new(key)
return cipher.decrypt(base64.b64decode(data), Random.new().read(15+SHA.digest_size))
'''
RSA签名
'''
def sign(self,signdata):
'''
@param signdata: 需要签名的字符串
'''
h=SHA.new(signdata)
signer = pk.new(privatekey)
signn=signer.sign(h)
signn=base64.b64encode(signn)
return signn
'''
RSA验签
结果:如果验签通过,则返回The signature is authentic
如果验签不通过,则返回"The signature is not authentic."
'''
def checksign(self,rdata):
signn=base64.b64decode(rdata.pop('sign'))
signdata=self.sort(rdata)
verifier = pk.new(publickey)
if verifier.verify(SHA.new(signdata), signn):
print "The signature is authentic."
else:
print "The signature is not authentic."
'''
请求接口前的加密过程
'''
def requestprocess(self,mesdata):
"""
加密过程:
1、将需要的参数mes取出key排序后取出value拼成字符串signdata
2、用signdata对商户私钥进行rsa签名,生成签名signn,并转base64格式
3、将签名signn插入到mesdata的最后生成新的data
4、用encryptkey16位常量对data进行AES加密后转BASE64,生成机密后的data
5、用对方公钥publickey对encryptkey16位常量进行RSA加密BASE64编码,生成加密后的encryptkey
"""
# signdata=self.sort(mesdata)
values={}
values['merchantaccount']=merchantaccount
password = '1234567890123456' #app输入的密码
encryptkey=self.rsa_base64_encrypt(password, publickey)
signdata=json.dumps(mesdata)
print '需要签名的字符串为:'+signdata
signn=self.sign(signdata)
mesdata['sign']=signn
mesdata['GUID']='abcd1234' #app生成的
data=self.aes_base64_encrypt(json.dumps(mesdata),encryptkey)
rdata={}
rdata['merchantaccount']=merchantaccount
rdata['data']=data
rdata['encryptkey']=encryptkey
print "要发送的data",rdata
return rdata
'''
对返回结果进行解密后输出
'''
def result_decrypt(self,result):
'''
1、返回的结果json传给data和encryptkey两部分,都为加密后的
2、用商户私钥对encryptkey进行RSA解密,生成解密后的encryptkey。参考方法:rsa_base64_decrypt
3、用解密后的encryptkey对data进行AES解密。参考方法:base64_aes_decrypt
'''
#从数据库中找到password = '1234567890123456'
result=json.loads(result)
account = result['merchantaccount']
kdata=result['data']
import db
password=db.find.where(username=account).password
encryptkey = self.rsa_base64_encrypt(password,publickey)
if result['encryptkey']==encryptkey:
kdata=result['data']
rdata=self.base64_aes_decrypt(kdata,password)
print '解密后的data='+rdata
session_key = result['GUID'] #避免重发攻击
if GUIDS[account] != session_key:
GUIDS[account]=session_key
return self.success()
return self.error()
def testCreditPayAsync(self):
'''
生成公钥私钥对过程:
生成私钥:openssl genrsa -out rsa_private_key.pem 1024
根据私钥生成公钥: openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
这时候的私钥还不能直接被使用,需要进行PKCS#8编码:
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)
加密过程:
1、将需要的参数mes取出key排序后取出value拼成字符串signdata
2、用signdata对商户私钥进行rsa签名,生成签名signn,并转base64格式
3、将签名signn插入到mes的最后生成新的data
4、用encryptkey16位常量对data进行AES加密后转BASE64,生成机密后的data
5、用对方公钥publickey对encryptkey16位常量进行RSA加密BASE64编码,生成加密后的encryptkey
6、将merchantaccount,第四部加密后的data,第五步加密后的encryptkey作为参数post请求给URL http://xxxx/xxx/api/xxx/xxx/xxx/xxx
7、返回的结果json传给data和encryptkey两部分,都为加密后的
8、用商户私钥对encryptkey进行RSA解密,生成解密后的encryptkey。参考方法:rsa_base64_decrypt
9、用解密后的encryptkey对data进行AES解密。参考方法:base64_aes_decrypt
'''
transtime=int(time.time())
od=str(Random.random.randint(10, 100000))
mesdata={"merchantaccount":merchantaccount,"cardno":"xxxx758xxxx23xxxx","validthru":"04xx","cvv2":"200","phone":"1581xxxxxxx",
"orderid":"33hhkssseef3u"+od,"transtime":transtime,"currency":156,"amount":2,"productcatalog":"1","productname":"","productdesc":"",
"userip":"192.168.5.251","identityid":"ee","identitytype":6,"other":"","callbackurl":"http://IP/webtest/callback.do"}
values=self.requestprocess(mesdata)
url='http://'+URL+'/xxxx'
print url
result=self.doPost(url, values)
print result
rdata=json.loads(self.result_decrypt(result))
self.checksign(rdata)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )