2017-03-04 529 views
0

我正在嘗試簽署一些數據的代碼。在將openssl生成的私鑰轉換爲Java密鑰庫之後,我使用帶SHA256withRSA的Java Signature類。我試圖確認在openssl中從Java類返回的簽名,但出於某種原因,我無法獲得openssl來驗證。我將最終需要在iOS Swift 3中實現此簽名驗證,但在我找到一個庫之前,我想嘗試使用openssl標準檢查Java簽名。驗證Java簽名類簽名與OpenSSL

例如,我從我們的登錄服務器這種反應(簽名組爲()由Signature.sign給出的字節數組的base64編碼的版本):使用從Java Signature類

HTTP/1.1 200 OK 
Connection: keep-alive 
X-Powered-By: Undertow/1 
TokenSignature: WtHSxFAy6yO2Bepb4NgRxYhRUEmKS793gd1NBX/bDErBjD3CTiLA8p05RNIG8U96bkwyi/ZySmQVwQf2w4meHMDBBpf7AnCSd1yZeBDeuWChiP3pGdUb3yuGIAnJdlKFHjaElDaJ3eqZD7JZcpcNeZv6xSQUZVi+xgZiUCtnZTYUZmkoRltkcEEbIv0rkERIsMhuuKAuLli7x76/XCpwNZ8dGc356Zzsq/gRhh8BrGejGKDJh/1D1iWAI6tfnBufs0EBe0E5kVm++3QVHNawETSjglBtUvre4ineSW9eTgzYfamijw2fvXOLVYf0p7iCdXJDFb9Pgm5ZDLGW4t/y6A== 
Server: WildFly/10 
Content-Type: application/json 
Content-Length: 343 
Date: Mon, 06 Mar 2017 23:28:57 GMT 

{"tokenId":8728935,"studentID":8580329,"username":"pkirkland","deviceName":"iPhone","expirationDate":1488842937819,"blacklisted":false,"employeeType":"student","groups":[{"id":9235,"name":"Software","ldapName":"cn=Software, cn=Groups, dc=example, dc=com"},{"id":9257,"name":"Students","ldapName":"cn=Students, cn=Groups, dc=example, dc=com"}]} 

私鑰。

下面是在密鑰庫中的公鑰:

-----BEGIN PUBLIC KEY----- 
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzX3f7gRMdClWmI1c03Ut 
u60JYJuHiSEnm8bfBhfa/UuGSY7dIGPE9tBt83lF9t2VvEz3GYsqWidrasUEbnf+ 
zAIYddk/6Z4Mdin6qNpYyh71dpDBBnvB2GB2atAhJlmS8BkaSt8nRBi9kFppTciJ 
TxpA7w+TucHV7YabSObyRUif+bRRYhNB2sY1I2zHB5fsg2SpBVYlYGnff5O7boKY 
o0QPW5WBtBL84xRJcvPBG8Azz4nPZuuW5gGCWY4kMj6fdT5n3yBAj0VeOxR9DO9e 
zG+BtTnJj9+F12lSZanIQlxjKjYRebuBsF9WKelLuW0iNTUVObMIyc+CmJs45rOg 
VQIDAQAB 
-----END PUBLIC KEY----- 

下面是在密鑰庫中的私有密鑰(我們不是正式版):

-----BEGIN RSA PRIVATE KEY----- 
MIIEowIBAAKCAQEAzX3f7gRMdClWmI1c03Utu60JYJuHiSEnm8bfBhfa/UuGSY7d 
IGPE9tBt83lF9t2VvEz3GYsqWidrasUEbnf+zAIYddk/6Z4Mdin6qNpYyh71dpDB 
BnvB2GB2atAhJlmS8BkaSt8nRBi9kFppTciJTxpA7w+TucHV7YabSObyRUif+bRR 
YhNB2sY1I2zHB5fsg2SpBVYlYGnff5O7boKYo0QPW5WBtBL84xRJcvPBG8Azz4nP 
ZuuW5gGCWY4kMj6fdT5n3yBAj0VeOxR9DO9ezG+BtTnJj9+F12lSZanIQlxjKjYR 
ebuBsF9WKelLuW0iNTUVObMIyc+CmJs45rOgVQIDAQABAoIBAAkeOL16+1l8LBeA 
zkmjvW/CcdQTkqQHEJbc8DB5BoKOw1qoOC+jva2l+fr/upcFpgtA7wX3It31OdL3 
AwdT076BqUwxY6CeHrdvjWvIpH/zd7jXG3mKLEPJo/eBXLcy6k41DvGbjUZ8Qo0R 
NfL5nv4fkBoLeuaXL0Lm4iUN+loQlocfIbc0LSd4xk84S8OcjflBkBt/YdV7YsO5 
4QMgDdFJ6nZVNcGRnwoiCsIS+cdDNjukvuqFMnSz12/IZ3/HXBycy3GGB4cgVRJS 
iKtTckH7hr5iT07XT/McuUVEXKotxTzqAEoPwG07hqx4WQeTFnXakKBOyx1LLZSx 
dt64IwECgYEA8VSi+kOu3mMusaVTkHpvzRBDLCWYvyub+hgaix4OUMxcglFfxBqq 
EISx33ri2uIuwcfDXNqte0O7Cz80E/hTWKUDFlQu8u+yNvgPFkNAlGoqNz0/9oqA 
2vDHjDhGTpTkGWJ//8CYpFJe6NO75ewoPpzUhLxz+S/HeITD7LV4+lECgYEA2fuL 
zv16MHBhIOVlXPEiWWRhztPP8e02z0xNdZiMJIIQa5DA0y/TNrCwKBwu1/FLPU+z 
NP1EXEJLB9y+IdEVisb/GVmDspVgE6ksk7JukCgDBrDts+6aSMt1Xy3y+aFIcxhq 
m2a70rdyhrDC6/iSLc/sfqE3A0T3PHGXmaUrAMUCgYA4c1XUOLTU7Fplz4hmiV1R 
mHY+A2Vhgm/v5md/Fz6+A6+4BBTkqGATkRaScgpSrQnG5lV6iOR/qu47yUMDUNke 
KSs5s+NvjEYhuZC94mlezh6l4TvvDaLqk9v5nshDZWydy36pcoHCHkp5J94SAFXB 
n6nOis6OAXElbdjuq9xqoQKBgQC+Btf+fmKCz7UcpF4VA/FZ1HSfhW8GDDF3zaDJ 
H08slGYUH4C5mjuatbUbglYj0ioxLMWhMBjkBLa8B+eIO2l4Lbo9MxfoGuhCu3ws 
1aQk73yT3LGb5imBxDxx2PC0RbGPBH4LMygRrfKdEIMcivmEDnqweYIny3tsqenq 
+13dsQKBgE+OkJgU8cJgvVhI8QmFwJekfbB9HFOX7xZrcGdTA3/TaEPiuxiUvLaS 
jEOIi5nDW4ZfEPeggFQcaKdbTvbCRjfkJFye6ftm8soNhayuy35atZX7u9RYjvJ8 
PZptOTd/xFTWxpux4xfu6BrBRsJF73DLkOo2JLgcQTYVZEs0cFR6 
-----END RSA PRIVATE KEY----- 

是相同的公共從openssl密鑰。我知道私鑰看起來不同,因爲一個是PKCS#1,另一個是PKCS#8,但我不認爲這很重要,因爲它只是一種不同的存儲格式。

問題是,當我使用openssl驗證使用原始.pub窗體中的公鑰的簽名時,openssl告訴我「驗證失敗」。填充或編碼有什麼不同?如果是這樣,我能做些什麼來檢查使用openssl?

編輯

我試圖與它的用戶信息的JSON對象驗證簽名。代碼是基本的Java Signature代碼,但在這裏它是無論如何。

byte[] unsigned = objString.getBytes("UTF-8"); 
Signature signer = Signature.getInstance("SHA256withRSA"); 
signer.initSign(cs.getPrivateKey()); 
signer.update(unsigned); //prepare for signature 
byte[] signature = signer.sign(); 

其中objString是JSON對象,而cs是用於訪問數據庫中密鑰的加密單例。

編輯:我的合作伙伴確認我們正在檢查數據的二進制版本,這是失敗的。

爲了驗證OpenSSL的,我保存的簽名到一個txt文件,並將其傳遞給

base64 -d sig.txt> sig.bin 
openssl dgst -sha256 -verify pubkey.pub -signature sig.bin data.json 
+0

在編輯中添加了相關信息。 – jkaw4

回答

1

旁白:在一般的Java Signature API,和PKC簽名,使用散列,但產生的簽名不是哈希值。一個RSA簽名有時被鬆散地描述爲'加密哈希',但這在技術上是錯誤的,對於其他簽名方案甚至沒有加密的概念。

Signature.sign()生成的實際簽名是(如您的代碼所示)包含二進制文件的byte[]。您發佈的價值顯然是base64編碼,這是代表現代加密數據和其他二進制數據的常見方式。如果您將該base64 轉換回二進制,它至少會驗證SHA256散列的有效PKCS1v1.5'類型1'塊的驗證。嘗試:

openssl base64 -d -A <sig.txt >sig.bin # if version 1.1.0+ can omit -A 
openssl dgst -sha256 -verify pubkey.pub -signature sig.bin data.json 

另一邊:RSA在大小1024位,雖然實際上沒有,只要是公知的破碎,不再(自2014)評爲可接受安全性提供足夠的裕度。大多數當局現在要求2048年,技術上你應該至少使用1280年或1536年 - 禁止量子計算的顯着進步,這是目前不可預測的。但是,這是一個安全問題.SX或者crypto.SX,而不是SO。

+0

我仔細檢查了我的合作伙伴,我們目前正在對二進制簽名進行驗證,而不是對base64編碼版本進行驗證。另外,我們目前正在使用2048位RSA。 嘗試了其他一切後,我嘗試了你發佈的命令,但不幸得到了相同的結果:驗證失敗 – jkaw4

+0

那麼你的Q不是'最新'? Q中的密鑰和簽名都是1024位。當我在你的Q中完全做了什麼,明顯的(?)填補了它的工作中遺漏的部分。你可以添加符合簽名的數據,或者如果你喜歡一些虛擬數據和它的簽名 - 如果沒有_entirely_ ASCII圖形(即沒有CRLF等)使用b64或十六進制來保存所有字節? –