【问题标题】:Missing leading zeroes while retrieving serial number of a x509 cert检索 x509 证书的序列号时缺少前导零
【发布时间】:2017-08-22 23:46:14
【问题描述】:

我正在尝试从 X.509 证书中获取序列号。当我将代码生成的序列号与实际序列号(在 Windows 上)进行比较时,实际序列号的前导零(X509证书)丢失。

有任何建议或替代方法来获取带前导零的十六进制 x.509 证书的序列号吗??

下面是我目前正在使用的代码段:

InputStream in = new FileInputStream("cert");
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(in);
String serialNum = certificate.getSerialNumber().toString(16);
System.out.println(serialNum);

【问题讨论】:

  • 为什么你认为应该有叶子零?可以显示 ASN 编码的证书序列号吗?
  • 实际序列号看起来像‎00 a6 XX XX XX XX XX XX XX。但是上面源代码生成的序列号看起来像a6 XX XX XX XX XX XX XX..缺少前导00。
  • 序列号定义为 ASN.1 INTEGER。前导零不重要。
  • @EJP 实际上,前导零很重要。 ASN.1 整数是二补整数。根据 RFC5280,序列号必须是正整数。如果正整数的最高有效位为 1,则编码值必须附加额外的零字节以表示正整数。

标签: java x509 java-security


【解决方案1】:

BigInteger 有一个 toByteArray() 方法可以重新添加前导 00:

byte[] serialNumBA = certificate.getSerialNumber().toByteArray()

现在您有几种方法可以将字节数组转换为十六进制字符串:

How to convert a byte array to a hex string in Java?

例如使用 Apache commons 编解码器:

String serialNum = Hex.encodeHexString(serialNumBA);

【讨论】:

  • 其实它并没有保留 00s;它重新添加了签名所需的单个 00 iff,(幸运的是)与 ASN.1 DER 使用的规则相同。
  • 谢谢..,当我使用 openssl 读取自签名证书的序列号时,它没有显示前导 00。但是当我在 windows 中读取序列号时,它显示序列号中的前导 oo .我可以知道为什么吗?
  • @jAnA 当您有一个整数值(一个数字)时,该值总是有几个字符串表示形式。您还可以将证书 SN 显示为以 10 为基数的字符串表示形式。省略前导零不一定是坏事。如果您只想在屏幕上显示证书 SN,那么它可能没问题,因为应该知道它必须是一个正数,这使得 00 变得多余。如果您想将 SN 作为字符串存储在数据库中并稍后搜索它,那么您必须非常小心,始终使用相同的算法进行转换。
猜你喜欢
  • 2021-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
相关资源
最近更新 更多