簡體   English   中英

修改X509證書

[英]Modifying X509 certificate

我想表明,如果我從給定的 X509 證書中修改一個位或一個字節,則簽名驗證結果為假(因為此修改導致與證書不同的哈希值)。 我陷入了如何使用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;
        }
}
}

如何設置概念驗證代碼以顯示驗證失敗?

請注意,我提出的這個想法是為了證明對證書的任何修改都會導致簽名驗證失敗。

可以通過簡單地翻轉有效證書中的隨機位然后嘗試驗證它們來證明這一點(以一定的正確概率)。

但是,您無法證明這樣的事情。 正確的證明需要:

  1. 正確實施 X509 證書的數學證明具有更改證書會使其無效的屬性(某些概率非常接近1 )。

  2. 正式方法證明加載證書和進行驗證的代碼已正確實現。


1 - 事實上,很容易看出概率不能完全為 1。 應用鴿籠原理。

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

更改從證書獲得的數組中的字節不會更改證書。

您必須使用CertificateFactory.從字節數組中重新加載它CertificateFactory.

邁克先生,你要做的就是獲取行數據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(); ] 並解密簽名以獲取哈希值並將其與修改后的哈希值進行比較,祝你好運;)

如果您查看 RFC 5280,證書有 3 個字段:

  • tbs證書
  • 簽名算法
  • 簽名值

簽名值是證書中的最后一項。

我也有類似的需求。 這些是我遵循的步驟:

  • 擁有 1 個 .crt 格式(base-64 編碼)文件的證書。 證書包含在“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”之間
  • 在 END CERTIFICATE 行之前的行中編輯證書的最后一個字符。 只需在該字符上加 1 或減少 1。如果最后一個字符是 x,則將其設為 y 或 w。

這將更改證書中的簽名,簽名將不再有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM