修改X509证书

时间:2014-02-20 16:40:04

标签: java https x509

我想证明,如果我从给定的X509证书修改一个位或字节,则签名验证结果为false(因为此修改会导致证书中的哈希值不同)。我遇到了如何使用 getTBSCertificate()方法对证书进行修改的情况。我的下面的代码完美地完成了验证过程但是我尝试使用位或字节修改的想法使其失败,但它不起作用。请注意,我提出的这个想法证明在签名验证时对证书的任何修改都会失败

public class VerifyX509 {

private static Certificate getCACert;
private static Certificate[] getCert;

public static void main(String[] args) throws CertificateEncodingException {
    setURLConnection("https://www.google.com");
    X509Certificate x509cert= (X509Certificate) getCert[0];
    byte[] b= x509cert.getTBSCertificate();
    b[0] = (byte) ~b[0];
    // HOW TO UPDATE getTBSCertificate() after flipping the b[0] to make Verify() in my method verifySign() return false!
    verifySign();

  }


public static void setURLConnection(String link){

    try{
        int i=1;
        URL destinationURL = new URL(link);
        HttpsURLConnection con = (HttpsURLConnection) destinationURL.openConnection();
        con.connect();
        getCert = con.getServerCertificates();
        for (Certificate c : getCert) 
        {
            if (i==2)
            {
                getCACert= c;
                return;
            }
            i+=1;
        }
        }catch (Exception e1) {
        JOptionPane.showMessageDialog(null, "Error while connection! Check your Internet Connection.");
        e1.printStackTrace();
        }

}


public static boolean verifySign()
{

        try
        {
            getCert[0].verify(getCACert.getPublicKey());
            return true;
        } catch (GeneralSecurityException e2)
        {
            return false;
        }
}
}

如何设置概念验证代码以显示验证失败?

3 个答案:

答案 0 :(得分:1)

  

请注意,我提出的这个想法是为了证明在签名验证时对证书的任何修改都会失败。

可以通过简单地翻转有效证书中的随机位然后尝试验证它们来证明这一点(以一定的正确概率)。

然而,你无法证明这样。适当的证明要求:

  1. 正确实施X509证书的数学证明具有此属性。

  2. 正式方法证明正在加载证书并进行验证的代码已正确实施。

答案 1 :(得分:1)

byte[] b= x509cert.getTBSCertificate();
b[0] = (byte) ~b[0];

更改从证书中获取的数组中的字节不会更改证书。

您必须使用CertificateFactory.

从字节数组重新加载它

答案 2 :(得分:0)

先生。 Mike,你所要做的就是获取行数据DER编码的证书信息(TBS部分),你可以按如下所示提取它

URL url = new URL("https://www.google.com/");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.connect();
Certificate userCert[] = con.getServerCertificates();
        X509Certificate x509cert = ((X509Certificate) userCert[0]);


        byte[] tbs=x509cert.getTBSCertificate(); 

然后通过循环将数组b的内容复制到另一个数组bcopy并执行您想要的任何修改(即通过使用屏蔽技术Anding with x55),之后您可以通过

获取哈希值
    String sha1 = "";
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(bcopy);
        sha1 = byteToHex(crypt.digest());

private static String byteToHex(final byte[] hash)
{
    Formatter formatter = new Formatter();
    for (byte b : hash)
    {
        formatter.format("%02x", b);
    }
    String result = formatter.toString();
    formatter.close();
    return result;
}

此时您已获得修改后的证书的哈希值,您现在可以从原始证书[byte[] sig= x509cert.getSignature();]中提取签名并解密签名以获取哈希值并将其与修改后的值进行比较哈希值,祝你好运;)