2019年12月

实际可用的CA签名程序:ca_sign.php.txt

本站点CA签发数字证书申请

实例演示:
关于PHP生成证书密钥的资料真是好少啊,查了半天,最终还是在官方文档找到了相关资料,又根据自己的理解,整理成了以下代码,分成两部分:生成证书密钥、加密解密数据。直接复制下来做成两个文件运行就好啦。已经写了详细的注释,相信PHP程序员都能看得懂。

generate.php

$dn = array(  
        "countryName" => 'CN', //所在国家名称  
        "stateOrProvinceName" => 'GD', //所在省份名称  
        "localityName" => 'GZ', //所在城市名称  
        "organizationName" => 'DGQ',   //注册人姓名  
        "organizationalUnitName" => 'GDEC', //组织名称  
        "commonName" => 'www.dgq.com', //公共名称  
        "emailAddress" => 'user@domain.com' //邮箱  
);  
    $privkeypass = '111111'; //私钥密码  
    $numberofdays = 3650;     //有效时长  
    $cerpath = "./test.cer"; //生成证书路径  
    $pfxpath = "./test.pfx"; //密钥文件路径  
   
    //生成证书  
    $cacert = file_get_contents("./cacert.cer"); //CA证书文件
    $cakey = array(file_get_contents("./private/cakey.pem"),NULL); //CA私钥文件
    $privkey = openssl_pkey_new( array(" private _key_bits" => 2048,    "private_key_type" => OPENSSL_KEYTYPE_ RSA ) ); 
    $csr = openssl_csr_new($dn, $privkey, array('digest_alg' => 'sha256')); 

    //$sscert = openssl_csr_sign($csr, null, $privkey, $numberofdays); //自签证书
    $sscert = openssl_csr_sign($csr, $cacert, $cakey, $numberofdays,array('digest_alg' => 'sha256')); //CA签发证书
    openssl_x509_export_to_file($sscert, $cerpath); //导出证书到文件
    openssl_pkcs12_export_to_file($sscert, $pfxpath, $privkey, $privkeypass); //生成密钥文件 

crypt.php

//私钥加密

$cer_key = file_get_contents($pfxpath); //获取密钥内容

openssl_pkcs12_read($cer_key, $certs, $privkeypass);
openssl_sign($data, $signMsg, $certs['pkey'],OPENSSL_ALGO_SHA1); //注册生成加密信息

$signMsg = base64_encode($signMsg); //base64转码加密信息
echo $signMsg;


//公钥解密
$cer_key = file_get_contents($cerpath); //获取证书内容

$unsignMsg=base64_decode($signMsg);//base64解码加密信息

$cer = openssl_x509_read($cer_key); //读取公钥
$res = openssl_verify($data, $unsignMsg, $cer); //验证
echo $res; //输出验证结果,1:验证成功,0:验证失败

一个简单的加密解密类:

class RsaCrypt {
    const PRIVATE_KEY_FILE_PATH = './rsa_private_key.pem';
    const PUBLIC_KEY_FILE_PATH = './rsa_public_key.pem';

   
    public static function encode($orignData) {
       //密钥文件的路径
       $privateKeyFilePath = self::PRIVATE_KEY_FILE_PATH;
       extension_loaded('openssl') or die('php需要openssl扩展支持');
       (file_exists($privateKeyFilePath)) or die('密钥的文件路径不正确');
       //生成Resource类型的密钥,如果密钥文件内容被破坏,openssl_pkey_get_private函数返回false
       $privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFilePath));
     
       ($privateKey) or die('密钥不可用');
       //加密以后的数据,用于在网路上传输
       $encryptData = '';
       ///////////////////////////////用私钥加密////////////////////////
       if (openssl_private_encrypt($orignData, $encryptData, $privateKey)) {
           return $encryptData;
       } else {
           die('加密失败');
       }
    }
   
    public static function decode($encryptData) {
       //公钥文件的路径
       $publicKeyFilePath = self::PUBLIC_KEY_FILE_PATH;
       extension_loaded('openssl') or die('php需要openssl扩展支持');
       (file_exists($publicKeyFilePath)) or die('公钥的文件路径不正确');
       //生成Resource类型的公钥,如果公钥文件内容被破坏,openssl_pkey_get_public函数返回false
       $publicKey = openssl_pkey_get_public(file_get_contents($publicKeyFilePath));
       ($publicKey) or die('公钥不可用');
       //解密以后的数据
       $decryptData = '';
       ///////////////////////////////用公钥解密////////////////////////
       if (openssl_public_decrypt($encryptData, $decryptData, $publicKey)) {
           return $decryptData;
       } else {
           die('解密失败');
       }
    }
}

特别说明:

x509,公钥证书,只有公钥。
p7,签名或加密。可以往里面塞x509,同时没有签名或加密内容。
p12,含有私钥,同时可以有公钥,有口令保护。
p7的作用就是电子信封。
X509是基本规范
P7和P12是两个实现规范,P7是数字信封,P12是带有私钥的证书规范。
x509是数字证书的规范,P7和P12是两种封装形式。比如说同样的电影,有的是avi格式,有的是mpg,大概就这个意思。

P7一般是把证书分成两个文件,一个公钥一个私钥,有PEM和DER两种编码方式。PEM比较多见,就是纯文本的,P7一般是分发公钥用,看到的就是一串可见字符串,扩展名经常是.crt,.cer,.key等。DER是二进制编码。
P12是把证书压成一个文件,.pfx 。主要是考虑分发证书,私钥是要绝对保密的,不能随便以文本方式散播。所以P7格式不适合分发。.pfx中可以加密码保护,所以相对安全些。
在实践中要中,用户证书都是放在USB Key中分发,服务器证书经常还是以文件方式分发。服务器证书和用户证书,都是X509证书,就是里面的属性有区别。

X509 是证书规范
PKCS#7 是消息语法 (常用于数字签名与加密)
PKCS#12 个人消息交换与打包语法 (如.PFX .P12)打包成带公钥与私钥

set up ocsp using openssl

Assuming that you already have an OpenSSL Certificate Authority set up, you will need to make a couple of changes to your openssl.cnf file. Add a new line to the usr_cert stanza

[ usr_cert ]
authorityInfoAccess = OCSP;URI:http://

create a new stanza

[ v3_OCSP ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning

For this example, the OCSP server will be running on ca.isrlabs.net on port 8888, so the authorityInfoAccess line will look like:

authorityInfoAccess = OCSP;URI:http://ca.isrlabs.net:8888

This line will add a new attribute to issued certs that tells clients where the CA’s OCSP server is located so it can check the validity of the cert. The new v3 template assigns a neccesary attribute “OCSPSigning” to any certificate issued under this template. We will need to issue an OCSP signing certificate to the OCSP server with the OCSPSigning attribute, otherwise signature verification will fail when a cert is being checked. This is the first thing we will do:

openssl req -new -nodes -out ca.isrlabs.net.csr -keyout ca.isrlabs.net.key -extensions v3_OCSP

Sign the request with the CA signing key:

openssl ca -in auth.isrlabs.net.csr -out auth.isrlabs.net.crt -extensions v3_OCSP

OpenSSL should show the signing request, look for this in the X509v3 extensions:

X509v3 Extended Key Usage:
OCSP Signing

Sign and commit the request. Now, issue a throwaway cert and sign it

openssl req -new -nodes -out dummy.isrlabs.net.csr -keyout dummy.isrlabs.net.key

openssl ca -in dummy.isrlabs.net.csr -out dummy.isrlabs.net.crt

Next, start up the OCSP server.

openssl ocsp -index /etc/pki/CA/index.txt -port 8888 -rsigner ca.isrlabs.net.crt -rkey ca.isrlabs.net.key -CA /etc/pki/CA/cacert.pem -text -out log.txt

Once the dummy cert has been been issued and the OCSP server started, we can test the cert using the “openssl ocsp” command. To verify a certificate with OpenSSL, the command syntax is:

openssl ocsp -CAfile -issuer -cert -url -resp_text

So to test our dummy file:

openssl ocsp -CAfile cacert.pem -issuer cacert.pem -cert dummy.isrlabs.net.crt -url http://ca.isrlabs.net:8888 -resp_text

There’s going to be a large block of text flooding the screen. Some of the more important text:

OCSP Response Data:
OCSP Response Status: successful (0×0)
Response Type: Basic OCSP Response

Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 922CD93C975EDC121DB25B1A55BA9B544E06F9B3
Issuer Key Hash: 322A8DBF79BE1A934543DC4F24FC69220A2803BA
Serial Number: 06
Cert Status: good

Response verify OK
dummy.isrlabs.net.crt: good
This Update: Feb 27 00:55:54 2012 GMT

Now revoke the cert, regenerate the CRL and restart the OCSP server (the server must be restarted every time a cert is issued or revoked). If the OCSP signing certificate was not issued with the OCSPSigning attribute, OpenSSL will gripe that the verification did not work properly. Reissue the signing cert with the OCSPSigning attribute for the server.

openssl ca -revoke /etc/pki/CA/newcerts/06.pem

openssl ca -gencrl -out /etc/pki/CA/crl.pem

Now we can verify the certificate again:

openssl ocsp -CAfile /etc/pki/CA/cacert.pem -issuer /etc/pki/CA/cacert.pem -cert dummy.isrlabs.net.crt -url http://ca.isrlabs.net:8888 -resp_text

OCSP Response Status: successful (0×0)
Response Type: Basic OCSP Response

Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 922CD93C975EDC121DB25B1A55BA9B544E06F9B3
Issuer Key Hash: 322A8DBF79BE1A934543DC4F24FC69220A2803BA
Serial Number: 06
Cert Status: revoked
Revocation Time: Feb 27 01:07:36 2012 GMT
This Update: Feb 27 01:12:08 2012 GMT

Response verify OK
dummy.isrlabs.net.crt: revoked
This Update: Feb 27 01:12:08 2012 GMT
Revocation Time: Feb 27 01:07:36 2012 GMT

If you were to install this cert on a website, and the CA certificate was installed, any modern browser should refuse to connect to the site as the cert has been revoked.

in
openssl req -new -nodes -out ca.isrlabs.net.csr -keyout ca.isrlabs.net.key -extensions v3_OCSP

openssl ca -in auth.isrlabs.net.csr -out auth.isrlabs.net.crt -extensions v3_OCSP

should not ca.isrlabs.net.csr on first command match
auth.isrlabs.net.csr ?

I matched both names in the command, but when I do

openssl ca -in isrlabs.csr -cert ca.crt -keyfile ca.key -out isrlabs.crt -extensions v3_OCSP

I get:

Using configuration from /usr/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName RINTABLE:’US’
organizationName :ASN.1 12:’U.S. Government’
organizationalUnitName:ASN.1 12:’DoD’
organizationalUnitName:ASN.1 12:’DoDIIS’
commonName :ASN.1 12:’isrlabs’
ERROR: adding extensions in section v3_OCSP
6216:error:2207707B:X509 V3 routines:V2I_AUTHORITY_KEYID:unable to get issuer keyid:v3_akey.c:166:

6216:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:v3_conf.c:93:name=authorityKeyIdentifier, value=keyid:always,issuer:always

It’s an error in the article, the hostname should be ca.isrlabs.net, or whatever the hostname of your issuing CA.