Python + PHP + RSA 实现加密(解决Python-RSA无法解密一般字符串的问题)

来源:互联网 发布:matlab矩阵循环赋值 编辑:程序博客网 时间:2024/05/16 14:26

摘要

微信校园卡需要一个能够加密的Python中继和PHP后台,由于是对短字符串的加密,并且考虑到效率,所以想要使用一种非对称加密的方法进行加密,RSA就是其中一种

最终实现的效果是:PHP后台对数据进行加密后生成二维码,通过扫码枪输入到Python中继后,通过与后台通信判定当前二维码合法性(当然,这只是个DEMO,生产环境下,私钥应该是放在Python端的)

严重的问题

(1) RSA模块使用base64转码后的密文进行解密操作
问题在于在PHP中用了base64进行解码 T.T
具体参考下文中的:《Python base64编码的问题》

(2) Python-RSA 模块使用的public key 开头是—–BEGIN RSA PUBLIC KEY—–,而有些模块,如PHP的,文件开头就不是这个,这会导致public key文件读取失败:

这里写图片描述

需要注意的问题

  1. url转码(urlencode)
  2. RSA加密等级对系统速度的影响
  3. 最好用POST传递哦,安全又方便

PHP实现

参考: http://blog.csdn.net/wsliangjian/article/details/45867351


加密信息,并生成二维码

public function gen_qr(){    $uid = "201621060701";    $time = $this->get_time();    $text = $uid.$time;    $text = $this->rsa->encrypt_public($text);    if(FALSE == $text){        echoJSON(500,"加密失败");    }    $data = [        'en_text' => $text,        'text' => $uid.$time    ];    /* 生成二维码并显示 */    show_QR();}

RSA封装

<?php/* 使用openssl实现非对称加密 */class RSA{    private $private_key = '-----BEGIN RSA PRIVATE KEY-----MIICWgIBAAKBgQC8bNv2gSyf60muXcXkrOsAo3DkONaDSCFccu6WsvKrHHuXTEmZUdfvyrTFj1oLEK9yqgBOPTb9aVpejPAyhYDwECUF/KHOWjaPMHhgSqfrfLEag/V+dfasdffasdfdfefadvBTsNmxnNPa/CCFC11Lbch2GvEE1aWx8VsQx+f91x3sq3sqvKHJjqQD+ZOLKaoh6zWeQhHn9nNPNUVsQx+f91x3sqVsQx+f91x3sqVsQx+f91xsBTsNmxnNPa/CCFC11Lbch2GvEE1aWx8VsQx+f91x3sqwefgsdgadg234g234gegavKHJjqQD+ZOLKaoh6zWeQhHn9nNPNUJBTsNmxnNPa/CCFC11Lbch2GvEE1aWx8fdvKHJjqQD+ZOLKaoh6zf91x3sqBTsNmxnNPa/CCsdscssFC11Lbch2GvEE1aWx8VsvKHJjqQD+ZOLKaoh6zWeQhHn9nNPNUgT47jtJGL+EFuHmQI/LBTsNmxnNPa/CCFCvKHJjqQD+ZOLKaoh6zWeQhHn9nNPNUR8+ZuqJzgo-----END RSA PRIVATE KEY-----';    private $public_key = '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8bNv2gSyf60muXcXkrOsAo3DkONaDSCFccu6WsvKrHHuXTEmZUdfvyrTFj1oLEK9yqgBOPTb9aVpejPAyhYDwECUF/KHOWjaPMHhgSqfrfLEag/V+rT86qdpj0HVgMDPw4ctfpHBe6rTMJnC+mUbfaWLOS8fsEDAfIwWEf5/jGQIDAQAB-----END PUBLIC KEY-----';    /* 使用公钥加密 */    public function encrypt_public($data){        /* 判断公钥是否是可用的 */        $pu_key = openssl_pkey_get_public($this->public_key);        if($pu_key==FALSE) {            return FALSE;        }else{            $encrypted = "";            openssl_public_encrypt($data,$encrypted,$pu_key);//公钥加密            $encrypted = base64_encode($encrypted);            return $encrypted;        }    }    /* 使用密钥解密 */    public function decrypt_private($encrypted_data){        /* 判断私钥是否是可用的 */        $pi_key =  openssl_pkey_get_private($this->private_key);        if($pi_key==FALSE) {            return FALSE;        }else{            $decrypted = "";            openssl_private_decrypt(base64_decode($encrypted_data),$decrypted,$pi_key);//私钥解密            return $decrypted;        }    }}?>

Python base64编码的问题

Python环境下RSA编解码请参考:
https://stuvel.eu/files/python-rsa-doc/usage.html
http://www.cnblogs.com/renfanzi/p/6062261.html

但是,在将PHP中所生成的加密字符串传入Python中时,出现了字符串冲突的问题:

这里写图片描述

在网上搜索了以下资料,发现并没用什么可用的讯息。 然后,通过debug RSA模块的加密函数的返回值后发现,输出的大概是这么个东西:

b"%k\xd9\xb6\xc5\xde\x19\x86\xf00#\x80s\x17\x9b\xb5\x04]\x96\x93\xf9\xd6\x96\xb5j\\\xbb\xbf\xbd\x8f\x07^+\xdfL8=\xee\xf .......

那么答案就很明显了:这TM是个base64 encode过的bytes字符串

因此,我们需要对从PHP处生成的字符串做一些些转码,整个实现的代码如下:

import rsaimport base64# Warning : 这里必须用'rb'模式打开,或者在f.read()后使用encode()函数进行转码with open('./rsa_key/rsa_private_key.pem','rb') as f:    privkey = rsa.PrivateKey.load_pkcs1(f.read())    # ALTER :     # privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())while(1):    try:        encrypted_str = input(">>")        # 将str转码成bytes        encrypted_str = encrypted_str.encode()        # 将bytes进行base64编码        encrypted_str = base64.b64decode(encrypted_str)        # 进行RSA解码        decrypted_str = rsa.decrypt(encrypted_str, privkey)    except Exception as e:        print("FAIL, Try Again PLS")        continue    # 将bytes转为str    decrypted_str = decrypted_str.decode()    print(decrypted_str)

Python 通过POST与web后台交互

import web # 参考web.pyimport timewhile(1):    text = input('>>')    url = "http://www.wunyungsumu.cn/WechatCard/u"    values = {        'text' : text    }    result     = web.post(url=url, values=values)    result_str = str(result, encoding="utf-8")    if(result_str=='0'):        print("Failed, Try Again Please !")        continue    uid = result_str[:12]    tim = result_str[12:]    print("uid:",uid," time:",tim)

Python 网络web封装

web.py

import urllib.parse as upimport urllib.request as urdef get(url):    req = ur.Request(url)    response = ur.urlopen(req)    return response.read()def post(url,values):    data = up.urlencode(values).encode(encoding='UTF8')    req = ur.Request(url, data)    response = ur.urlopen(req)    return response.read()# url = 'http://umbra.nascom.nasa.gov/cgi-bin/eit-catalog.cgi'# values = {#         'obs_year': '2011',#         'obs_month': 'March'#     }## print(post(url=url, values=values))

实现效果

这里写图片描述

这里写图片描述

原创粉丝点击