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。我不知道从哪里开始。
答案 0 :(得分:9)
在您对邮件进行签名时,您应该拥有以下代码:
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privKey);
signature.update(message);
byte[] signatureValue = signature.sign();
请注意名为signatureValue
的字节数组。这是数据的实际签名。这是您应该为verify()
- 方法提供的内容。应该在调用update()
- 方法时提供已签名的消息。即:
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(pubKey);
signature.update(message);
bool ok = signature.verify(signatureValue);
答案 1 :(得分:3)
我认为问题在于你实际上没有给它一个消息来验证。
RSA签名首先对消息进行散列(即“SHA1withRSA”中的“SHA1”),然后对其执行trapdoor operation。除非您知道一些秘密信息(RSA私钥),否则这是一个在一个方向上很容易做而在另一个方向很难做的操作。
要验证,首先要反转数学变换(因为它在一个方向上很容易),然后将签名中嵌入的散列与刚刚计算的消息的散列进行比较。签名本身不包含消息;要验证签名,您需要签名和签名的邮件。
在API级别,Signature
类似乎希望您使用此签名所针对的消息内容来调用update
。如果没有这个,它可能是将哈希值与空字符串的哈希值进行比较,因此除非您最初签名的邮件也是空字符串,否则签名实际上是无效的。
答案 2 :(得分:1)
你是对的,谢谢杰克。以下方法工作正常(即使使用.NET创建的密钥)!我希望这有助于其他人。
public static void main(String[] args) {
try{
String userID = "189711";
String companyCode = "ILIKEPIZZA";
String combine = userID + "." + companyCode;
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 sign = "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(sign);
signature.initVerify(pubKey);
signature.update(combine.getBytes("UTF-8"));
System.out.println(signature.verify(sigBytes));
}catch(Exception e){
System.out.println("Error: " + e.toString());
}
}