2012-04-09 21 views
5

我正在用python-crypto API编写一个Python2客户端,用于对XML文件进行数字签名,并且我有一个用Scala编写的服务来验证签名。我的Python代码看起来是这样的:在Python和Java/Scala之间插入RSA签名的问题

from Crypto.PublicKey import RSA 
from Crypto.Hash import SHA 
from os import urandom 
import logging 

... 
... 

生成密钥(密钥为2048):

self.__key = RSA.generate(self.keySize,urandom) 
self.__private_key = self.__key.exportKey() 
self.__public_key = self.__key.publickey().exportKey() 
with open(pubPath,'w') as fpub: 
    logging.info("Writing Public Key to %s" % pubPath) 
    fpub.write(self.__public_key) 
with open(priPath,'w') as fpri: 
    logging.info("Writing Private Key to %s" % priPath) 
    fpri.write(self.__private_key) 

而且用于读取键:

self.__private_key = fpri.read() 
self.__public_key = fpub.read() 
self.__key = RSA.importKey(self.__private_key) 

并进行数字签名

logging.debug('Data to sign: "%s"' % data) 
digest = SHA.new(data.strip()).digest() 
return str(self.__key.sign(digest, None)[0]) 

然后在Sc ALA/Java中,我使用以下命令:

package com.example.security 
import com.example.action.ActionRequest 
import java.io.BufferedInputStream 
import java.security.spec.X509EncodedKeySpec 
import java.security.KeyFactory 
import java.security.PublicKey 
import java.security.Signature 
import org.apache.log4j.Logger 

class SignatureSecurityManageer extends SecurityManagerTrait { 

    def loadPublicKey() : PublicKey = { 
     val stream : BufferedInputStream = new BufferedInputStream(this.getClass().getResourceAsStream("/com/example/security/key.der")) 
     var key = new Array[Byte](stream.available()) 
     stream.read(key) 
     KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(key)) 
    } 

    def securityFilter(req : ActionRequest) : Boolean = { 

     var parts = req.data.split("\n\n") 

     var log : Logger = Logger.getLogger(this.getClass()); 
     log.trace("Data \"%s\"".format(parts(0))) 
     log.trace("Sig \"%s\"".format(parts(1))) 

     var sg = Signature.getInstance("SHA1withRSA"); 
     sg.initVerify(loadPublicKey()) 
     sg.update(parts(0).trim().getBytes()) 
     sg.verify(parts(1).trim().getBytes()) 
    } 
} 

我变换由客户端生成的PEM公共密钥转换成二进制公共密钥,因此它可以被Java读取:

openssl rsa -in src/com/example/security/key.pub -inform PEM -out src/com/example/security/key.der -outform DER -pubin 

在运输,我使用双重新行将XML和签名分开。我意识到尾随空白会出现问题,所以我说的那些条/上述修剪和我检查日志,并验证该数据是相同的:

Python客户端:

2012-04-09 14:24:51,089: Data to sign: "<?xml version="1.0" ?><AgraData><package id="Local-Laptop" timestamp="1333945491074"><sensors><sensor id="SUMTEMP001" type="Temperature" units="C"><data>8</data></sensor><sensor id="SUMVOL001" type="Volume" units="l"><data>27</data></sensor><sensor id="SUMFLO001" type="FlowRate" units="l"><data>41.142</data></sensor></sensors></package></AgraData>" 

Scala的服务:

[2012-04-09 14:24:51,771] com.urbanalta.agrastore.security.SignatureSecurityManageer TRACE - Data "<?xml version="1.0" ?><AgraData><package id="Local-Laptop" timestamp="1333945491074"><sensors><sensor id="SUMTEMP001" type="Temperature" units="C"><data>8</data></sensor><sensor id="SUMVOL001" type="Volume" units="l"><data>27</data></sensor><sensor id="SUMFLO001" type="FlowRate" units="l"><data>41.142</data></sensor></sensors></package></AgraData>" 

但是在Scala服务中,当我尝试验证签名时它返回false。我认为某处我没有指定正确的签名/键类型,但我不确定在哪里。

+0

你能首先确认签名字符串和被验证的字符串*完全相同吗?你可以例如检查它们的SHA。编码可能会改变某些字符。 – Jus12 2012-04-10 07:00:17

+0

有几个想法......(顺便说一句,我从来没有用过Python)。 (1)Python的SHA方法与Scala中的SHA1方法相同吗?见[this](http://www.rsa.com/rsalabs/node.asp?id=2252)。 (2)检查Python方法是否在内部计算SHA1。尝试将'data.strip()'传递给'sign'方法而不是摘要。 – Jus12 2012-04-10 19:41:09

回答

1

这可能是this submission的另一个实例,它不仅仅是摘要,还包括AlgorithmIdentifier和已签名的摘要。