【问题标题】:phpseclib $X509->setDomain on CSR?CSR 上的 phpseclib $X509->setDomain?
【发布时间】:2015-02-18 21:47:49
【问题描述】:

是否可以在 CSR 上为 subjectAltName 设置 x509 v3 扩展属性?

我能够成功生成 CSR,然后将其传递给 CA 进行签名。

CA 可以调用 X509->setDomain("bob.com","*.bob.com","asdf.org"); 等函数并且它们毫无问题地出现在最终证书中(注意:我正在为 phpseclib 进行签名、重新加载、设置扩展、辞职解决方法)。

CSR 进程调用相同的函数 $X509->setExtension("id-ce-subjectAltName",array("names","here") ) 或 $X509->setDomain("domain1","domain2") ;似乎没有在 CSR 本身中设置一些 X509 扩展属性(openssl 可以),我只能在第二次签名之前重新导入后通过 CA 添加 SAN。

谢谢!

编辑:我创建了一个示例 CSR(签名、重新加载、x509v3 扩展、resign 解决方法),似乎可以设置一些扩展属性(CA:false、密钥使用等),但不能设置 subjectAltName 信息:

-----BEGIN CERTIFICATE REQUEST-----
MIIC1TCCAb8CAQAwVDELMAkGA1UEBgwCU1MxEDAOBgNVBAgMB09ic2N1cmUxDzAN
BgNVBAcMBlNlY3VyZTEQMA4GA1UECgwHYm9iY29ycDEQMA4GA1UEAwwHYm9iLmNv
bTCCASAwCwYJKoZIhvcNAQEBA4IBDwAwggEKAoIBAQCunNrjxEOILsESZ1osUkT3
zSeAHlzNiCBQnc/Xf+oW7Ir7wKfbHkV10cM583mw3Zy8rlCT/lUq0H+f3Uoc5/FA
dsYWhatlJRlTjv+yjSsxyB9i/hZ/KliP3Ix2O+Pq1wZIWfvk40hmCHHSB6YDtqt0
vXqUTIhH3SfyLtK9nd/6WG8bgIq9jgL6xvF3h44ynEwkuOnHt4a9WrflGX4KKcwo
OM98M/TAntDgSXBEYoLxenIbl3ypa7gtghVHHls3QOSay5QM87K3PJ3kSWVlZ3tN
tZGfbFdLiS+3MH8G3ujSX8XYeBnUj5jXi4SzpzQ9o5pyArL8DD8kC/Q9P/el1aZb
AgMBAAGgQDA+BgkqhkiG9w0BCQ4xMTAvMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/
BAwwCgYIKwYBBQUHAwEwBwYDVR0RBAAwCwYJKoZIhvcNAQELA4IBAQAUIhgLf6LH
WwhncU+yrNy6yHPHjFbipehUaS/Wa6FBbANpLyEdslqNwFD2FyXofSQVCB0L6VnH
NNXHcfZqWOT8+Xd0yNmfr/w+vg+s1yY4S0VAG6mxGsqwdIJqgXm2jaw0rMpzRs/k
wfOpJ+gyRTrQz9VJrn4xC4Uv6zTGNj56qZehDievW74SGISbGzj7AGmCxpp5/qZD
LN4Ls3wZ7I4TfuYZDh7qWuFwEAEEv40JPF2qO3VitvyAYrKg3bnUlFzQrOsfs4Ot
xzihLwkFEobih1bOEhzTnSv+lMckfw0DQ5Eb8mtFTC+/KOqEMMU5Hq1fm3B9Bkgs
FmqQZk4QlerY
-----END CERTIFICATE REQUEST-----

【问题讨论】:

  • 我创建了一个示例 CSR(签名、重新加载、x509v3 扩展、resign 解决方法),并且可以设置一些扩展(CA:false、密钥用法等),但不能设置 subjectAltName 信息。

标签: x509 phpseclib


【解决方案1】:

我想通了,phpseclib 中的 SignCSR 函数不响应 setDomain 函数或 $this->domains 数组中的任何内容,但是可以手动编码并自己强制设置主题替代名称:

$OPTIONS["altnames"] = array(
                                "bob.com",
                                "10.123.123.123",
                                "*.bob.com",
                                "asdf.fdsa",
                            );

        $ALTNAMES = $this->altnames($OPTIONS["altnames"]);
        if ( count($ALTNAMES) )
        { 
            $CSR->setExtension("id-ce-subjectAltName"   , $ALTNAMES );
        }

protected function altnames($ALTNAMES)
{ 
    //Sort names and IPs into two different arrays
    $DOMAINS = array(); $IPS = array();
    foreach ($ALTNAMES as $ALTNAME)
    { 
        if ( filter_var($ALTNAME, FILTER_VALIDATE_IP) )
        {
            array_push($IPS,$ALTNAME);
        }else{
            array_push($DOMAINS,$ALTNAME);
        }
    }
    // Create our altname array for the subjectAltName parser
    $RETURN = array();
    foreach ($DOMAINS as $DOMAIN)   { array_push($RETURN, array("dNSName"   => $DOMAIN  ) ); }
    foreach ($IPS as $IP)           { array_push($RETURN, array("iPAddress" => $IP      ) ); }
    return $RETURN;
}

现在,我发现的一个警告(这是 phpseclib 需要考虑的功能问题)是缺乏 IPv6 支持。如果您在 altnames 数组 (2620:153::1234) 中提供一个有效的 IPv6 地址,它将转换为 IP 地址:0.0.0.0,因为使用了嵌入在 X509 代码中的 IP2LONG 和 LONG2IP。

虽然对于我的用例来说不是一个大问题,但它是一个小麻烦,我已经尝试使用自定义 IP2BIN 和 BIN2IP 函数替换库中 IP 的编码和解码逻辑,但没有取得很大成功。

上面的代码生成的示例 CSR:

-----BEGIN CERTIFICATE REQUEST-----
MIIC/DCCAeYCAQAwVDELMAkGA1UEBgwCU1MxEDAOBgNVBAgMB09ic2N1cmUxDzAN
BgNVBAcMBlNlY3VyZTEQMA4GA1UECgwHYm9iY29ycDEQMA4GA1UEAwwHYm9iLmNv
bTCCASAwCwYJKoZIhvcNAQEBA4IBDwAwggEKAoIBAQDOGLdjEr2IyW27e08hmRN+
Bcu4uOWAWEvxvY3+5pHdBQQEXhww5YQuEvpmgbKtav0j7aqFPDYNSXTv+aQNe9fq
cP3nZmKAWU+qbQMjWxwV9mEJOlWI214v7C8lLbMvBlny141J7KTvv1TGGLCBH/V2
EnQSdJzGDwXmJ2k0iChlQ7zl1TlonamYX9gefzp3N/DDp6kNhuPSX9zRorYIp5CC
WEIRmDdegwxHACrNu0K4xwuPjTRJf0oUkRsfBuDxqvBalQ0bzd/23fiQ51MEVla3
fUWL/+b2SKOlvgfu0XbfZ+Qx21DeyRQpqIWnv0gR4AM8qltxUgRjZloUfK5IQ8rp
AgMBAAGgZzBlBgkqhkiG9w0BCQ4xWDBWMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/
BAwwCgYIKwYBBQUHAwEwLgYDVR0RBCcwJYIHYm9iLmNvbYIJKi5ib2IuY29tgglh
c2RmLmZkc2GHBAp7e3swCwYJKoZIhvcNAQELA4IBAQAf1Vlt09ZBhVpxlmi+n93u
Gm8fNrd5afeIzWj0h4dFGJSOg5T8SkfL5txk2C9tQEdayQWB1kllx5rIqXAPe6gz
kbcjJn8l2IB3khIoKYmylmtV8Yo0Fl/Xba1oLCAsixbK+UxiSLgXqMryz9DBy40s
5oYXpy5JOnqL7BRC7b+Lk/chw7CcncPZI4rei6HM8WATymTySdrPoQegvBj0VIar
qHBZrMV9lsjTREJ9hvA/FycA/PNlP9y8N+eTF9SBrnTi8ix+v+Iirc43xeD2EVLG
6uqXecClji6OEOKcdDsH0D0HD1PMFmKB0FWvq71dt7eVIHkTPwTLFG2XAjfn6Fb8
-----END CERTIFICATE REQUEST-----

解码为:

Certificate Request:
Data:
    Version: 0 (0x0)
    Subject: C=SS, ST=Obscure, L=Secure, O=bobcorp, CN=bob.com
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
            Public-Key: (2048 bit)
            Modulus:
                00:ce:18:b7:63:12:bd:88:c9:6d:bb:7b:4f:21:99:
                13:7e:05:cb:b8:b8:e5:80:58:4b:f1:bd:8d:fe:e6:
                91:dd:05:04:04:5e:1c:30:e5:84:2e:12:fa:66:81:
                b2:ad:6a:fd:23:ed:aa:85:3c:36:0d:49:74:ef:f9:
                a4:0d:7b:d7:ea:70:fd:e7:66:62:80:59:4f:aa:6d:
                03:23:5b:1c:15:f6:61:09:3a:55:88:db:5e:2f:ec:
                2f:25:2d:b3:2f:06:59:f2:d7:8d:49:ec:a4:ef:bf:
                54:c6:18:b0:81:1f:f5:76:12:74:12:74:9c:c6:0f:
                05:e6:27:69:34:88:28:65:43:bc:e5:d5:39:68:9d:
                a9:98:5f:d8:1e:7f:3a:77:37:f0:c3:a7:a9:0d:86:
                e3:d2:5f:dc:d1:a2:b6:08:a7:90:82:58:42:11:98:
                37:5e:83:0c:47:00:2a:cd:bb:42:b8:c7:0b:8f:8d:
                34:49:7f:4a:14:91:1b:1f:06:e0:f1:aa:f0:5a:95:
                0d:1b:cd:df:f6:dd:f8:90:e7:53:04:56:56:b7:7d:
                45:8b:ff:e6:f6:48:a3:a5:be:07:ee:d1:76:df:67:
                e4:31:db:50:de:c9:14:29:a8:85:a7:bf:48:11:e0:
                03:3c:aa:5b:71:52:04:63:66:5a:14:7c:ae:48:43:
                ca:e9
            Exponent: 65537 (0x10001)
    Attributes:
    Requested Extensions:
        X509v3 Basic Constraints: critical
            CA:FALSE
        X509v3 Extended Key Usage: critical
            TLS Web Server Authentication
        X509v3 Subject Alternative Name: 
            DNS:bob.com, DNS:*.bob.com, DNS:asdf.fdsa, IP Address:10.123.123.123
Signature Algorithm: sha256WithRSAEncryption
     1f:d5:59:6d:d3:d6:41:85:5a:71:96:68:be:9f:dd:ee:1a:6f:
     1f:36:b7:79:69:f7:88:cd:68:f4:87:87:45:18:94:8e:83:94:
     fc:4a:47:cb:e6:dc:64:d8:2f:6d:40:47:5a:c9:05:81:d6:49:
     65:c7:9a:c8:a9:70:0f:7b:a8:33:91:b7:23:26:7f:25:d8:80:
     77:92:12:28:29:89:b2:96:6b:55:f1:8a:34:16:5f:d7:6d:ad:
     68:2c:20:2c:8b:16:ca:f9:4c:62:48:b8:17:a8:ca:f2:cf:d0:
     c1:cb:8d:2c:e6:86:17:a7:2e:49:3a:7a:8b:ec:14:42:ed:bf:
     8b:93:f7:21:c3:b0:9c:9d:c3:d9:23:8a:de:8b:a1:cc:f1:60:
     13:ca:64:f2:49:da:cf:a1:07:a0:bc:18:f4:54:86:ab:a8:70:
     59:ac:c5:7d:96:c8:d3:44:42:7d:86:f0:3f:17:27:00:fc:f3:
     65:3f:dc:bc:37:e7:93:17:d4:81:ae:74:e2:f2:2c:7e:bf:e2:
     22:ad:ce:37:c5:e0:f6:11:52:c6:ea:ea:97:79:c0:a5:8e:2e:
     8e:10:e2:9c:74:3b:07:d0:3d:07:0f:53:cc:16:62:81:d0:55:
     af:ab:bd:5d:b7:b7:95:20:79:13:3f:04:cb:14:6d:97:02:37:
     e7:e8:56:fc

【讨论】:

  • 更新,显然在 CSR 中设置 REQUESTED x509 v3 扩展不足以让 CA 随意签署它们。 CA 还必须阅读它们并在第一次签署实际证书本身后重新申请。我正在研究如何使用 phpseclib 完成此任务,目前 CA 刚刚签署 CSR 提供​​的结果是剥离所有这些扩展。
  • 我认为这是 phpseclib 需要改进的一个领域。你做的很好!
【解决方案2】:

好的,我想我在 phpseclib 的 X509 签名函数中找到了一个“特性”:

function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')

如果您对 CSR 进行签名,则签名函数中的代码声称要复制 X509 v3 扩展属性,但是当它执行此行时:

$csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);

结果始终为空白(一个空数组),$THIS(新)证书中的属性在之前约 30 行代码中的某处被覆盖。

我将 csrexts 行移到 Sign 函数的顶部,现在属性被正确复制到生成的证书中,并在 CSR 中具有 X509 扩展属性(必须通过我之前的答案手动计算和设置)

我将使用 sourceforge 尝试发布错误请求,希望能帮助其他人摆脱困境。

【讨论】:

    【解决方案3】:

    好的,所以我已经使用 PHPSecLib 文档中的一个示例来完成这个工作,并玩了几个小时。也许这是 2 月后添加的内容,但无论如何,这里是如何生成具有主题备用名称的 CSR:

        $privKey = new Crypt_RSA();
        extract($privKey->createKey());
        $privKey->loadKey($privatekey);
    
        $x509 = new File_X509();
        $x509->setPrivateKey($privKey);
        $x509->setDNProp('id-at-organizationName', 'Company');
        $x509->setDNProp('id-at-organizationalUnitName', 'CompanyDepartment');
        $x509->setDNProp('id-at-commonName', 'myurl.com');
        $x509->setDNProp('id-at-localityName', $this->application);
    
        $x509->loadCSR($x509->saveCSR($x509->signCSR()));
    
        // Set extension request.
        $x509->setExtension("id-ce-subjectAltName", [
            ['dNSName' => 'myalternativename.com', 'iPAddress' => 127.0.0.1]
        ]);
    
        echo $x509->saveCSR($x509->signCSR());
    

    这应该打印出以 myalternativename.com 作为 SAN 的 CSR。

    【讨论】:

    • 127.0.0.1 需要用引号括起来。
    【解决方案4】:

    该错误在 2020 年仍然存在。

    这个错误的原因是需要一个有效的 $x509->currentCert 数组。 setExtension() 函数对空的 currentCert 数组无效。 currentCert 数组结构等于 signCSR() 函数的结果。因此,您可以将其初始化如下:$x509->currentCert = $x509->signCSR(); 现在你可以调用 setExtension() 函数了。

    以下是如何使用 SAN 属性生成 CSR 的完整示例:

    use \phpseclib\Crypt\RSA;
    use \phpseclib\File\X509;
    
    $privateKey = new RSA();
    $privateKey->loadKey(file_get_contents(__DIR__ . '/private.key'));
    
    $x509 = new X509();
    $x509->setPrivateKey($privateKey);
    $x509->setDNProp('commonname', 'example.com');
    $x509->setDNProp('emailaddress', 'admin@mail.com');
    $x509->currentCert = $x509->signCSR(); // Important!
    $x509->setExtension('id-ce-subjectAltName', [
        ['iPAddress' => '127.0.0.1'],
        ['dNSName' => 'www.example.com'],
    ]);
    
    $csr = $x509->signCSR();
    file_put_contents(__DIR__ . '/domain.csr', $x509->saveCSR($csr));
    echo "OK\n";
    

    【讨论】:

      猜你喜欢
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多