python RSA签名

这周一个项目客户提供了一份对接文档要求用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签名出来的东西一样了, 但是最后多了一个“=”。 这个我不知道为什么会多了一个“=”。  如果哪位高手知道,解释一下。


写的有点凌乱啊,望看的见谅。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值