12

**好的,很明显这个问题与在 Linux 服务器上设置 openssl 以及如何正确设置自定义 openssl.cnf 文件有关。我不是在寻找任何复杂的东西,但我需要一个能够创建自签名客户端证书以对我的 web 服务进行身份验证的前端。因此,我需要能够使用我的 CA 为客户公司创建中间 CA,然后允许他们使用安全接口为他们的员工颁发客户证书。登录取决于您是否属于特定的中间 CA,以及您的证书或中间 CA 是否未被吊销。

对于任何想知道的人,我们可以使用自签名证书,因为它们仅用于我们的服务器对用户进行身份验证,并且由于我们颁发了它们,因此我们信任它们。此外,对于初创公司来说,通过商业产品 AFAIK 将自己确立为中间 CA 的成本也太高了。微软可以做到,我们做不到。我们的网络服务器本身使用 CA 签名证书。

我知道用于设置这种事情的 php 代码是直截了当的,但不是如何正确设置 openssl。我在网上尝试了几个不同的例子,但它们似乎都不适用于我的设置,而且它们似乎都不同。一盒是全新安装的 Centos 6.2,但我仍然遇到错误。

谁能指出我设置 openssl、apache2 和 php 的正确方向,以便我可以使用这些 php 库而不会出错?我们的虚拟服务器正在使用 debian 挤压,我可以完全控制安装的软件。

谢谢。

open_pkey_new()返回错误,例如 error:0E06D06C:configuration file routines:NCONF_get_string:no value。但是我正在传递一个到 openssl.cnf 文件的路径,所以我不知道为什么我仍然遇到这个问题。这是我的相关代码

<?php
$cwd=getcwd();
$distname= array(
    "countryName" => "CA",
    "stateOrProvinceName" => "Ontario",
    "localityName" => "Toronto",
    "organizationName" => "G4 Apps",
    "organizationalUnitName" => "Development",
    "commonName" => "Mark Lane",
    "emailAddress" => "nobody at gmail.com"
        );
$password = 'seanix';

$cacert_location=$cwd."/certs/CA/g4CA.crt";
$cakey_location=$cwd."/certs/CA/g4CA.key";
$cnf=$cwd.'/certs/myopenssl.cnf';
$configArgs = array(
        'config' =>$cnf
);
?>

这是我制作钥匙的功能。

<?php
function makekey($password,$configArgs) {
    $key= openssl_pkey_new($configArgs);
    //print_r($configArgs);
    openssl_pkey_export($key, $pkeyout,$password);
    if (($e=openssl_error_string()) ==false) return $pkeyout;
    else {
        do {

            echo $e . "<BR>";
        } while($e=openssl_error_string());
        return -1;
    }
}
?>

我也尝试过配置文件的相对路径,但它仍然无法正常工作。看起来可能是主机提供商 ssl 设置。我切换到本地虚拟机并获得了生成密钥,但现在在创建 csr 时遇到了同样的错误。

错误:0E06D06C:配置文件例程:NCONF_get_string:无值

<?php
function newcsr($distname,$key,$configArgs) {
    $csr=openssl_csr_new($distname,$key,$configArgs);
    openssl_csr_export($csr, $csrout);
    if (($e=openssl_error_string()) ==false) return $csrout;
    else {
        do {

            echo $e . "<BR>";
        } while($e=openssl_error_string());
        return -1;
    }
}
?>

openssl.conf这看起来是 openssl.cnf 中的错误,所以我已包含该文件。

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

oid_section     = new_oids


[ new_oids ]


tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

####################################################################
[ ca ]
default_ca  = g4CA      

####################################################################
[ g4CA ]

dir     = /home/g4apps/secure.g4apps.com/generator/certs    
certs       = $dir/     
crl_dir     = $dir/crl      
database    = $dir/index.txt    


new_certs_dir   = $dir/newcerts     

certificate = $dir/CA/g4CA.crt  
serial      = $dir/serial       
crlnumber   = $dir/crlnumber    

crl     = $dir/CA/g4CA.crl  
private_key = $dir/CA/g4CA.key  
RANDFILE    = $dir/private/.rand    

x509_extensions = usr_cert      

name_opt    = ca_default        
cert_opt    = ca_default        


default_days    = 365           # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md  = default       # use public key default MD
preserve    = no            # keep passed DN ordering

policy      = policy_match


[ policy_match ]
countryName     = match
stateOrProvinceName = match
organizationName    = match
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

[ policy_anything ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ req ]
default_bits        = 2048
default_md      = md5
default_keyfile     = privkey.pem
distinguished_name  = req_distinguished_name
attributes      = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert

string_mask = utf8only

[ req_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = CA
countryName_min         = 2
countryName_max         = 2

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = ON

localityName            = Locality Name (eg, city)
localityName_default    = Toronto

0.organizationName      = Organization Name (eg, company)
0.organizationName_default  = G4 Apps



organizationalUnitName      = Organizational Unit Name (eg, section)

commonName          = Common Name (eg, your name or your server\'s hostname)
commonName_max          = 64

emailAddress            = Email Address
emailAddress_default        = lmlane@gmail.com
emailAddress_max        = 64


[ req_attributes ]
challengePassword       = A challenge password
challengePassword_min       = 4
challengePassword_max       = 20

unstructuredName        = An optional company name

[ usr_cert ]

nsComment           = "OpenSSL Generated Certificate"

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer



[ v3_req ]


basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]


subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true


[ crl_ext ]

authorityKeyIdentifier=keyid:always

[ proxy_cert_ext ]
basicConstraints=CA:FALSE

nsComment           = "OpenSSL Generated Certificate"

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

####################################################################
[ tsa ]

default_tsa = tsa_config1   

[ tsa_config1 ]

dir             = ./demoCA      
serial      = $dir/tsaserial    
crypto_device   = builtin       
signer_cert = $dir/tsacert.pem  

certs       = $dir/cacert.pem   
signer_key  = $dir/private/tsakey.pem 
default_policy  = tsa_policy1       
other_policies  = tsa_policy2, tsa_policy3
digests     = md5, sha1     
accuracy    = secs:1, millisecs:500, microsecs:100  
clock_precision_digits  = 0 
ordering        = yes   

tsa_name        = yes   
ess_cert_id_chain   = no    

堆栈跟踪strace php getkeystore.php &> stack.trace

http://secure.g4apps.com/generator/stack.trace

4

6 回答 6

7

我在我的 Mac 和全新安装的 CentOS 6.3 上试过这个,我得到了同样的错误。我从 IUS 得到我的 CentOS 软件包。但这很奇怪,因为即使我收到了这条消息,实际上也正在生成密钥。

以下代码:

$res = openssl_pkey_new();
openssl_pkey_export($res, $privkey);
var_dump(openssl_error_string());
var_dump($privkey);

给我以下输出:

string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value"
string(887) "-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDdh4FiOEtUZzvTSnlb/pJHjmsS9rOHQ7PU2WOO6ZHxYRIgK1NR
ReY7bBwEsT2ziUpx0b8K2Fx4m+XovzysB/lVrKbrdbHoVtGuJGZjYSXgFlCRTBu+
+TnAPUBF0LGJfxfVzjOkHzsh02lH3fvzFpFgRZRWs4za+vVzIweeOweYTwIDAQAB
AoGANZD5iS2BkZQw1COS+tqwtlrKq1g6CwAk8NfsCfeSkaJeRqcTS3iydjXrBHtz
JwGQnbsRDedJXOSdkE0Ft7dp44lijOAp1ngMDCKbabxVN2Go6b1d743HE0oIhFCC
Dv2B9kf9vzeYy+0/BVCs5i4iPoKXJJTSJrWoDxrFEJWSJIkCQQDwe39bOFHmQlxz
pbfT3DZ8Q311xFo6PewcAf7DTsikoPZANx0GQ41WdZj6/n4QVP4k+TnhZLiJzsH+
p3RUrx8tAkEA69LsgPrQMZ0YjsE2vjRLdJmp1916G1xqSLIVWDUPd9Ns+MA8YKTx
AQxC3dl3n+w24m7UlCThANlU/+2r0eoi6wJBAKIxGOdEJ/Cdp08UYNRR/Kl4t2A7
SwNnChylt9awByEJsqwCv9+epe+/Jqt6AzouqK31LXV4AgJn4W1IMWyAJA0CQCp0
6/2AqnD0PpKc+JUf5yHT9H8Xsb8xUTVLUopx6xoAp5LVUUl5CKbOpU85ss7JAUyc
9YrCZPv5JNN6379ILwcCQQDDcjtNnhQHukQQQ8iVL9YCrWzyCgplTz3uktueT+Dd
SDK1bCM4xDehfG3RKu1ZNx80Q0nzmi7FSPJ2md7qSIHc
-----END RSA PRIVATE KEY-----
"

我怀疑这是PHP中的一个错误。某种 openssl 配置 PHP 被挂断了。我在 php.net 上找到了一个关于此的错误报告,但它为用户“开始工作”,因此该错误已关闭。

作为替代方案,您可以查看phpseclib,这是一个纯粹用 PHP 编写的库。

于 2012-11-22T19:13:21.283 回答
3

使用 openssl_csr_new 时,请确保第一个参数 $dn 不包含具有空值的键。

例如,此调用openssl_csr_new将触发错误

0E06D06C:configuration file routines:NCONF_get_string:no value

<?php

$dn = [
    'CN' => 'example.com',
    'ST' => '',
    'C'  => '',
    'O'  => '',
];

openssl_csr_new($dn, $privKey);
于 2018-02-16T10:11:30.293 回答
2

检查您的 openssl.cnf 是否有

default_md = md5

在其中,否则将其添加到 cnf 文件中,如果有帮助,请重试。

于 2012-08-21T18:31:42.203 回答
1

根据@Luke提到的错误 ,我的结论是:

openssl_pkey_new() 不返回值,因此为 "FALSE"

var_dump() 只是说它返回一个 OpenSSL 密钥。

“所以它起作用了 - “NCONF_get_string:no value”只是某种通知。” - vrana@php.net

openssl_csr_new() (也许更多)有类似的行为。

于 2017-10-26T13:00:11.123 回答
1

我已经打了这个问题十几次,所以是时候投入我的 2 美分了:由于(恕我直言)PHP 完成的一些向后配置解析,否则有效/超级复杂的 openssl.cnf 可能会导致多达 10 个警告。在将头撞到墙上后,我做了一个垫片,以便 OpenSSL 和 PHP 可以和平共存。

与其弄乱您的 openssl.cnf,不如制作您自己的骨架 cnf 并在其中包含默认值,如下所示:

#PHP shim for an otherwise beautiful openssl.cnf
#Notes:
# duplicate OID definitions fail
# duplicate OID usage generates a warning in most cases
# All duplicate sections/values are overlayed: PHP > shim > include > default
RANDFILE    = /dev/null #PHP warns if this doesn't exist
oid_file    = /dev/null #PHP warns if this doesn't exist
#PHP warns if oid_section isn't in the default section
#PHP warns if oid_section is used in another section (only on initialization)
oid_section = php_oids  #set an empty OID section
.include /etc/ssl/openssl.cnf    #include our working conf
[ req ]
  #included format differs from expected format
  attributes         = php_attr #openssl_csr_new()
  #not set in include
  encrypt_rsa_key    = yes #overriden by encrypt_key
  #uncomment to override include, or if otherwise unset
  #req_extensions     = php_req_extension #overridden by req_extensions
  #x509_extensions    = php_x509_extension #overridden by x509_extensions
  #default_bits       = 4096          #overridden by private_key_bits
  #default_md         = sha512        #overridden by digest_alg
  #string_mask        = utf8only      #overridden by string_mask
  #distinguished_name = php_distinguished_name #openssl_csr_new()
[ php_attr ] #empty attributes section
  #challengePassword = password
  #unstructuredName = i_prefer_structure
  ##NO *_min,*_max,*_default
  ##challengePassword         = A challenge password (6-20 characters)
  ##challengePassword_min     = 6
  ##challengePassword_max     = 20
  ##challengePassword_default = this_wont_work
[ php_oids ] #empty OID section (no duplicates in this section)
  #test_cert = 2.23.140.2.1
  ##NO short_id=long_id,id_num
  ##TEST = test_cert, 2.23.140.2.1
[ php_distinguished_name ] #empty DN section
  #commonName         = Common Name (CN)
  #commonName_min     = 1
  #commonName_max     = 63
  #commonName_default = this_works
  #streetAddress      = this_also_works
  #0.organizationalUnitName = this_actually_works
  #ONLY THE FIRST OID IS USED
  ##1.organizationalUnitName = this_is_silently_discarded
[ php_x509_extension ] #empty x509 extension section
  subjectKeyIdentifier   = hash #at least one value required
  #authorityKeyIdentifier = keyid:always
  #keyUsage               = critical, digitalSignature, cRLSign, keyCertSign
  #basicConstraints       = critical, CA:true, pathlen:0
  #certificatePolicies    = ia5org, test_cert
  #authorityInfoAccess    = @ocsp_ext
  #crlDistributionPoints  = @crl_ext
  #tlsfeature             = status_request_v2
[ php_req_extension ] #empty req extension section
  subjectKeyIdentifier   = hash #at least one value required
  #keyUsage               = critical, nonRepudiation, digitalSignature, keyEncipherment
  #extendedKeyUsage       = critical, clientAuth, emailProtection
  #basicConstraints       = critical, CA:FALSE
  #certificatePolicies    = ia5org, test_cert
  #authorityInfoAccess    = @ocsp_ext
  #crlDistributionPoints  = crl_ext
  #tlsfeature             = status_request_v2
  #nsComment              = "OpenSSL 1.1.1c Generated Client Certificate"

除了 [req] 部分,请随意删除所有注释以缩小文件。

这是相应的 PHP 文件来测试它:

<?php
  //Serial can't be our desired 20 byte random hex:
  //  [bin2hex(random_bytes(20))] is ideal
  //  [8 bytes] PHP_INT_MAX
  //  file a bug report?
  //NO subjectAltName !!!!!
  //ini_set('openssl.cafile','/etc/ssl/certs/my-ca.crt');
  //ini_set('openssl.capath','/etc/ssl/certs/');
  $pass='password';
  $capass='capass';
  /* it's best to set all of these values in PHP to avoid confusion */
  $config=[
   /*'digest_alg'      =>'sha512',                     /*default_md*/ /*openssl_get_md_methods()*/
   /*'private_key_bits'=>8192,                         /*default_bits*/
   /*'encrypt_key'     =>true,                         /*encrypt_key,encrypt_rsa_key*/
   /*'string_mask'     =>'utf8only',                   /*string_mask - undocumented*/
   'x509_extensions' =>'x509_ext_orig',                /*x509_extensions*/
   'req_extensions'  =>'usr_cert_orig',                /*req_extensions*/
   'private_key_type'  =>OPENSSL_KEYTYPE_EC,
   'encrypt_key_cipher'=>OPENSSL_CIPHER_AES_256_CBC,
   'curve_name'        =>'secp384r1',                /*openssl_get_curve_names()*/
   'config'            =>'php-openssl.cnf'           /* export OPENSSL_CONF=php-openssl.cnf */
  ];
  /* all values here OVERWRITE any default DN value */
  $dn=[
   /*'name'=>'', //FAILS- NO EMPTY VALUES*/
   'OU'=>'override_original_OU',
   'surname'=>'new_surname'
  ];
  /* all values here ADD to the default. this array can be multi-dimensional */
  $csrargs=[
   'surname'=>'additional_surname',
   'OU'=>['second_OU','third_OU']
  ];
  $pkargs=[
   /*'extracerts'=>'',*/
   'friendly_name'=>'php-cert'
  ];
  while($err=openssl_error_string()) echo("openssl_init- {$err}\n");
  if($pkey=openssl_pkey_new($config)){ /* create a new private key */
    while($err=openssl_error_string()) echo("openssl_pkey_new- {$err}\n");
    $csr=openssl_csr_new($dn,$pkey,$config,$csrargs); /* generate a csr */
    while($err=openssl_error_string()) echo("openssl_csr_new- {$err}\n");
    print_r(openssl_csr_get_subject($csr,true)); /* show the dn */
    /* sign our CSR using the largest random serial we can */
    $x509=openssl_csr_sign($csr,'file:///etc/ssl/certs/int-ca.crt',['file:///etc/ssl/private/int-ca.key',$capass],30,$config,random_int(72057594037927936,PHP_INT_MAX));
    while($err=openssl_error_string()) echo("openssl_csr_sign- {$err}\n");
    if($x509!==false){
      openssl_pkcs12_export_to_file($x509 ,'/tmp/phpcert.pfx',$pkey,$pass,$pkargs); /* export the keypair as pfx */
      while($err=openssl_error_string()) echo("openssl_pkcs12_export_to_file- {$err}\n");
      openssl_pkey_export_to_file($pkey,'/tmp/phpcert.key',$pass,$config); /* export the private key */
      while($err=openssl_error_string()) echo("openssl_pkey_export_to_file- {$err}\n");
      openssl_pkey_free($pkey); /* free memory */
      openssl_x509_export_to_file($x509,'/tmp/phpcert.crt',true); /* export the signed certificate */
      openssl_x509_free($x509); /* free memory */
      while($err=openssl_error_string()) echo("openssl_x509_export_to_file- {$err}\n");
  }else{
    while($err=openssl_error_string()) echo("openssl_pkey_new- {$err}\n");
  }
?>

希望这会有所帮助。

于 2020-02-10T08:45:09.630 回答
0

在我的配置(FreeBSD、libressl 2.8、php 构建自端口)中,[req] 部分中的条目“default_bits”被注释掉了。

通过启用此配置条目,此问题已得到解决。

于 2019-01-03T21:14:15.243 回答