2017-03-04 116 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或十六进制来保存所有字节? –