【问题标题】:How does CSR signing work?CSR 签名如何运作?
【发布时间】:2014-07-03 21:48:36
【问题描述】:

我正在尝试使用 OpenSSL API 以 PEM 格式签署 CSR 文件。

我不能使用X509_sign() 方法,因为我需要使用第三方 API 对请求进行签名。此 API 要求我的应用程序发送需要签名的数据,它会返回给我一个签名。

我需要发送char* 以向第 3 方 API 签名,但我不明白签名过程是如何工作的:

  • 我是否需要仅使用来自 CSR 的数据来构造这个 char*,例如公钥的主题、指数和模数:

    Char* = "DN=test,O=something...123456(this is the exponent)a2:43:65(this is the modulus)...

  • 或者我是否需要使用在 OpenSSL 中使用 -text 命令时出现的所有元素来构建缓冲区:

    Certificate: Data: Subject: dn=test, O=something Public key info: Exponent: 123456 Modulus: A2:43:65 ....

总结一下:CA 在执行 X509 证书的签名时实际使用了请求的哪些元素,应该以什么格式呈现这些数据?

【问题讨论】:

  • 你需要查看第三方API的文档,看看它期望的输入格式。也许它需要一些标准格式,也许不是。通过您提供的信息,我们可以告诉您该字符串中必须存在哪些信息,但不能告诉您需要如何格式化。

标签: openssl x509


【解决方案1】:

你的头衔和正文不一致; openssl X509_sign() 签署证书,而不是CSR。 CSR 不是证书,证书不是 CSR,并且颁发证书并不是像许多不知情或懒惰的人所说的那样“签署 CSR”。 (正常)CSR 实际上是由请求者而不是 CA 签署的。 openssl 使用 X509_REQ 类型作为 CSR,X509_REQ_sign 签署 CSR。

但答案基本相同。 X.509 证书或 PKCS#10 CSR 是三件事的序列:包含要签名的数据的主体、AlgorithmIdentifier 和签名(作为 BITSTRING)。这些使用http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One 定义并使用可分辨编码规则或DER 进行编码。您输入或看到的由openssl req -textopenssl x509 -text 或其他程序显示的文本表格代表相同的数据,但通常不足以重现确切的位,并且您必须具有确切的位才能使数字签名起作用。 (这就是 DER 中“区分”的含义;它通过指定用于某些其他模棱两可的情况的确切八位字节和位来修改基本编码规则或 BER。)对于 CSR,请参阅我在 https://security.stackexchange.com/questions/58717/what-part-of-the-csr-is-hashed-in-order-to-create-its-signature/58735 中的回答;对于 cert,'wrapper' 是相同的,但主体有很大不同,并且包含的​​内容比 DN 和 publickey 多很多。

TL;DR 对于X509* cert,您签署cert->cert_info 的DER 编码,其类型为X509_CINF,可以使用i2d_X509_CINF() 进行编码。对于X509_REQ* csr,您使用i2d_X509_REQ_INFO() 签署csr->req_info 的DER 编码类型X509_REQ_INFO

替代方案: openssl 具有 engine 的概念,它是处理一些加密操作的外部库和/或硬件单元。如果您的第三方 API 是或可以“包装”为 openssl 引擎,您可以通过配置和指定该引擎来使用(几乎所有)普通的 openssl 例程。 如果该引擎尚不存在,那么仅为您的项目做它可能会做太多工作,但如果您预见到其他(未来)用途,它可能是值得的。

【讨论】:

  • 谢谢,这对我有用,但我不知道如何将此签名设置到我的 X509 证书中...你知道吗?
  • 如果您想使用 OpenSSL,请将 ->sig_alg 更改为 &X509_ALGOR,其中包含 *cert_info->signature 中的值的副本,该副本在您签名之前必须是正确的,并且 ->signature 为&ASN1_BIT_STRING 包含“wire”签名值(对于 RSA,仅作为 bigendian 字节的数字,对于 DSA 或 ECDSA 的两个 INTEGERS 的 SEQUENCE 的 DER 编码)。遵循 OpenSSL 规则,您在这种类型的结构中设置的任何指针都指向使用 xxx_new 或来自 OPENSSL_malloc 的唯一内存创建的唯一对象,并且您杀死您的任何指针 xxx_free 或 OPENSSL_free(如果适用)。 ...
  • ... 然后您可以使用通常的 i2d_X509[_fp}_bio] 或 PEM_write[_bio]_X509 编码和/或写入生成的 X509*,显示女巫 X509_print 等。或者,使用 DER您已经拥有的主体的编码(用于签名),来自主体的“签名”algid 的 DER 编码,以及包含规范签名的 BIT STRING 的 DER/BER 编码,然后加入 DER/BER 序列. (不要忘记 BIT STRING 中的 usedbits 八位字节。)如果您想要 PEM,则以标准方式将 DER 转换为 PEM,通过 base64 + 中断 + 开始/结束行。
  • 非常感谢戴夫,这很有帮助。在我的第一种方法中,您忘记将 X509_ALGO 的副本添加到 cert_info 部分,我的签名是错误的。最后一个问题,我不完全理解你的意思:和->签名是&ASN1_BIT_STRING,包含“wire”签名值(只是RSA的双字节数,DSA或ECDSA的两个整数的序列的DER编码)。因为我将签名放入我的 X509 对象的操作是:
  • certificate->signature->data = new unsigned char[signatureLenght]; memcpy(证书->签名->数据、签名、签名长度);证书->签名->长度=签名长度;
猜你喜欢
  • 2017-02-12
  • 2020-11-19
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多