signature.verify() 总是返回 False
public static void main(String[] args) {
try{
String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
String exp = "AQAB";
byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
String signedMessage = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
BigInteger modulus = new BigInteger(1, modulusBytes );
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
Signature signature = Signature.getInstance("SHA1withRSA");
byte[] sigBytes = hexStringToByteArray(signedMessage);
signature.initVerify(pubKey);
System.out.println(signature.verify(sigBytes));
}catch(Exception e){
System.out.println("Error: " + e.toString());
}
}
private static byte[] hexStringToByteArray(final String encoded) {
if ((encoded.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[encoded.length()/2];
final char enc[] = encoded.toCharArray();
for (int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder(2);
curr.append(enc[i]).append(enc[i + 1]);
result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
此代码始终返回 false。我不知道从这里该去哪里。
public static void main(String[] args) {
try{
String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
String exp = "AQAB";
byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
String signedMessage = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
BigInteger modulus = new BigInteger(1, modulusBytes );
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
Signature signature = Signature.getInstance("SHA1withRSA");
byte[] sigBytes = hexStringToByteArray(signedMessage);
signature.initVerify(pubKey);
System.out.println(signature.verify(sigBytes));
}catch(Exception e){
System.out.println("Error: " + e.toString());
}
}
private static byte[] hexStringToByteArray(final String encoded) {
if ((encoded.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[encoded.length()/2];
final char enc[] = encoded.toCharArray();
for (int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder(2);
curr.append(enc[i]).append(enc[i + 1]);
result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
This code always returns false. I'm not sure where to go from here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在对消息进行签名的地方,您应该有一些如下所示的代码:
注意名为
signatureValue
的字节数组。这是数据上的实际签名。这就是您应该提供给verify()
方法的内容。已签名的消息应在对 update() 方法的调用中提供。 IE:Where you sign the message you should have some code like this:
Note the byte-array named
signatureValue
. That is the actual signature on the data. That is what you should provide to theverify()
-method. The message that is signed should be provided in a call to theupdate()
-method. I.e.:我认为问题在于你实际上并没有给它一个消息来验证。
RSA 签名的工作原理是首先对消息进行哈希处理(即“SHA1withRSA”中的“SHA1”),然后执行 活板门操作。这是一种在一个方向上很容易执行而在另一个方向上很难执行的操作,除非您知道一些秘密信息(RSA 私钥)。
为了进行验证,您首先要反转数学变换(因为它在一个方向上很容易),然后将签名中嵌入的哈希值与您刚刚计算的消息的哈希值进行比较。签名本身并不包含消息;要验证签名,您需要签名和已签名的消息。
在 API 级别,它看起来像
Signature
类期望您使用此签名所针对的消息内容调用update
。如果没有这个,它可能会将哈希值与空字符串的哈希值进行比较,因此除非您最初签名的消息也是空字符串,否则签名实际上无效。I think the problem is that you are not actually giving it a message to verify.
An RSA signature works by first hashing the message (that's the "SHA1" in "SHA1withRSA"), and then performing an trapdoor operation to it. This is an operation which is easy to do in one direction and hard in the other direction, unless you know some secret information (the RSA private key).
To verify, you first invert the mathematical transformation (because it's easy in one direction), and then compare the hash that is embedded in the signature with the hash of the message you just computed. The signature does not in itself contain the message; to verify a signature you need both the signature and the message that was signed.
At an API level, it looks like the
Signature
class is expecting you to callupdate
with the contents of the message that this signature was for. Without this, it probably is comparing the hash with the hash of an empty string, so unless your originally signed message was also an empty string, the signature is in fact not valid.你是对的,谢谢杰克。下面的方法完美地工作(即使使用在 .NET 中创建的密钥)!我希望这对其他人有帮助。
You were right, thanks Jack. The below method works perfectly (even with a key created in .NET)! I hope this helps others.