代码之家  ›  专栏  ›  技术社区  ›  Bittercoder

使用证书公钥在java中验证签名

  •  0
  • Bittercoder  · 技术社区  · 17 年前

    我想把一些C代码转换成Java中的等效代码。

    C#代码接受一些字符串内容和签名(在单独的机器上使用私钥生成),并与公钥相结合,它验证签名匹配,从而确保请求未被篡改。

      public bool VerifySignature(string content, byte[] signatureBytes, AsymmetricAlgorithm publicKey)
      {
            var hash = new MD5CryptoServiceProvider();
    
            byte[] dataBuffer = Encoding.ASCII.GetBytes(content);
    
            var cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write);
            cs.Write(dataBuffer, 0, dataBuffer.Length);
            cs.Close();
    
            var deformatter = new RSAPKCS1SignatureDeformatter(publicKey);
            deformatter.SetHashAlgorithm("MD5");
    
            return deformatter.VerifySignature(hash, signatureBytes);
      }
    

    公钥本身是一个X509证书-由.cer文件构造,存储为程序集资源,即。

    byte[] data; // data is read from a resource stream.
    var publicKey = new X509Certificate2(data, "", X509KeyStorageFlags.MachineKeySet).PublicKey.Key
    

    byte[] certContents=null;
    byte[] signature=null;
    String contents = "abc";
    
    // load cert
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certContents));
    
    // grab public key
    RSAPublicKey publicKey = (RSAPublicKey)cert.getPublicKey();
    
    // get sha1 hash for contents        
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.update(contents.getBytes());                
    byte[] hash = mac.doFinal();
    
    // get cipher
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    
    // verify signature of contents matches signature passed to method somehow (and this is where I'm stuck)
    

    有人能提供我如何验证签名的见解吗?或者提供指向一些资源的链接,这些资源可能比普通java文档更好地解释java.crypto和java.security.cert的用法。

    1 回复  |  直到 17 年前
        1
  •  2
  •   ZZ Coder    17 年前

    那个C代码看起来真让我困惑。它使用SHA1CryptoServiceProvider,但使用MD5哈希,所以我无法判断它使用的是哪种哈希算法。我猜是MD5。

    签名验证过程涉及填充,因此代码无法工作。下面是我代码中的一些片段,您可以使用它来验证签名。data是要签名的字节,sigBytes保存签名。

    String algorithm = "MD5withRSA";
    
    // Initialize JCE provider    
    Signature verifier = Signature.getInstance(algorithm);
    
    // Do the verification   
    boolean result=false;
    
    try {
        verifier.initVerify(cert); // This one checks key usage in the cert
        verifier.update(data);
        result = verifier.verify(sigBytes);
    }
    catch (Exception e) {
        throw new VerificationException("Verification error: "+e, e);
    }
    
    推荐文章