使用由OpenSSL生成的密钥和证书在Java中验证签名

3
以下是Java 8代码,结果显示“signature NOT signed by matching key”,我不明白为什么。有任何想法吗?我的猜测是与openssl生成私钥或证书的方式有关,但从我的研究来看,我正在使用正确的命令。我试图加载私钥,签署一条消息,然后使用x509证书中包含的公钥验证签名。privatekey.pkcs8.key文件是使用基于MS Windows的openssl生成的以下命令生成的:
openssl.exe" genrsa -out privatekey.pem 1024
openssl pkcs8 -in privatekey.pem -inform PEM -topk8 -out privatekey.pkcs8.key -outform DER -nocrypt

公钥证书publickey.cer也是使用基于MS Windows的openssl生成的,使用以下命令:
openssl req -x509 -key privatekey.pem -days 365 -out publickey.cer -new

我一直在使用以下Java代码尝试验证签名:

public static void main(String[] args) throws Exception{ 
    new TestSigs();
}

public TestSigs {
    byte[] signature = generateSignatureForMessage("src/cryptoprivatekey.pkcs8.key", "Hello");
    verifySignature("src/crypto/publickey.cer", signature);
}

public byte[] generateSignatureForMessage(String privateKeyPath, String message) throws Exception {
    RSAPrivateKey privKey = loadPrivateRSAKeyFromFile(privateKeyPath);
    Signature s = Signature.getInstance("SHA256withRSA");
    s.initSign(privKey);
    s.update(ByteBuffer.wrap(message.getBytes()));
    byte[] signature = s.sign();
    return signature;
}

private void verifySignature(String publicKeyPath, byte[] signature) throws Exception {
    Certificate cert = loadCertificate(publicKeyPath);
    Signature s = Signature.getInstance("SHA256withRSA");
    s.initVerify(cert);
    if(s.verify(signature)) {
        System.out.println("signature signed by matching key");
    } else {
        System.out.println("signature NOT signed by matching key");
    }
}

private Certificate loadCertificate(String filename) throws FileNotFoundException, CertificateException {
    FileInputStream fis = new FileInputStream(filename);
    BufferedInputStream bis = new BufferedInputStream(fis);
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    return cf.generateCertificate(bis);
}

private RSAPrivateKey loadPrivateRSAKeyFromFile(String keyPath) throws Exception {
    byte[] privKeyBytes = loadRSAKeyBytesFromFile(keyPath);
    KeyFactory kFact = KeyFactory.getInstance("RSA");
    KeySpec ks = new PKCS8EncodedKeySpec(privKeyBytes);
    return (RSAPrivateKey)kFact.generatePrivate(ks);
}
1个回答

3

verifySignature 方法的签名(没有双关语)表明您的实现无法正常工作。要检查 Signature,处理器需要访问已签名数据和签名。而您的方法并未提供这些信息:

private void verifySignature(String publicKeyPath, byte[] signature)

我建议你将其修改为与generateSignatureForMessage方法对称的形式,即:

  1. 向签名对象提供其需要处理的内容(用于签名的待签名内容,用于签名检查的已签名内容)
  2. 请求签名对象执行操作(signverify

这将形成一种类似于以下实现:

private void verifySignature(String publicKeyPath, byte[] signature, byte[] signedContent) throws Exception {
    Certificate cert = loadCertificate(publicKeyPath);
    Signature s = Signature.getInstance("SHA256withRSA");
    s.initVerify(cert);
    s.update(signedContent);
    if(s.verify(signature)) {
        System.out.println("signature signed by matching key");
    } else {
        System.out.println("signature NOT signed by matching key");
    }
}

谢谢!我应该意识到您需要同时应用原始数据。 - extorn

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