简体   繁体   English

PHP中的私有证书颁发机构?

[英]Private Certificate Authority in PHP?

I am setting up a private CA, and I want to interface with it using PHP. 我正在建立一个私有CA,我想使用PHP与它进行交互。 I have tried with PHP's built-in openssl library . 我已经尝试使用PHP的内置openssl库 So I create a CSR, and to sign it I use openssl_csr_sign . 因此,我创建了一个CSR,并使用openssl_csr_sign进行签名。

This does sign the CSR, but that's it. 这确实签署了CSR,仅此而已。 In OpenSSL's CLI it would be something like 在OpenSSL的CLI中,它类似于

openssl x509 -req -days 360 -in file.csr -CA ca.crt -CAkey ca.key ...

Whereas I want something like 而我想要类似的东西

openssl ca -cert ca.crt -keyfile ca.key -in file.csr -out file.crt ...

Basically it uses the x509 module to sign it, instead of the ca module. 基本上,它使用x509模块而不是ca模块对其进行签名。 So it doesn't write it into the database specified in openssl.cnf , it doesn't use or update the serial number; 因此,它不会将其写入openssl.cnf指定的数据库中,它不会使用或更新序列号; it's more "I trust this guy so I'll sign his public key with my private key" than an actual CA. 它比实际的CA更像是“我信任这个人,所以我将用我的私钥对他的公钥进行签名”。 Is there a way to manage a private CA in PHP, with openssl or not? 有没有办法用PHP处理OpenCA的私有CA?

Yes and no. 是的,没有。

Despite using a provided openssl.conf file, PHP's OpenSSL extension doesn't automatically manage the certificate database and/or serial numbers, and it doesn't provide any utilities to help with that. 尽管使用了提供的openssl.conf文件,PHP的OpenSSL扩展并不会自动管理证书数据库和/或序列号,并且不提供任何实用程序来帮助您。

On the other hand, the database itself has a relatively simple format , so you can implement it yourself using the primitive file-system functions. 另一方面,数据库本身具有相对简单的格式 ,因此您可以使用原始文件系统功能自己实现它。 Here are some hints if you actually go with that route: 如果您确实选择了这条路线,这里有一些提示:

  • Since each certificate record sits on a separate line, fgets() comes handy while parsing it. 由于每个证书记录都位于单独的行上,因此fgets()在解析时会派上用场。
    • fscanf() looks better at first glance, but it treats all whitespace the same and tabs are an essential part of the format, so ... 乍看之下fscanf()看起来更好,但是它会将所有空格都一样对待,并且制表符是格式的重要组成部分,所以...
    • file() is even easier, but only for reading. file()甚至更容易,但仅用于读取。 Chances are that you'll need read+write at the same time, and you'll need to obtain a lock on the file to avoid race conditions. 可能是您需要同时进行读写操作,并且需要获得文件上的锁,以避免出现竞争状况。
  • The DN string elements can be in arbitrary order, not all are mandatory and the delimiter isn't escaped when present inside a value, so you'll find it hard to produce it in the same way that the OpenSSL CLI tool does. DN字符串元素可以按任意顺序排列,并非所有元素都是强制性的,并且在值中包含定界符时也不会转义,因此,您将发现很难以与OpenSSL CLI工具相同的方式来生成它。 You're better off doing a openssl_x509_parse() on the just signed certificate and reading the value from there. 您最好对刚刚签署的证书执行openssl_x509_parse()并从那里读取值。
    • I don't remember what it was, but that function had some minor difference in the result between PHP 5 and 7 and it was kind of important for the DN string. 我不记得它是什么,但是该函数在PHP 5和7之间的结果略有不同,这对于DN字符串来说很重要。
  • PHP (properly) handles the serial number as an integer, but it is stored in hexadecimal notation, so you'll need to convert it back and forth. PHP(适当地)将序列号作为整数处理,但是它以十六进制表示法存储,因此您需要来回转换它。
    • The serial file stores the next serial number, so you can do $serial = hexdec(file_get_contents($pathToSerial)) , pass that variable to openssl_csr_sign() and then write sprintf("%X\\n", $serial + 1) to the file. 序列文件存储下一个序列号,因此您可以执行$serial = hexdec(file_get_contents($pathToSerial)) ,将该变​​量传递给openssl_csr_sign() ,然后将sprintf("%X\\n", $serial + 1)写入文件。
  • Revocation timestamps sit in the 3rd column of the database, but since you don't revoke a certificate right while signing it, it won't be present - that's why there's 2 tabs between the expiration date and serial number, don't forget that while writing. 撤销时间戳记位于数据库的第3列中,但是由于您在签名时没有立即撤销证书,因此不会显示该证书-这就是为什么在到期日期和序列号之间有两个选项卡的原因,请不要忘记在写作时。
  • Contrary to what one would expect, The OpenSSL CLI tool doesn't actually operate on the same database file. 与人们期望的相反,OpenSSL CLI工具实际上并未在同一数据库文件上运行。 It reads the current one, renames it to <filename>.old and then creates an entirely new one as <filename> . 它读取当前<filename>.old ,将其重命名为<filename>.old ,然后创建一个全新的<filename>作为<filename> What this means is that any file-system ownership, permissions that give your PHP script access to it are lost whenever you use the CLI tool. 这意味着,每当您使用CLI工具时,任何文件系统所有权,授予您PHP脚本访问权限的权限都会丢失。
    • Put runtime checks for access to the file; 进行运行时检查以访问文件; on failure - abort generation/signing and log/print a message (possibly with chown , chmod instructions) to notify you of that. 失败时-中止生成/签名并记录/打印消息(可能带有chownchmod指令)以通知您。
    • Same thing applies to the serial and all other files. 串行文件和所有其他文件也相同。
  • While I've never seen it happen, it's not impossible that any of key generation, CSR creation and signing fails. 尽管我从未见过这种情况发生,但是密钥生成,CSR创建和签名中的任何一个都不是不可能的。
    • The resulting pKey, CSR, certificate are all interdependent and of type resource (which should be closed after use). 生成的pKey,CSR,证书都是相互依赖的,并且是resource类型的(使用后应关闭)。 To throw an exception and close the resources only when necessary, I like to pre-define the variables holding them and use them in a closure that handles all conditional resource-free routines before throwing an exception. 要抛出异常并仅在必要时关闭资源,我想预定义保存变量的变量,并在引发异常之前在处理所有有条件的无资源例程的闭包中use它们。
    • Only write to the database after all 3 have succeeded, and write to the serial file last. 仅在全部3个都成功之后才写入数据库,最后写入串行文件。
  • You've probably already figured that one out, but they pKey resource holds both the private and public keys. 您可能已经知道了这一点,但是它们的pKey资源同时拥有私钥和公钥。

As you can see, it is manageable if you know what you're doing, but it has a lot of gotchas and not really worth it for a simple PoC. 如您所见,如果您知道自己在做什么,它是可管理的,但是它有很多陷阱,对于简单的PoC而言,确实不值得。 Calling the CLI tool via exec() (and siblings) is a simpler choice. 通过exec() (和兄弟姐妹)调用CLI工具是一个更简单的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 仅使用用户名,密码和证书颁发机构连接到使用PHP的Web服务 - Connecting to a web service with PHP given only username, password and certificate authority 安全地更新证书颁发机构证书 - Securely updating Certificate Authority Certificates 如何将证书颁发机构添加到 PHP,以便 file() function 信任它签署的证书? - How do I add a Certificate Authority to PHP so the file() function trusts certificates signed by it? php 到 mssql 服务器 errro SSL 提供商:证书链是由不受信任的机构颁发的 - php to mssql server errro SSL Provider: The certificate chain was issued by an authority that is not trusted 从PHP访问证书私钥,证书密钥存储在Windows证书存储区中 - Access certificate private key from PHP, certificate key stored in windows certificate store php套接字:使用不带私钥的Symantec证书 - php socket: using Symantec certificate without a private key PHP OpenSSL可以生成私钥/公钥/证书对吗? - Can PHP OpenSSL generate private/public key/certificate pairs? SSL:使用 PHP 将私钥与证书匹配(没有 phpseclib) - SSL: match private key with certificate using PHP (without phpseclib) 在PHP中使用curl和客户端证书以及单独文件中的私钥 - Using curl in php with client certificate and private key in separate files 使用捆绑信息找不到或没有找到证书颁发机构 - Invalid or no certificate authority found, using bundled information
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM