用于 tls 身份验证的 phpseclib 用户证书

phpseclib user cert for tls authetication

更新:我重写了示例代码,CSR 与实际 openssl 创建的 CSR 非常接近(只缺少 CA:False 扩展属性)

我已经有一个 CA 并且想要动态生成用户证书以使用 phpseclib 注册授权设备。

我知道逻辑有点模糊,这段代码是从各种不同的例子拼凑而成的:

<?php

$USERNAME = "tester";
$DEVICENAME = "command";
$PASSWORD = "test";
$ID = 123;

require_once("config.inc.php"); // Sets defined paths to CA cert and key    
require_once("File/X509.php");
require_once("Crypt/RSA.php");

// Setup our CA
$CA = array();      // Store our certificate authority information
$CA["key"           ] = new Crypt_RSA();
$CA["key"           ]->loadKey( file_get_contents(CAKEY) ); // Load our CA key to sign with
$CA["asciicert"     ] = file_get_contents(CACERT);
$CA["cert"          ] = new File_X509();
$CA["cert"          ]->loadX509( $CA["asciicert"] );        // Load our CA cert and public key
$CA["cert"          ]->setPrivateKey($CA["key"]);

// Create a new keypair
$DEVICE = array();
$DEVICE["keys"      ] = new Crypt_RSA();
$DEVICE["keypair"   ] = $DEVICE["keys"]->createKey(2048);
// Save our private key
$DEVICE["privkey"   ] = new Crypt_RSA();
$DEVICE["privkey"   ]->loadKey($DEVICE["keypair"]["privatekey"]);
// Save our public key
$DEVICE["pubkey"    ] = new Crypt_RSA();
$DEVICE["pubkey"    ]->loadKey($DEVICE["keypair"]["publickey"]);
// Create a new CSR
$DEVICE["csr"       ] = new File_X509();
$DEVICE["csr"       ]->setPrivateKey($DEVICE["privkey"]);
$DEVICE["csr"       ]->setPublicKey ($DEVICE["pubkey" ]);
$DEVICE["csr"       ]->setDN("C=SS, ST=obscure, L=obscure, O=secure, OU=networksecurity, CN={$USERNAME}@{$DEVICENAME}/emailAddress={$USERNAME}@{$DEVICENAME}");
// Sign the CSR
$DEVICE["signedcsr" ] = $DEVICE["csr"]->signCSR("sha256WithRSAEncryption");
$DEVICE["asciicsr"  ] = $DEVICE["csr"]->saveCSR($DEVICE["signedcsr"]);
// Update the CSR with attributes         
$DEVICE["cert"      ] = new File_X509();
$DEVICE["cert"      ]->loadX509( $DEVICE["asciicsr"] );         // Now load it back up so we can set extended attributes
$DEVICE["cert"      ]->setPublicKey ($DEVICE["pubkey" ]);
$DEVICE["cert"      ]->setStartDate("-1 day");                  // Make it valid from yesterday...
$DEVICE["cert"      ]->setEndDate("+ 5 years");                 // Set a 5 year expiration on all device certs
$DEVICE["cert"      ]->setSerialNumber($ID, 10);                // Use our ID number in the DB, base 10 (decimal) notation
// These wont work, ill fix this later...
$DEVICE["cert"      ]->setExtension("id-ce-basicConstraints",   array("cA" => false                                                     ),  1   );
$DEVICE["cert"      ]->setExtension("id-ce-keyUsage"        ,   array("keyEncipherment"         ,"nonRepudiation"   ,"digitalSignature" ),  1   );
$DEVICE["cert"      ]->setExtension("id-ce-extKeyUsage"     ,   array("id-kp-emailProtection"   ,"id-kp-clientAuth"                     ),  1   );
$DEVICE["cert"      ]->setExtension("netscape-cert-type"    ,   array("Email"                   ,"SSLClient"                            ),  1   ); 
// Finally have the CA sign the updated CSR
$DEVICE["signedcert"] = $DEVICE["cert"]->sign($CA["cert"], $DEVICE["cert"], "sha256WithRSAEncryption"); // Sign the new certificate with our CA
$DEVICE["asciicert" ] = $DEVICE["cert"]->saveX509($DEVICE["signedcert"]);   // Ascii our certificate for presentation

print <<<END
User Public key:\n{$DEVICE["keypair"]["publickey"]}\n       
User Private key:\n{$DEVICE["keypair"]["privatekey"]}\n       
User CSR:\n{$DEVICE["asciicsr"]}\n    
CA Cert:\n{$CA["asciicert"]}\n    
User Certificate:\n{$DEVICE["asciicert"]}\n    
END;    
?>

下面是这个程序的一些示例输出:

...
User CSR:
-----BEGIN CERTIFICATE REQUEST-----
MIIC1DCCAb4CAQAwgZQxCzAJBgNVBAYMAlNTMRAwDgYDVQQIDAdvYnNjdXJlMRAw
DgYDVQQHDAdvYnNjdXJlMQ8wDQYDVQQKDAZzZWN1cmUxGDAWBgNVBAsMD25ldHdv
cmtzZWN1cml0eTEXMBUGA1UEAwwOdGVzdGVyQGNvbW1hbmQxHTAbBgkqhkiG9w0B
CQEMDnRlc3RlckBjb21tYW5kMIIBIDALBgkqhkiG9w0BAQEDggEPADCCAQoCggEB
ANzsEUPULfmkbDK2DLTWUbHxpqbxiQ0WF5vuUOXutcdJADG9uExyllRtnPmUq3yV
GhfF/jbKKwXrDMTc9JLRoPRjbCesHQq9p+WU2pgzHWOGne3b2SNB6ISSVUbmZwRd
3Uu78u2EIPw2yB/YAdMaSipuLnA4jbGwWHtMXWSr9g0en+CkJ0cHN3P0GAnDR7BF
2pq88si5Who9Dvn/Mo3npMZiAmD5D7qwD88mVFMC1j4q1xnqHi2X19Xz9+xgWZ1h
IdedpWh+v0i2kHE73Csu0Jiczxb28zdm+MjBEYGZ6X6LzCYHI5kx2wDKsxuxraMf
sY0QS/kATiTzSJMcWzxR82UCAwEAATALBgkqhkiG9w0BAQsDggEBABuThxlknbCS
Fzd8B+eM98uFW6YQmfp5js/S2+Cor3+btGi2d/siXDGusW7ceOEv4WLRikrv+0tt
rHNzndhl77ukSikA0H0VMUqNFYIL1N//W2nDhphYKWwKWHGoQ+/ZH30aLgw43iNz
IzWAj2d39bGEqAvGPzU6BDpm8o1ucMoJaqUAHNov69Ro/n+rb0k3ouuTqjewF781
lQFHMPhUY4j2JbGKpah3qPGvAgc44JR6VmG6Rh9nVhcZz5szit8K1UTgvIlSl7EH
7ggBHQl67kON19JKlKneJVsD36tczkEhuDGU5Dv4TH7SLiKwIRYHulD3bmqg2/Nq
sGAxVviaKBA=
-----END CERTIFICATE REQUEST-----

CA Cert:
-----BEGIN CERTIFICATE-----
MIIDVTCCAj2gAwIBAgICEA8wDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMCU1Mx
EjAQBgNVBAgMCVNlY3VyZSBDQTESMBAGA1UEBwwJU2VjdXJlIENBMRIwEAYDVQQK
DAlTZWN1cmUgQ0EwHhcNMTUwMjAxMTkzNjA2WhcNMTYwMjAxMTkzNjA2WjBPMQsw
CQYDVQQGEwJTUzEPMA0GA1UECAwGU2VjdXJlMQ8wDQYDVQQKDAZTZWN1cmUxHjAc
BgNVBAMMFW5ldHdvcmtzZWN1cml0eS5uaW5qYTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAN7PJWsyd3Hn7q5/Y4N9Dcpvtip/hiSEFwrkl4UWd+bD7CGz
wQjyZziVAj7mXjgTrPCmMzwV/aRtT2WM7l1vI8WV0swsTEidvZF+EDEAujnadMxr
8JWVC+ljYvhy7nIDRYpPwkKSBWpIF1UFaG8MduHxBtqlRlOJoIDQmJkLQO5fV/kv
cujct4myMhar6TPx52xWX0FLt0B3Rn04Rb0InstyDY0NtrTMsgSq32rj3sijTCAG
WDsnxNO+jsC7uFAjjldcWnqBs7of+sVb7TPiEsq/5adE6G50ctqW8H7JpY+SFZzG
Y+wPRUxJZsYq4qt/rkEv7ldtsbhHD6wO4I61eksCAwEAAaNBMD8wDAYDVR0TBAUw
AwEB/zALBgNVHQ8EBAMCBeAwIgYDVR0RBBswGYIXKi5uZXR3b3Jrc2VjdXJpdHku
bmluamEwDQYJKoZIhvcNAQELBQADggEBAMsXyUX95AkQKadbaZ1XEWoayElWtKUc
dRB15XDJ7xoWGQo/fDYebXOJMPffIQoOGtRZcYtPaVjr3PMUCaxIAUvdmO3UMfLh
M8kQhYBzyEKw+SRwcUHmKbU8Tz5AolL1qjoNm5SWBV9RbFj2TRcR27v/apmhIR+K
6KKbcIXklKhhBPacJL7NwAgibb8Ip4OtxSuzarydddPryAwTwUSJNlmozRAx7dFk
xLkLMQMqEtW7BmJqU+YUczddYvbsxmYqfaChM/TBo7VZd84RlWoXOqqfon6JGLWN
5lN86iVnfXeGLbhLt5GKWB6e4rUbiMAqmGYO6Cd2BMFRtlp9IYZIBSY=
-----END CERTIFICATE-----

User Certificate:
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----

签名的证书是空白的,我真的很困惑。到位的错误检查似乎让我认为如果有问题它会简单地 return FALSE,但是在 ----- 行之间得到空白输出让我想知道发生了什么。

来自您的代码:

$DEVICE["cert"      ]->loadX509( $DEVICE["asciicsr"] );

试试这个:

$DEVICE["cert"      ]->loadCSR( $DEVICE["asciicsr"] );