openssl命令生成根证书和使用根证书签名工作证书

建立根证书流程如下:
//生成私钥,产生CARoot.key文件,需要输入私钥保护口令
openssl genrsa -des3 -out CARoot.key 2048 

//生成证书请求,需要输入CARoot.key私钥保护口令。根据提示输入:国家、省份、组织名、邮箱、等信息。最后生成CARoot.csr证书请求文件。
openssl req -new -key CARoot.key -out  CARoot.csr -config openssl_root_ca.cnf

//签发证书,最后生成自签名的根证书 CARoot.crt
openssl req -x509 -days 666 -key CARoot.key -in CARoot.csr -out CARoot.crt -config openssl_root_ca.cnf


下面将介绍以CARoot.crt为根证书签发下级证书的过程。

//生成自己的私钥
openssl genrsa -des3 -out workCert.key 2048

//生成证书请求文件
openssl req -new -key workCert.key -out workCert.csr -config openssl_root_ca.cnf

//根证书签发下级证书,一定要带上-CAcreateserial参数,否则可能报下面的错误(CAroot.srl No such file or directory)
openssl x509 -req -CA CAroot.crt -CAkey CAroot.key -in workCert.csr -out workCert.crt -days 3650 -CAcreateserial -passin pass:123456

CAroot.crt: CA的证书
CAroot.key: CA的私钥
123456: CA的密码
workCert.csr: 证书请求文件
workCert.crt: 被CA签名后的服务器证书

openssl_root_ca.cnf的配置如下

[ ca ]
default_ca = CA_default

[ CA_default ]
# 放置相关的文件和目录.
dir           = D:/test/ca/root
certs         = $dir/cert
new_certs_dir = $dir/signed_certs
database      = $dir/index.txt
serial        = $dir/serial
RANDFILE      = $dir/private/.rand

# 放置私钥和证书的路径.
private_key   = $dir/private/root_ca.key.pem
certificate   = $dir/cert/root_ca.cert.pem

default_md    = sha256

name_opt      = ca_default
cert_opt      = ca_default
default_days  = 365
preserve      = no
policy        = policy_defualt

[ policy_defualt ]
# 签发证书文件资料的检查 (和根证书必须一样).
countryName            = optional
stateOrProvinceName    = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ req ]
# req 工具需要的參数.
default_bits       = 2048
distinguished_name = req_distinguished_name
string_mask        = utf8only
default_md         = sha256

[ req_distinguished_name ]
# 生成证书是要输入的一些说明信息
countryName            = Country Name (2 letter code)
stateOrProvinceName    = State or Province Name
localityName           = Locality Name
0.organizationName     = Organization Name
organizationalUnitName = Organizational Unit Name
commonName             = Common Name
emailAddress           = Email Address

[ root_ca ]
# 签发根证书时使用
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ intermediate_ca ]
# 签发和发布时使用
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

备注:

dir           = D:/test/ca/root为你自己电脑的目录

在该 目录下需创建cert、private、signed_certs目录,创建index.txt,serial文件,openssl_root_ca.cnf也在该目录下

说明:

CARoot.crt证书打开,内容是 以下这种格式

-----BEGIN CERTIFICATE-----
MIIDfzCCAmcCFDshuNrLclYAPomoTG7AHKMwdO94MA0GCSqGSIb3DQEBCwUAMHwx
CzAJBgNVBAYTAnpnMQswCQYDVQQIDAJoYjEOMAwGA1UEBwwFd3VoYW4xDTALBgNV
BAoMBHdodHkxDTALBgNVBAsMBHdodHkxDTALBgNVBAMMBHdodHkxIzAhBgkqhkiG
9w0BCQEWFHlhbmdtaW5nQHdodHkuY29tLmNuMB4XDTIyMDcyMjA2MDgxOVoXDTI0
MDUxODA2MDgxOVowfDELMAkGA1UEBhMCemcxCzAJBgNVBAgMAmhiMQ4wDAYDVQQH
DAV3dWhhbjENMAsGA1UECgwEd2h0eTENMAsGA1UECwwEd2h0eTENMAsGA1UEAwwE
WbmVxkmFJxEGBRtJV2XdLzkFDP//XCY0PY3TdSVK7zKGyIwwhu5BvZKOCqTMU8As
Annpra/Oivpg7lyBlmIPT6rLDnogfZMeIOT2sRCXDFAC1j5TAcASxtui+9Dg/ohm
rJCXpQkpfUf7g5dfQr/VdWoYckyOK0OqhIIcD7s0CAM1Qu15Sjhd0pLrAgMBAAEw
DQYJKoZIhvcNAQELBQADggEBAEHpkhO4V3XJtW0tPRqPOBZ+q+cQv4OvoXQ8/AT3
dpC9vvV3x9ke7hFPQ+52Y9VyynirmfUQ23ZrmOFmeQLj97g=
-----END CERTIFICATE-----

可以使用以下代码进行解析,然后使用公钥加密

//这里直接把crt证书文件的base64部分取出,作为base64的字符串使用
String hexStr = Base64Util.base64Decode(rootCertBase64);
byte[] decode = Forms.hexStringToByte(hexStr);

//将内容转成流的方式
ByteArrayInputStream bis = new ByteArrayInputStream(decode);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certificate = cf.generateCertificate(bis);

String data = "aaaabbbbccccdddd";
System.out.println("根证书公钥加密原数据: " + data);
//取出公钥--这里的公钥是pkcs8的那种结构型--待核实
PublicKey rootCertPublicKey = certificate.getPublicKey();

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, rootCertPublicKey);
byte[] encData = cipher.doFinal(data.getBytes());
System.out.println("根证书公钥加密: " + Forms.byteToHexString(encData));
            

CARoot.key打开,内容是如下格式,该格式是PKCS#1编码格式,不能直接使用。

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2F477D49DBCF844A

/Snd+opdw9ZNeRfSAiVZJQalI3w3H5T19ojHaf0X6HL1vt5GUMdVgqLv/guXLjPw
/AUqucLbhX/372X5YKgBVneF2wkP2ppHj0etrpJm1pQlKcJjTqFo6DNMGYEUepwc
lNaYYhRBDprffHKiSXM2OFGvzbmJ0s4zabwAgT5hE7BhrDKknOjadDFd9bFI0lX8
LJF7XcUbAbQHPnTcCXp1D4iksJgGA0mjmuB7DgG19TjCTTUdk+L139R8r7UiHsG9
jNJ1X7gvrfkNKeoloTLEdiuYSCxhOd50dAqKpPxlW0RePxUw6iEwNfqmrcOzHUOu
IgcK149cDiqlj27QF5FA1RlJcajsgXFK0yICi9Za1Kz3cKdUmyYxkcBwBG6VcsV1
XQewbOBz8qqMyjyX1u+SQGlxDALCls29Hh3e+Jr5qf1TmZ8nt9CdXzITgeoHmohN
fa2KEyb0Mk1pNMgzYPWXhKsmnFcip2S0Bd8qRhgLVK4Jq5SoWZ2TguD0G+xmNRp1
VHthal0BctDg2oRf/mkoepMEJNGkOH8zVuhfT9D90kuuGtnclYXtCXgyn4QtMk3f
xJGuCE9jc9rs3lKFDgXsOxJxa6ncphCfwQLE1oDrEa+nhEo5RJVSewvuVpyJBNQE
HCuNXRDdxc4NE6SxFKm5CHdJTY5O4YB743b7FX9exzhHd3qUNuh8/Kd6Eht/8RQ2
U4XZ9cm4Z0P4Olrm+sPKaVo4r71/jnXrsjGQlZGKCVbZq2R4r0/jtMCFTogK7wu7
01PGURWPxCdTTPrU8PwIKF12SLNQFuGi8ngZzzC0asmJsyFEO+LJoMsa+ZY22xGa
dxxrJQciX2uRrn99nboHLcLorhcm8oA+9XvvXNLB13+jnRUIpip6F5PgJq7OnTxg
-----END RSA PRIVATE KEY-----

需要先将PKCS#1的编码格式转变为PKCS#8编码的格式,内容如下:

转变的命令为:openssl pkcs8 -topk8 -in CARoot.key -out CARoot.key.p8 -nocrypt

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCe68zN+uVKx0rB
UoYxD/k4ypF7RR1PWfBDv+mf83JGX6yNeXjfb6/G+vaDoHQkur5+jLCbyZ8NZQRp
xyReXfSbigFcRA40nsfN2XxS2r/D6bI6hIqS9At5T7mj/vTmKd+esSXkamGLBAJ6
wlA1ABzDilOcrDyiNmIeCnUQ5E3xxpkMm8w2UpS+KzAodRrtFhQ6gK8UVVwDMF4k
prEDhTOfKy0rM5W3i4o1p11uaW7G6dPeBtPdUcEW5ZIUkzt+y7YCPsrYa8FZVVMJ
yIyaRkp2a+D7st4hgPBUcbpvYItd5XUKKiLXKmiJ9We9w+TA4/J/7iygDu1L4pyH
sgcGDIBBAgMBAAECggEBAJcyAezqSeHGD4Iz0EW3S8XTO2wLCmKnT6Y1XMD3rX30
okcLDYuOR67Ir2X1bupO3NOraI8e2Hq24+b7NsetHf4o4zhz6wv3EGLxCo4NXiq3
GQEBfpFnK89joVu8QiUEK6NgKIvTBjBrRSyj2AlErRkAbqH9X8Z4dQrdqhjDDMD7
UGpdeAa/xI5LjfYlDl44HSGrTqbkC+grNNgeqs+3FrD9FoVVaZz6XLSVuHMD+Thm
MZJ4Dnbf2s3eYKLj8chMiodOYvr1y5H67wSfmqFuB70iU4ZIhgJnzAOM1dmQZArV
2C1mLSRV9FjUJTchLA36Wr/3Z7Ij6QXRNKzk/U/nTscwFOiQA/cV/uMfJT/LKssq
czlrRA92IZ2YIIApPE3mttW6
-----END PRIVATE KEY-----

以上PKCS#8的格式使用如下:

String base64Decode = Base64Util.base64Decode(privateKeyBase64);
// System.out.println("下级证书私钥base64Decode: " + base64Decode);
byte[] keyBytes = Forms.hexStringToByte(base64Decode);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decData = cipher.doFinal(encData);
System.out.println("下级证书私钥解密: " + Forms.byteToHexString(decData));

公钥加密,私钥解密;私钥签名,公钥验签

public static void testPubKey(){
        try {
            //公钥证书
            String workCert = "MIIDtzCCAp8CFEHdcA7b5rGZmtBflLQ6O/97RZW2MA0GCSqGSIb3DQEBCwUAMIGN\n" +
                    "MQswCQYDVQQGEwJ6ZzEOMAwGA1UECAwFaHViZWkxEzARBgNVBAcMCnlhbmdfaHVi\n" +
                    "ZXUxEzARBgNVBAoMCnlhbmdfaHViZWkxEzARBgNVBAsMCnlhbmdfaHViZWkxEzAR\n" +
                    "BgNVBAMMCnlhbmdfaHViZWkxGjAYBgkqhkiG9w0BCQEWC3lhbmdAcXEuY29tMB4X\n" +
                    "DTIyMDczMDAzMDQxNVoXDTMyMDcyNzAzMDQxNVowgaExCzAJBgNVBAYTAnpnMQ4w\n" +
                    "DAYDVQQIDAVodWJlaTEYMBYGA1UEBwwPeWFuZ193b3JrX2h1YmVpMRgwFgYDVQQK\n" +
                    "DA95YW5nX3dvcmtfaHViZWkxGDAWBgNVBAsMD3lhbmdfd29ya19odWJlaTEYMBYG\n" +
                    "A1UEAwwPeWFuZ193b3JrX2h1YmVpMRowGAYJKoZIhvcNAQkBFgt5YW5nQHFxLmNv\n" +
                    "bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM14s8Y+Ky9EWRhkEsxq\n" +
                    "qPNaGS+FyUdLJMR7v9SUY0fH0UpYMV7hYRZC1SEeK8Ig5GwIhPRIQ2dotr8oDd6R\n" +
                    "kNytraMd668998o9TavHVjNQPzKuPNDtBklD0TNB2a5p/4aw5sC8kUh1WBtAAyz9\n" +
                    "yZ8gZu5EAxSZd2lm/t1AAv06JNTDVqQqH2C0UUeRyQ6f3rKLOqQWMjoVysWqn+ge\n" +
                    "IfGlJO70R+3nF6q60epFY9CO/3kJ00xUi6CpOw0u9886bEPmhsr0dAcjPRCOkSWj\n" +
                    "xMCLlb7aTKEQAK1wPiSiDAgUzwlOEFlhF4GX/dv2o8qcDqbxlGYQBSyBvm9UxrPO\n" +
                    "1m8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAD6zKXeudVHVtY/tuPjipOSuLTmhU\n" +
                    "+pbymWelXYVFuvLgm24p+L3w4/NK/51hIMMhzX4DrXbVExAqF5oHA3OdCwn/VoRR\n" +
                    "V/tdbZhWDUUS/bE9oj1UyQcP9cLHm5YQ6fCKgvqy6yfgp5JaV5u72gVwJrHcZcuh\n" +
                    "wJshkb+V1OEdgAz05P47yxlTP029dVvI9159SPewMss6D9JvutQFXsAeNIGIKmJy\n" +
                    "0auCbKKNmngP4UnkIW6lUx9FhJ4tRk3nppIf48qkweIPbtWnNbyW+MeDTmIR3Bst\n" +
                    "T8/gZoX6ZLdrrLCJd7+BY7/vxHkx91Dn/AtsjskzzH+yOTN3UHqDMam9vw==";
            //证书私钥
            String workCertPrivateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNeLPGPisvRFkY\n" +
                    "ZBLMaqjzWhkvhclHSyTEe7/UlGNHx9FKWDFe4WEWQtUhHivCIORsCIT0SENnaLa/\n" +
                    "KA3ekZDcra2jHeuvPffKPU2rx1YzUD8yrjzQ7QZJQ9EzQdmuaf+GsObAvJFIdVgb\n" +
                    "QAMs/cmfIGbuRAMUmXdpZv7dQAL9OiTUw1akKh9gtFFHkckOn96yizqkFjI6FcrF\n" +
                    "qp/oHiHxpSTu9Eft5xequtHqRWPQjv95CdNMVIugqTsNLvfPOmxD5obK9HQHIz0Q\n" +
                    "jpElo8TAi5W+2kyhEACtcD4kogwIFM8JThBZYReBl/3b9qPKnA6m8ZRmEAUsgb5v\n" +
                    "VMazztZvAgMBAAECggEASyHDus2oxNPdMEoHha/Kr5FWfEYTX3peq2oErxrDYs/x\n" +
                    "+5lcFDGdaqJthHqfzZBxdf93fkueOgXULPnceHIJ4mevgmHCeIXUQaNA73soTgMd\n" +
                    "2M5Vdp/1GH0v1epSSrB/uyScfAV3qmMeIHi7sIvsWb9jY+SCq9miDGyY7RYnAajF\n" +
                    "J+7pgr+8bwLrV8KV8vXCNZD6zwH6NCUYcpsDCul2uE7n99gEKxJu27DqkaCCjiWE\n" +
                    "6dkeYfAXhhq3dj2SRrQZ+3ufL3E4QVxrpxAMAx8r7MwxuVka+ADeYZriFdREDYrQ\n" +
                    "2eb46H+IYk/iokSC1enfmkMdAegbc43dQrDaoMJQAQKBgQDyse8RoZTYC/d/3dao\n" +
                    "Y6HuBvEVVLbncc4DOHVwZ3ZOtTWASmbIUkTX54KzdCCYEy5n8yMtjDtNX7Y6N0hz\n" +
                    "Rzpj9PgTTTulIeqiFgjGRo1FWvDyte2LFSZZ4I59uRDDChOwqufVUotiVUJL/FgL\n" +
                    "yljRy5Kb7i7pEW17aSDtL20qAQKBgQDYvFwuQnPJVNR3OPReWsoYX9liHbXv6gCg\n" +
                    "XuS0t25Vt4asDG5u3gJ1SBJSI3g0UPf0TF0YPHYfzlJGsKvB48Kp66aXm8zPNa0J\n" +
                    "L8+kH567xpoC/d68qdNy5hRZId/jvmPt54Y0tUy/BjdNmqlDwLbkyZDjTj9m7lNz\n" +
                    "sEqGjzmgbwKBgA/sdM8nVujGADs3hvoNb3Z6ph7MLCQLZ4T2k14Iq86GPThpqUzD\n" +
                    "eRjha8XyfKD9wTG41joK1WlCOmafcfV+WupsDErX6m3vR8HSyEiaIHLIgL6sCSXz\n" +
                    "AU0sWq0NE3h4lMomrIdmnxaYmXz61ZwQbrt1K+1nN1S7e/946lwlnHgBAoGAY2Cq\n" +
                    "28M4mB4/dZM16XWzqM16PZTl8WXYd7BLKdnZy4/lPkpM8KT3d5NeYy9EVKizqN7C\n" +
                    "6PQALcFK1IL5nmOyxHr63hVgKbqw5r93dAfTnsIHqEuDr/omrE53Eg+IO0L3SwSX\n" +
                    "8t8Wm5hcD0dVSW257tnFh5Q/WhD5TtiMs3pEsB0CgYEA4cFqWFWXrxYmKo8oAIdt\n" +
                    "KknEQtO92IyRejZNrBwQjAK86ixxdUqybvNSLZdava3wpciwcg48yKlgOFBSOsfz\n" +
                    "vEFLJDozJj/Yeqoy/hhjqw6pHxf0n2YjlrBq+YWbJF2+U2FG6+01NA8i4v0ASWjz\n" +
                    "Vx5ffzP6TqAxECuyy+hDxDs=";
            String mainKeyHex="74657374616263646566313030303031";

            //公钥加密
            String hexStr = Base64Util.base64Decode(workCert);
            byte[] decode = Forms.hexStringToByte(hexStr);
            // //将内容转成流的方式
            ByteArrayInputStream bis = new ByteArrayInputStream(decode);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Certificate certificate = cf.generateCertificate(bis);
            //取出公钥--这里的公钥是pkcs8的那种结构型--待核实
            PublicKey publicKey = certificate.getPublicKey();
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            //用公钥初始化此Cipher对象(加密模式)
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            //对数据加密
            byte[] encrypt = cipher.doFinal(mainKeyHex.getBytes());
            //公钥加密然后转Base64
            String encMainKeyBase64 = Base64Util.base64Encode(encrypt);
            System.out.println("证书公钥加密转base64:" + encMainKeyBase64);

            //私钥解密
            String encMainKey = Base64Util.base64Decode(encMainKeyBase64);
            byte[] privateKeyData = Forms.hexStringToByte(Base64Util.base64Decode(workCertPrivateKey));
            //创建PKCS8编码密钥规范
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyData);
            //根据PKCS8编码密钥规范产生私钥对象
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            //用私钥初始化此Cipher对象(解密模式)
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            //对数据解密
            byte[] decrypt = cipher.doFinal(Forms.hexStringToByte(encMainKey));
            System.out.println("证书公钥对应的私钥解密:" + new String(decrypt));



            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateKey);
            signature.update(HexUtil.decodeHex(mainKeyHex));
            byte[] signData = signature.sign();
            System.out.println(String.format("签名校验 --- genRsaSign RSAWithSHA256 签名: [%s]", Forms.byteToHexString(signData)));
            String signBase64 = Base64Util.base64Encode(signData);
            System.out.println(String.format("签名校验 --- genRsaSign RSAWithSHA256 签名 Base64: [%s]", signBase64));


            signature.initVerify(publicKey);
            String signBase64Decode = Base64Util.base64Decode(signBase64);
            System.out.println(String.format("签名校验 --- genRsaSign RSAWithSHA256 验签 signBase64Decode: [%s]", signBase64Decode));
            //update原待签名数据
            signature.update(HexUtil.decodeHex(mainKeyHex));
            //verify原签名后数据
            boolean result = signature.verify(Forms.hexStringToByte(signBase64Decode));
            System.out.println(String.format("签名校验 --- genRsaSign RSAWithSHA256 验签: [%s]", result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

你可能感兴趣的:(工具,https,安全,ssl)