Java OpenSSL Verify and getPublicKey


Java OpenSSL Verify and getPublicKey

我们正在将PHP(Yii框架)移植到Java(Play!framework 2.2.x),并发现了以下代码:

    $sign = base64_decode($sign64);
    // $cert is a string read from a file.
    $pubkey = openssl_get_publickey($cert);
    // $data is composed of incoming username data, time, etc.
    if(openssl_verify("$data", $sign, $pubkey) != 1) {
        $this->verifies = false;
    } else {
        $this->verifies = true;
    }
    openssl_free_key($pubkey);

我缩短了这段代码,使它包含了要点
$data是随GET请求一起发送的字段
$sign64是与此GET请求一起发送的另一个字段。它由另一个服务器提供,是验证发送的数据是否有效的签名
$cert文件包含字符串"-----开始证书-----"
所以我必须问;在Java中实现此验证代码的标准方法是什么?

具体而言;我们正在使用Play!框架到目前为止,我已经做了以下工作:

String sign = new String(javax.xml.bind.DatatypeConverter.parseBase64Binary(sign64));
java.io.FileInputStream filestream = new java.io.FileInputStream(new java.io.File("certificate.crt"));
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
java.security.cert.Certificate cert = cf.generateCertificate(filestream);
java.security.PublicKey pubkey = cert.getPublicKey();
try
{
    cert.verify(pubkey, sign64); // This seems to be the closest to what I desire...
}
catch (...)
{
    // Here I output the error message...
}

我最终得到的是一个"NoSuchProviderException"。它显示了一些与字符串"sign"相同的神秘文本。我的问题是:我是不是做错了什么?parseBase64Binary正确吗?签名的方法正确吗?不应该;因为我在这里根本不对数据变量进行签名。如何在Java/Play中正确执行此操作!框架

使用以下代码解决了问题:(这是针对那些有相同问题的人)

import java.security.*;
// ...
public static boolean verifySignature(String data, PublicKey key, byte[] signature) throws Exception {
    Signature signer = Signature.getInstance("SHA1withRSA");
    signer.initVerify(key);
    signer.update(data.getBytes());
    return (signer.verify(signature));
}

使用问题中给出的代码读取公钥。签名使用:byte[]sign=java.util.Base64.getDecoder().decode(sign64);

最大的挑战是找出要使用哪种算法。我从上面的代码中得到的例子有"SHA1withDSA",已经尝试了很多。最终字符串"SHA1withRSA"起了作用。它正确地验证了来自我们的数据提供商的签名数据。