Tôi đang viết một khách hàng bằng Python2 với API python-crypto để ký một tệp XML và tôi có một dịch vụ được viết bằng Scala giả sử để xác minh chữ ký. mã Python của tôi trông giống như sau:Sự cố nội suy chữ ký RSA giữa Python và Java/Scala
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from os import urandom
import logging
...
...
Để tạo các phím (keysize là 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)
Và để đọc trong các phím:
self.__private_key = fpri.read()
self.__public_key = fpub.read()
self.__key = RSA.importKey(self.__private_key)
Và để ký
logging.debug('Data to sign: "%s"' % data)
digest = SHA.new(data.strip()).digest()
return str(self.__key.sign(digest, None)[0])
Sau đó, trong Sc ala/Java, tôi sử dụng như sau:
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())
}
}
tôi chuyển đổi khóa công khai PEM tạo ra bởi các khách hàng vào một khóa công khai nhị phân để nó có thể được đọc bởi Java:
openssl rsa -in src/com/example/security/key.pub -inform PEM -out src/com/example/security/key.der -outform DER -pubin
Trong việc vận chuyển, Tôi tách XML và chữ ký với hai dòng mới. Tôi nhận ra dấu khoảng trắng có thể trình bày vấn đề vì vậy tôi thêm những dải/Trims trên và tôi kiểm tra các bản ghi và xác minh rằng dữ liệu là giống hệt nhau:
Python Chủ đầu tư:
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>"
Dịch vụ 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>"
Nhưng trong dịch vụ Scala, nó trả về false khi tôi cố gắng xác minh chữ ký. Tôi nghĩ rằng một nơi nào đó tôi không xác định đúng chữ ký/loại khóa, nhưng tôi không chắc chắn ở đâu.
Trước tiên bạn có thể đảm bảo rằng chuỗi đã ký và chuỗi đã được xác minh là * chính xác * giống nhau không? Ví dụ, bạn có thể kiểm tra SHA của chúng. Có thể mã hóa đã thay đổi một số ký tự. – Jus12
Một vài suy nghĩ ... (BTW, tôi chưa từng sử dụng Python). (1) Phương pháp SHA của Python có giống với phương pháp SHA1 trong Scala không? Xem [this] (http://www.rsa.com/rsalabs/node.asp?id=2252). (2) Kiểm tra xem phương thức Python có tính toán SHA1 trong nội bộ hay không. Hãy thử chuyển 'data.strip()' sang 'sign' method thay cho digest. – Jus12