Java 无法在Android上验证rsa签名
我正在尝试使用私钥对加密消息进行签名,并用Java进行验证。这是我第一次使用加密和签名,所以我不确定它应该如何工作,我被困在这里了。验证总是返回false 我在这里签名:Java 无法在Android上验证rsa签名,java,cryptography,rsa,digital-signature,Java,Cryptography,Rsa,Digital Signature,我正在尝试使用私钥对加密消息进行签名,并用Java进行验证。这是我第一次使用加密和签名,所以我不确定它应该如何工作,我被困在这里了。验证总是返回false 我在这里签名: public byte[] rsaSign (byte[] data) { byte[] cipherData = null; try { RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(signModulus, signExponent); KeyFa
public byte[] rsaSign (byte[] data) {
byte[] cipherData = null;
try {
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(signModulus, signExponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privKey = fact.generatePrivate(keySpec);
Signature s = Signature.getInstance("SHA1withRSA");
s.initSign(privKey);
s.update(data);
return s.sign();
}
return cipherData;
}
在这里,我尝试验证签名:
public boolean rsaVerify (byte[] data, byte[] signature) {
boolean success = false;
try {
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(signModulus, signPublicExponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
Signature s = Signature.getInstance("SHA1withRSA");
s.initVerify(pubKey);
s.update(data);
success = s.verify(signature);
return success;
}
return false;
}
有人能看到问题吗?密钥在C#中生成,并在java中转换为大整数。签名验证失败,因为您在验证方法中使用了不同的
公钥。
使用公钥
验证签名是否与rsaSign()
方法中使用的私钥
一致
希望这对你有帮助。请注意,此公钥
与签名生成方法中使用的私钥
一致:
/**
* This method will sign message with RSA 2048 key
* @return Void
*/
public void rsaSign (String message) throws Exception {
//key generation
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(2048, random);
KeyPair keyPair = keyGen.generateKeyPair();
PrivateKey priv = keyPair.getPrivate();
PublicKey pub = keyPair.getPublic();
System.out.println("RSAPub key Mod for Sign/Verify : " + Helper.toHex(((RSAPublicKey)pub).getModulus().toByteArray()));
System.out.println("RSAPub key Exp for Sign/Verify : " + Helper.toHex(((RSAPublicKey)pub).getPublicExponent().toByteArray()));
//sign
Signature dsa = Signature.getInstance(signALG);
dsa.initSign(priv);
dsa.update(Helper.toByte(message));
byte[] realSig = dsa.sign();
System.out.println("RSA Sign-Data : " + Helper.toHex(realSig));
}
/**
* This method verify signature with RSA public key
* @param message The plain message
* @param rsaMOD RSA Public key Modulus in string
* @param rsaEXP RSA Public key Exponent in string
* @param rsaSignData Signature which will be verified
* @return true if verifications success, false otherwise
*/
public boolean rsaVerify(String message, String rsaMOD, String rsaEXP, String rsaSignData) throws Exception {
BigInteger modBigInteger = new BigInteger(Helper.toByte(rsaMOD));
BigInteger exBigInteger = new BigInteger(Helper.toByte(rsaEXP));
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(spec);
Signature signature = Signature.getInstance(signALG);
signature.initVerify(publicKey);
signature.update(Helper.toByte(message));
return signature.verify(Helper.toByte(rsaSignData));
}
您应该首先使用自己生成的密钥对在本地测试这些东西。如果失败了,你的代码就错了——它是一个非常简单的JavaSignature
包装器,所以根本不太可能
您已经使用了签名算法的完整规范,因此提供程序默认值在这里不是问题
然后,在生成/验证签名之前,以十六进制或Base64格式打印数据,检查两侧数据的正确性。如果失败,您就有一个I/O或编码/解码错误。编码/解码错误和字符串处理占密码学相关问题总数的30%左右
最后,您可以获得并比较私钥和公钥的模数。如果模不匹配,那么您使用的是不同密钥对的私钥和公钥,签名验证当然会失败。对于我来说,这显然是一个与库相关的问题,如果这样做会更好,正如Ilmari所提到的。你应该强烈考虑迁移你的问题,因为它很可能得到答复。所以我把它张贴,但我没有任何答案。我会考虑让它自给自足,再试一次。谢谢@user3685322:确保将输入值发布到SignModule、signExponent、signPublicExponent;问题可能就在那里,不。RSAPublicKeySpec有参数,问题表明它们是在C#中生成的。我认为OP破坏了密钥对的一致性@我对新的介绍没意见;我有问题,因为我没有看到问题中的代码“在验证方法中生成新公钥”的迹象。你说的破坏密钥对的一致性是什么意思?我在c#中生成了密钥对,并将它们转移到我的android应用程序中,主要用于测试。公钥最终将在服务器端使用。打破一致性意味着,您使用私钥生成签名,但不使用相应的公钥验证该签名。你试过我在答案里贴的代码吗?