您的位置:首页 > 编程语言 > Python开发

python RSA签名

2015-06-14 08:08 621 查看
这周一个项目客户提供了一份对接文档要求用RSA数字签名,客户提供的是java的demo,但是自己不想用java来做,想用python来实现,就自己研究了下python下RSA签名。

先是研究了java-demo的流程和逻辑(因为是公司项目客户提供的,不便对外公开),基本的流程是这样的:

1)先根据私钥KEY字符串,获取私钥对象(PrivateKey)

私钥KEY----------就是一个长字符串

比如下面这个是我自己用openssl生成的(MIIEpQIBAAKCAQEA9JPHRFaWOhi7PXZz/Kmun/ldJrd+YQy6diU2eFijVooL8NDG

4dsOojUpT9FhAUedXcDZrYN3BstFcaGRJQouyXZsbJjyFL8WNLLGFIwdcv1pTGve

cLOEdU1Rl+E4wCznYflxcUN3ngZQo7cN/la2poM1k/epR8UsWiH8wQj+v7FHMrt4

XMhVSVAqslfhs6yqJQuQwu3YiaspZVySAywaFFveLCcedKPrlZYoN9Q1Qg7hyXZ+

hqIPIyXBHFU721GqlDJ8K6lCXxjNK7xFWwo1QzLAwdfLA0ZJ1K00+4nv9E1JUcbX

emhDJHvyZ9O/ExRqdykkE6CAJD3tZkjhQwERnwIDAQABAoIBABQVxrl/+tpOiaHk

hmXrcWHF0raJPyGtL+rf53c+oDtNHunp20tU+ACuKPRbF4JJZUz7t2SedTnjm5JX

WFoYWftFdGX+sXKutp4hSE8Lqqd01B7ohN3wgCI59UdpwYVWqrHLEFvi1IHvttOb

BtUqPdmy0MWUAxzXvmqwe9dGa9VGCp55HezZo0nDkwg8s7h/CKndxmGCvFX/O5iV

RaJgUOkQ9iRp8v1M3ri/XBvt1BmAUzFvXs3RNmF3/fKsvOCINFIGnZt+zyW7s7XA

RBgOluorDLdMusvxy9qrGspc3U8L6Uf7xsHKwvaAVD/RLP03FopNkg8HPphikbQA

naoWzKECgYEA/giQ3qSJfNH/0TELayYVzEq3MYOEc/tiI1YrUUXLTJ7rQ3yZSjt7

HMIgjPzO6Ek4iVdVX0QnNNvD9To40blr5KykeIoAOyta7hEAvZS4uMue1YXkW8i2

YpQJ9BzNho0SpHyB13/7TT9l9kyNSqemOVrDfvo24d4S7YafhBiNXOkCgYEA9nh4

+GCmV6+XR7lwbMrp3JLE/xpyiGK8P27COT22pT9Q3in8BSgjMa+vmJnGase6oQr6

xcd5Odqg5YmCs+T2MLoJg0sSBfCJxASRZPDnpz2MjTordm09PkauOCSsoq1IhH5E

xkDw97zIm1m1h87W8Zd+E500E687vRBanEzFxUcCgYEAwdwNmiqcVWn4vE6eNSW6

Ss3V4W5JPS1g5jCTHBGUJKO+TCEg5hpgSEEJEC65Q2DlSUIhf3MGLHttno3Q4JOM

99ScKvS9WmoqmTTWiNae5T9WtgHYlAam0LHCqsz0NzMfP/FYMPmU8I1qJTykMo2f

93MBb7xI97M+ZI9w2iDWeEkCgYEAu5G1ZjiPfv3XYDNE1taZoU5k80taTGbvokqV

LuDDZgDIdzp2XCpOllqAhN7KPKshYbusWuXSYO/8MJM0z9j4bt61rKBt5+1FutJL

IAmiEglqNHRHbUn3KLS7k2h9pRPAs2wwxLvZZn/aHzfnSaJku9kxjpW9cxmRmfGf

M4HNpLMCgYEAppL5J9jja2DrkRXoS9d4MvwaTlF/HsY2QRVRmlcvZddKXECcJ/fI

wmP7V/NNegLBsMukdrPez28bK1ci0iigO6dCjxnUZF1KDPzLwgsNG2Z9i54nsmOT

7xwfITqzE3gA2NSRNVY7oo8pwfGU1kEeySrMUxrRZ3EaerTS0JSIdSg=)

注意java提供的私钥KEY字符串是不包括开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----的。

因为openssl默认产生的PEM格式的是包括开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----的

根据提供的私钥KEY字符,demo中得到一个私钥对象(PrivateKey)。

下面是java得到私钥对象的代码:

public static PrivateKey getPrivateKey(String key) {

try {

byte[] keyBytes = (Base64.decodeBase64(key));

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

return privateKey;

} catch (Exception e) {

e.printStackTrace();

return null;

}

2)根据得到的私钥对象(PrivateKey),得到给定字符串的签名

public String sign(byte[] data, PrivateKey priKey) {

try {

Signature signature = Signature.getInstance("MD5WithRSA");

signature.initSign(priKey);

signature.update(data);

return Base64.encodeBase64URLSafeString(signature.sign());

} catch (Exception e) {

return null;

}

}

上面是java中的RSA的基本的流程,这里还有个验签的步骤,这里就不说了。

下面讲一下我在python中的使用,网上找了很多,也吸取了很多有用的东西,一开始用M2Crypto来做,这个库可以用pip install M2Crypto获取,但是这个库是依赖openssl的,先得安装openssl,我下得得官网得openssl-0.9.8-stable-SNAP-20150609.tar.gz,然后还得安装Perl,具体教程可以参考(http://www.cnblogs.com/ZhouL3777/archive/2012/10/21/2732890.html),我M2Crypto完全安装成功后,后面可能是我使用的问题,签名出来的字符串跟java签名出来的不一样,这个地方以后有空再深入研究下。后面讲下重点,使用pycrypto库。

使用pycrypto来做RSA签名:

1.因为pyCrypto库不依赖openssl库,所以直接pip install pycrypto 就可以安装成功(我的python2.7.9,pycrypto版本是2.6.1)

2.签名函数:

'''
RSA签名
'''
def sign(signdata):
'''
@param signdata: 需要签名的字符串
'''

h=MD5.new(signdata)
signer = pk.new(RSA.importKey(p))
signn=signer.sign(h)
# signn=base64.b64encode(signn,["-","_"])
signn=base64.urlsafe_b64encode(signn)
return signn


关键介绍下函数中p,这个是私钥字符串,但是开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----得加上。

我用客户提供的私钥字符串(不含开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----的),然后p是加上开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----的值。

# signn=base64.b64encode(signn,["-","_"])
signn=base64.urlsafe_b64encode(signn)

这两个其实是一样的效果,把“+”转成“-”,把“/”转成“_”而已。

这样签名出来的跟java签名出来的东西一样了, 但是最后多了一个“=”。 这个我不知道为什么会多了一个“=”。 如果哪位高手知道,解释一下。

写的有点凌乱啊,望看的见谅。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: