Java中signature.verify()返回false

3

首先,我看到有其他帖子提出了这个问题,但没有人像我一样遇到了同样的问题,即 signature.verify() 意外地返回了 false

这是我的代码:

private static String encriptar(String xmlSolicitud, PrivateKey privateKey)
        throws Exception {

    Signature signature=Signature.getInstance("SHA1withRSA");
    signature.initSign(privateKey);
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8")));
    byte[] signatureValue = signature.sign();
    String response = Base64.encode(signatureValue);
    signature.initVerify(keyReader.publicKeyRead(Reference.rutaPublicKeyTest));
    System.out.println(signature.verify(signatureValue));
    return response;
}

如果需要,以下是我读取密钥的方法:

public static PrivateKey privateKeyRead(String filename)
        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    PKCS8EncodedKeySpec spec =
                new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(spec);
}

public static PublicKey publicKeyRead(String filename)
        throws Exception {

    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    X509EncodedKeySpec spec =
                new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
}

你能帮我解决这个问题吗? https://stackoverflow.com/questions/66117526/unable-to-verify-signed-xml-with-certificate-cer - moDev
1个回答

3
在调用sign方法后,签名的状态会被重置。根据文档

调用此方法会将该签名对象重置为之前通过调用initSign(PrivateKey)进行签名时的状态。也就是说,如果需要,可以通过新的updatesign调用从同一签名者生成另一个签名。

因此需要再次使用已签名的字节更新签名:
private static String encriptar(String xmlSolicitud, PrivateKey privateKey)
        throws Exception {

    Signature signature=Signature.getInstance("SHA1withRSA");
    signature.initSign(privateKey);
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8")));

    byte[] signatureValue = signature.sign();
    String response = Base64.encode(signatureValue);

    signature.initVerify(keyReader.publicKeyRead(Reference.rutaPublicKeyTest));
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8"))); // <-- Here

    System.out.println(signature.verify(signatureValue)); // <-- Will print true

    return response;
}

顺便说一下,看起来你正在签署XML内容。为了避免规范化问题,最好使用XML签名


1
哇,太棒了,谢谢,它起作用了!还有感谢您对文本进行的更正!WebService仍然返回无效的CMS错误,但这应该是另一个错误。非常感谢! - leoxs
XML签名看起来很不错,但我不确定,因为我对xml非常新手,但是任何WebService都应该能理解它吧?谢谢! - leoxs
显然这取决于服务,但一般来说,需要签名的XML内容的Web服务在大多数情况下都会期望一个XML签名。 - Robby Cornelissen
嗯,也许这就是我遇到错误的原因,我会去看一下。 非常感谢你的帮助! - leoxs
@RobbyCornelissen 这里的String xmlSolicitud 是指整个XML还是仅指XML中的签名节点? - moDev
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接