繁体   English   中英

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

[英]Private Certificate Authority in PHP?

我正在建立一个私有CA,我想使用PHP与它进行交互。 我已经尝试使用PHP的内置openssl库 因此,我创建了一个CSR,并使用openssl_csr_sign进行签名。

这确实签署了CSR,仅此而已。 在OpenSSL的CLI中,它类似于

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

而我想要类似的东西

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

基本上,它使用x509模块而不是ca模块对其进行签名。 因此,它不会将其写入openssl.cnf指定的数据库中,它不会使用或更新序列号; 它比实际的CA更像是“我信任这个人,所以我将用我的私钥对他的公钥进行签名”。 有没有办法用PHP处理OpenCA的私有CA?

是的,没有。

尽管使用了提供的openssl.conf文件,PHP的OpenSSL扩展并不会自动管理证书数据库和/或序列号,并且不提供任何实用程序来帮助您。

另一方面,数据库本身具有相对简单的格式 ,因此您可以使用原始文件系统功能自己实现它。 如果您确实选择了这条路线,这里有一些提示:

  • 由于每个证书记录都位于单独的行上,因此fgets()在解析时会派上用场。
    • 乍看之下fscanf()看起来更好,但是它会将所有空格都一样对待,并且制表符是格式的重要组成部分,所以...
    • file()甚至更容易,但仅用于读取。 可能是您需要同时进行读写操作,并且需要获得文件上的锁,以避免出现竞争状况。
  • DN字符串元素可以按任意顺序排列,并非所有元素都是强制性的,并且在值中包含定界符时也不会转义,因此,您将发现很难以与OpenSSL CLI工具相同的方式来生成它。 您最好对刚刚签署的证书执行openssl_x509_parse()并从那里读取值。
    • 我不记得它是什么,但是该函数在PHP 5和7之间的结果略有不同,这对于DN字符串来说很重要。
  • PHP(适当地)将序列号作为整数处理,但是它以十六进制表示法存储,因此您需要来回转换它。
    • 序列文件存储下一个序列号,因此您可以执行$serial = hexdec(file_get_contents($pathToSerial)) ,将该变​​量传递给openssl_csr_sign() ,然后将sprintf("%X\\n", $serial + 1)写入文件。
  • 撤销时间戳记位于数据库的第3列中,但是由于您在签名时没有立即撤销证书,因此不会显示该证书-这就是为什么在到期日期和序列号之间有两个选项卡的原因,请不要忘记在写作时。
  • 与人们期望的相反,OpenSSL CLI工具实际上并未在同一数据库文件上运行。 它读取当前<filename>.old ,将其重命名为<filename>.old ,然后创建一个全新的<filename>作为<filename> 这意味着,每当您使用CLI工具时,任何文件系统所有权,授予您PHP脚本访问权限的权限都会丢失。
    • 进行运行时检查以访问文件; 失败时-中止生成/签名并记录/打印消息(可能带有chownchmod指令)以通知您。
    • 串行文件和所有其他文件也相同。
  • 尽管我从未见过这种情况发生,但是密钥生成,CSR创建和签名中的任何一个都不是不可能的。
    • 生成的pKey,CSR,证书都是相互依赖的,并且是resource类型的(使用后应关闭)。 要抛出异常并仅在必要时关闭资源,我想预定义保存变量的变量,并在引发异常之前在处理所有有条件的无资源例程的闭包中use它们。
    • 仅在全部3个都成功之后才写入数据库,最后写入串行文件。
  • 您可能已经知道了这一点,但是它们的pKey资源同时拥有私钥和公钥。

如您所见,如果您知道自己在做什么,它是可管理的,但是它有很多陷阱,对于简单的PoC而言,确实不值得。 通过exec() (和兄弟姐妹)调用CLI工具是一个更简单的选择。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM