修改X509证书

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

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; } } } 

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

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

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

但是,你无法certificate这一点。 适当的证据要求:

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

  2. 正式方法certificate正在加载证书和执行validation的代码。

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

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

您必须使用CertificateFactory.从字节数组重新加载它CertificateFactory.

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(); 并解密签名以获取哈希值并将其与修改后的哈希值进行比较,祝你好运;)

如果查看RFC 5280,证书有3个字段:

  • 即tbsCertificate
  • signatureAlgorithm
  • 的SignatureValue

signatureValue是证书中的最后一项。

我有类似的要求。 这些是我遵循的步骤:

  • 拥有.crt格式(base-64编码)文件的1个证书。 证书包含在“—– BEGIN CERTIFICATE —–”和“—– END CERTIFICATE —–”之间
  • 在END CERTIFICATE行之前的行上编辑证书的最后一个字符。 只需向该字符添加1或减少1.如果最后一个字符是x,则将其设为y或w。

这将更改证书中的签名,签名将不再有效。