无法在 PHP 中创建 OpenSSL S/MIME 证书

Cannot create OpenSSL S/MIME certificate in PHP

我可以在命令行上创建 S/MIME 证书就好了:

openssl genrsa -out some_cert.key 4096
openssl req -new -key some_cert.key -out some_cert.csr

然后由我自己的权限签署证书:

openssl x509 -req -in some_cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out some_cert.crt

然后将其作为“人民”证书导入 Thunderbird。

但是 - 在同一台 Linux 机器上(即相同的 OpenSSL cnf) - 我 不能 在 PHP:

$directory = "/tmp";
$path = "/path/to/authority";
$ca = file_get_contents($path . '/ca.crt');
$cakey = array(file_get_contents($path . '/ca.key'), "authorityKeyPass");
$dn = array(
    "countryName" => "UK",
    "stateOrProvinceName" => "Scotland",
    "localityName" => "Aberdeen",
    "organizationName" => "Someorg",
    "organizationalUnitName" => "Someunit",
    "commonName" => foo@domain.org,
    "emailAddress" => foo@domain.org
);
$config = array(
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
    'x509_extensions' => 'v3_ca',
);

// Generate a new private key
$privkey = openssl_pkey_new($config);

// Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey);

// Sign certificate
$sscert = openssl_csr_sign($csr, $ca, $cakey, 365);

// Export CRT (public key)
openssl_x509_export($sscert, $certout);

// Save to file
file_put_contents('/tmp/serverCASigned.crt', $certout);

文件已正确保存,但我无法将其作为“人民”证书导入到 Thunderbird:无错误消息,只是导入对话框关闭且未导入证书。

并且命令行生成的 .crt 文件的大小与 php...

中生成的文件的大小不同

果然是签名部分

我找到的最佳解决方案是使用 phpseclib:

// Load the library phpseclib
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include_once('File/X509.php');
include_once('Crypt/RSA.php');

// CA Private key
$CAPrivKey = new Crypt_RSA();
$CAPrivKey->setPassword("authorityKeyPass");
$CAPrivKey->loadKey(file_get_contents($path . "/ca.key"));

// CA Authority
$issuer = new File_X509();
$issuer->setPrivateKey($CAPrivKey);
$issuer->loadX509(file_get_contents($path . "/ca.crt"));

// Subject - who will be signed by authority
$subject = new File_X509();
$subject->loadCSR($csrout);

// And sign it
$x509 = new File_X509();
$x509->setStartDate('-1 month');
$x509->setEndDate('+5 year');
$x509->setSerialNumber(mt_rand(1, 2147483647) . mt_rand(1, 2147483647));
$result = $x509->sign($issuer, $subject);

// Save to file
file_put_contents('/tmp/serverCASigned.crt', $x509->saveX509($result));

并且一切正常...