Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法在Android上验证rsa签名_Java_Cryptography_Rsa_Digital Signature - Fatal编程技术网

Java 无法在Android上验证rsa签名

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

我正在尝试使用私钥对加密消息进行签名,并用Java进行验证。这是我第一次使用加密和签名,所以我不确定它应该如何工作,我被困在这里了。验证总是返回false

我在这里签名:

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));
    }

您应该首先使用自己生成的密钥对在本地测试这些东西。如果失败了,你的代码就错了——它是一个非常简单的Java
Signature
包装器,所以根本不太可能

您已经使用了签名算法的完整规范,因此提供程序默认值在这里不是问题

然后,在生成/验证签名之前,以十六进制或Base64格式打印数据,检查两侧数据的正确性。如果失败,您就有一个I/O或编码/解码错误。编码/解码错误和字符串处理占密码学相关问题总数的30%左右


最后,您可以获得并比较私钥和公钥的模数。如果模不匹配,那么您使用的是不同密钥对的私钥和公钥,签名验证当然会失败。

对于我来说,这显然是一个与库相关的问题,如果这样做会更好,正如Ilmari所提到的。你应该强烈考虑迁移你的问题,因为它很可能得到答复。所以我把它张贴,但我没有任何答案。我会考虑让它自给自足,再试一次。谢谢@user3685322:确保将输入值发布到SignModule、signExponent、signPublicExponent;问题可能就在那里,不。RSAPublicKeySpec有参数,问题表明它们是在C#中生成的。我认为OP破坏了密钥对的一致性@我对新的介绍没意见;我有问题,因为我没有看到问题中的代码“在验证方法中生成新公钥”的迹象。你说的破坏密钥对的一致性是什么意思?我在c#中生成了密钥对,并将它们转移到我的android应用程序中,主要用于测试。公钥最终将在服务器端使用。打破一致性意味着,您使用私钥生成签名,但不使用相应的公钥验证该签名。你试过我在答案里贴的代码吗?