x509证书、openssl、go生成证书

x509证书

1. 概述

X.509标准是密码学里公钥证书的格式标准。X.509 证书己应用在包括TLS/SSL(WWW万维网安全浏览的基石)在内的众多 Internet协议里,同时它也有很多非在线的应用场景,比如电子签名服务。X.509证书含有公钥和标识(主机名、组织或个人),并由证书颁发机构(CA)签名(或自签名)。对于一份经由可信的证书签发机构签名(或者可以通过其它方式验证)的证书,证书的拥有者就可以用证书及相应的私钥来创建安全的通信,以及对文档进行数字签名。

2. x509证书结构

X.509证书的结构是用ASN.1(Abstract Syntax Notation One:抽象语法标记)来描述其数据结构,并使用ASN1语法进行编码。

X.509 v3数字证书的结构如下:

  • Certificate 证书内容

  • Version 证书版本号,版本(version)为整数格式。证书格式的版本只有v1、v2、v3,分别用整数0、1、2表示

  • Serial Number 证书序列号,RFC 3280标准要求证书序列号必须是正整数,且长度不应该大于20字节

  • Signature Algorithm CA签发证书时所使用的数字签名算法

  • Issuer 签发证书的CA实体

  • Validity 证书有效期

  • Not Before 证书起始日期

  • Not After 证书截至日期

  • Subject 证书持有者实体

  • Subject Pbulic Key Info 证书持有者公钥信息

  • Public Key Algorithm 证书持有者公钥算法

  • Public-Key 证书持有者公钥信息

  • Issuer Unique Identifier (optional)颁发者唯一标识符(可选)

  • Subject Unique Identifier (optional)主题唯一标识符(可选)

  • X509v3 extensions (optional) 证书的扩展项(可选)

  • Sigature Algorithm CA签发证书时所使用的数字签名算法

  • Signature 证书的签名

    openssl x509 -in secp256k1cert.pem -noout -text
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                3a:15:11:3c:1a:74:77:6d:ff:5f:b6:8f:28:e7:83:73
        Signature Algorithm: ecdsa-with-SHA256
            Issuer: C=CN, ST=BJ, L=BJ, O=youngz, OU=youngz, CN=hello.world.com
            Validity
                Not Before: Mar 19 12:26:16 2022 GMT
                Not After : Mar 19 12:26:00 2023 GMT
            Subject: C=CN, ST=BJ, L=BJ, O=youngz, OU=youngz, CN=hello.world.com
            Subject Public Key Info:
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (256 bit)
                    pub: 
                        04:73:c5:fc:f3:f1:c6:3f:33:bf:d7:f1:c9:e1:f1:
                        7e:c7:da:4a:80:9b:94:db:44:70:24:8b:b9:1d:ff:
                        99:ad:81:0f:b7:a7:76:85:21:68:a3:8c:df:87:9f:
                        58:11:a1:54:a6:91:75:2e:97:85:5b:7e:f6:2b:34:
                        36:34:c1:65:5f
                    ASN1 OID: secp256k1
            X509v3 extensions:
                X509v3 Key Usage: critical
                    Digital Signature, Certificate Sign
                X509v3 Extended Key Usage: 
                    TLS Web Client Authentication, TLS Web Server Authentication
                X509v3 Basic Constraints: critical
                    CA:TRUE
                X509v3 Subject Key Identifier: 
                    30:EF:CB:66:8C:8C:B8:2E:DE:81:4C:D3:35:22:EA:E5:55:45:D5:C4
                X509v3 Subject Alternative Name: 
                    DNS:hello.world, IP Address:127.0.0.1
        Signature Algorithm: ecdsa-with-SHA256
             30:45:02:20:05:30:ab:42:40:0a:fb:d4:04:8b:10:22:31:c3:
             94:24:9f:03:68:c2:96:a2:7e:f8:c6:86:ff:5d:f0:6d:fa:c6:
             02:21:00:8e:53:c3:c6:90:bc:76:68:a4:d9:f8:71:a5:cf:3f:
             b0:95:b4:20:a6:ca:88:26:88:4b:6b:0d:8d:b4:6f:5a:d8
    

2.1 证书扩展字段(X509v3 extensions)

2.1.1 Key Usage

  • Digital Signature 用于验证数字签名(除了签发证书,签发CRL和非否认性服务)。
  • Content Commitment 表示私钥可以用来进行非否认性服务中的签名
  • Key Encipherment 密钥用来加密传输其他密钥
  • Data Encipherment 公钥用来直接加密数据
  • Key Agreement 用于密钥协商时
  • Cert Sign 用于验证公钥证书上的签名
  • CRL Sign 用于验证证书撤销列表(例如CRL、增量CRL或ARL)上的签名时
  • Encipher Only 在没有密钥协商位的情况下,仅加密位的含义未定义。当仅加密位被断言并且密钥协商位也被设置时,主体公钥可仅用于在执行密钥协商时对数据进行加密。
  • Decipher Only 在没有密钥协商位的情况下,仅解密位的含义未定义。当仅解密位被断言并且密钥协商位也被设置时,主体公钥可仅用于在执行密钥协商时解密数据。

总结: 如果存在keyUsage扩展,则除非设置了相应的keyCertSign或cRLSign位,否则不得使用subject公钥验证证书或CRL上的签名。如果subject公钥仅用于验证证书和/或CRL上的签名,则不应设置数字签名和非否认位。然而,如果主体公钥将用于验证证书和/或CRL以及其他对象上的签名,则可以在keyCertSign和/或cRLSign位之外设置数字签名和/或非否认位。

2.1.2 Extended Key Usage

  • ServerAuth
  • ClientAuth
  • CodeSigning
  • EmailProtection
  • IPSECEndSystem
  • IPSECTunnel
  • IPSECUser
  • TimeStamping
  • OCSPSigning
  • MicrosoftServerGatedCrypto
  • NetscapeServerGatedCrypto

2.1.3 Basic Constraints

  • 基本限制扩展用来区分该证书是CA证书还是末端实体证书
  • CA证书给出最大路径深度,为关键性扩展
  • 末端实体证书,关键或非关键扩展

2.1.4 Subject Key Identifier

主体密钥标识:用户会进行不同安全要求的业务,需要多个密钥/证书来对应不同的应用。主体密钥标识的作用:区分用户的各个密钥/证书对,也就是区分各个公钥

2.1.5 Subject Alternative Name

以上扩展用于表示CA/证书主体非X.500 DN形式的身份信息和名称(如IP地址,电子邮件,域名)

3. 证书分类

证书根据用途分类,可以分为三类:根证书,中间证书,实体证书。根证书->中间证书->实体证书,构成了一条证书链。根证书是证书链的起点,实体证书是证书链的重点(也叫末端证书)

3.1 根证书

根证书:所谓根证书就是ca机构自签证书,证书机构用这个自签证书去给其他人签发中间证书

3.2 中间证书

中间证书:中间证书是由可信的ca机构(根证书)签发的子证书,受ca机构的信任。同时中间证书也可以作为新的机构的根证书,去签发下一级的中间证书,或者签发自己的实体证书

3.3 实体证书

实体证书:实体证书是由中间证书签发的子证书(基本由中间证书签发,也可以由根证书签发<不建议用根证书签发实体证书,减少根证书的对外的暴露>)

4. 证书的输出格式

.der 用于二进制DER编码证书

.pem用于不同类型的X.509v3文件,是以"- BEGIN …"前缀的ASCII(Base64)数据,不止用于证书,还可用于单独的私钥文件

-----BEGIN CERTIFICATE-----
MIICQDCCAeegAwIBAgIRAMz//txip7OCd/RPFj70j/QwCgYIKoZIzj0EAwIwYzEL
MAkGA1UEBhMCQ04xCzAJBgNVBAgTAkJKMQswCQYDVQQHEwJCSjEPMA0GA1UEChMG
eW91bmd6MQ8wDQYDVQQLEwZ5b3VuZ3oxGDAWBgNVBAMTD2hlbGxvLndvcmxkLmNv
bTAeFw0yMjAzMjAwNzQ5NDNaFw0yMzAzMjAwNzUwMDBaMGMxCzAJBgNVBAYTAkNO
MQswCQYDVQQIEwJCSjELMAkGA1UEBxMCQkoxDzANBgNVBAoTBnlvdW5nejEPMA0G
A1UECxMGeW91bmd6MRgwFgYDVQQDEw9oZWxsby53b3JsZC5jb20wVjAQBgcqhkjO
PQIBBgUrgQQACgNCAAREETkIgjrHWdyxaHWpuNl6o9jrel+isQsS1Z6hWDP32V5y
UNuXDykKIN+wnsZBpCMEYMHb2QHV0jpemJqQp0pFo38wfTAOBgNVHQ8BAf8EBAMC
AoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMB
Af8wHQYDVR0OBBYEFMot6y8NPSPzvphQlCVbTpGWtoQLMBwGA1UdEQQVMBOCC2hl
bGxvLndvcmxkhwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIC+cRTpDwt4f5wyLD+R+
BuZFR7HIveiA5LJwkE2Ua77LAiBDvv0t+lC7TER4ixprWJqyef2upuO8j/pCzJIZ
mqmwuA==
-----END CERTIFICATE-----

.crt用于证书,可以采用二进制DER或ASCII PEM编码,Unix 或类Unix系统中常见,CER和CRT扩展几乎是同义词

.cercrt的替代形式,macrosoft的转换形式

.key用于公钥和私钥PKCS#8,可以被编码为二进制DER或ASCII PEM

-----BEGIN EC PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgOpA43TnovcOtCeiLBPqn
VNgfO4Hi/Ept9v0TxuBSgb6hRANCAARFrCbbwVIRn6ottQLNxjTFJhQYCybnzn0j
RAsl10eez0S2GlSLQ87yzRLycQE/I9yjk1h62t7IZ6FQ1elP5saE
-----END EC PRIVATE KEY-----

.p7b, .p7cPKCS#7 SignedData structure without data, just certificate(s) or CRL(s)

.p12PKCS#12格式,包含证书的同时可能还有带密码保护的私钥
.pfx – PFX,PKCS#12 之前的格式(通常用 PKCS#12 格式,比如那些由IIS产生的 PFX 文件)

5. 证书吊销

在证书有效期中间,该证书可能无效,如:私钥丢失身份信息发生变化。应该阻止订户停止使用该证书,CA要撤销该证书。Certificate Revocation List证书撤销列表也要CA进行数字签名,以实现数据完整性、数据源鉴别、非否认。

证书吊销列表 (CRL,见RFC5280) 提供已吊销的证书的列表。客户端应用程序(如 Web 浏览器)可以使用 CRL 检查服务器的真实性。服务器应用程序(如Apache或OpenV.P.N)可以使用 CRL 拒绝访问不再受信任的客户端。在公共可访问的位置(例如http://example.com/intermediate.crl.pem)发布 CRL,第三方可以从此位置获取 CRL,以检查他们依赖的证书是否已被吊销。由于CRL的更新是有周期的,所以在证书已经被撤销,但是CRL还没有更新的情况下就无法查询到最新状态,此时应该使用ocsp来进行实时的查询。

6. OpenSSL使用

6.1 生成公私钥

6.1.1生成rsa公私钥

# 1. 生成私钥
openssl genrsa -out rsaprivatekey.pem 512
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAJbxkv3G8IEluvPwUtuVbRm9dn88DW2jbc1IP0lHZUXc9t0romf0
wyyMmrnm9GcmjIZKtlsYwnqUQ0q84xXH/2UCAwEAAQJAF6WSzJUM+n6JskuU/3eC
VwT6emZTCDkRK5bE61r2/6GnpV8U616VVcG/p8PWQG7Nc54yZ2hpTkbB+GiD8d9Y
BQIhAMfWDqkukbwxxJs4LeTIsg56DDf2eJBi3Itw8MErBQZfAiEAwV3EOar/68SS
dDYPYgt9vvDzKrLZYIcsFIb6hr3SqLsCIBd8KqDrXik12Bs90PbwNyzIXyM8jhK5
651fmou5GJAVAiEAhCD8aqNsSMCDiqE+FbLgc87VekHHw+vZtRUer1+aSO0CIEk9
+USV3jvtPIPVg+N+ZwCDG/hsm5kYtQt9COQP1uCe
-----END RSA PRIVATE KEY-----

# 2. 生成公钥(从私钥中提取公钥)
openssl rsa -pubout -in rsaprivatekey.pem  -out rsapublickey.pem
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJbxkv3G8IEluvPwUtuVbRm9dn88DW2j
bc1IP0lHZUXc9t0romf0wyyMmrnm9GcmjIZKtlsYwnqUQ0q84xXH/2UCAwEAAQ==
-----END PUBLIC KEY-----

# 3. 生成带口令的私钥
openssl genrsa -out rsaprivatekey.pem -passout pass:123456 -des3 512
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,9A5FDC2856B53E72

elBPfcBzR6haOU9rm38edA1eleEEMKVCpcRBwUaZf/sOV/Bfg78U7f0tL235BVtS
zYQOZq+bPXjL7qkC6iE+Z+nuM5fEjL3WzbqfnDaUYqtr6FC6YGX/wG38ky8tSFev
D29KiRqaldnk5yrAp0gBoWvZfm78zC8CGLh65meSjbZ3vVZFXiN8qM7jVNS730sS
gACB5nXZE22l7WFPZkuOT0Q3/2KkibIbZ00TcZIC2dfZrDdU5CIlvMYWg7YRSyZX
R4TDVF4tCKxdYpQt6/iv9zlTMXIJSIfIrTDkpQRdxSq48q5/NeqohuLdDSHBdpcW
RfRmUld8ztpzeNyMubuJMx7W+EofYiSALIWYF73gnAvGlKJRs5sPNXsBT1HAxT37
A0rIE5/PpEQ5+Rr4Ym9S4aenAOp+ZLa+k2iXrBd0V1jwYneTa/+Raw==
-----END RSA PRIVATE KEY-----

# 4. 从带口令的私钥中提取公钥
openssl rsa -in rsaprivatekey.pem -passin pass:123456 -pubout -out rsapublickey.pem
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMBUYc9XgABebGvp2CdrMIXw1uFHJ9eG
1nwrtFZ066tAxybj6uyizLB5pQQ03awvW7DFzZEiX2KNPQda7b1pTucCAwEAAQ==
-----END PUBLIC KEY-----

# 5. 查看带口令的私钥
openssl rsa -in rsaprivatekey.pem -noout -text -passin pass:123456

6.1.2生成ecc公私钥

# 1. 生成secp256k1私钥
openssl ecparam -genkey -name secp256k1 -out secp256k1pk.key
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIFTX9EtiHqskcT6G3Uv2Fts9DhUuN0suWkaLIPYXWa+HoAcGBSuBBAAK
oUQDQgAEZWBanwDMoEhCdBY17yeBqw+Kiw7WXllmh+x74w2+oYV9adQxVXsDi4FN
gQ3c8DwAR/VMakcKp6kuOTEjnpAfmg==
-----END EC PRIVATE KEY-----

# 2. 转成pkcs8格式
openssl pkcs8 -topk8 -in secp256k1pk.key -out secp256k1pk.p8 -nocrypt
-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgVNf0S2IeqyRxPobdS/YW
2z0OFS43Sy5aRosg9hdZr4ehRANCAARlYFqfAMygSEJ0FjXvJ4GrD4qLDtZeWWaH
7HvjDb6hhX1p1DFVewOLgU2BDdzwPABH9UxqRwqnqS45MSOekB+a
-----END PRIVATE KEY-----

# 3. 从私钥里提取公钥
openssl ec -in secp256k1pk.key -pubout -out secp256k1pub.key
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEZWBanwDMoEhCdBY17yeBqw+Kiw7WXllm
h+x74w2+oYV9adQxVXsDi4FNgQ3c8DwAR/VMakcKp6kuOTEjnpAfmg==
-----END PUBLIC KEY-----

# 4. 将公钥转成16进制
 xxd -c 10000000 -ps ./secp256k1pub.key

6.2 生成证书

以下证书算法都是使用secp256k1算法

# 1. 生成根证书私钥
openssl ecparam -genkey -name secp256k1 -out root.key
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIPC62IBJyL6gsrUGBReZKZyCsj/qtybxvXtjMw89S32aoAcGBSuBBAAK
oUQDQgAEs0Q1vsaw2BjdB6xjiXDG5vodM2M5vk3j2cCA0slIFzVqnbGMEintj9ls
s2mieMuZdssHlJ+T0YHXJWEdKJu9ZQ==
-----END EC PRIVATE KEY-----

# 2. 生成自签名根证书
openssl req -new -x509 -days 365 -key root.key -out root.crt
-----BEGIN CERTIFICATE-----
MIICHTCCAcKgAwIBAgIUcs/MwDHYIK0dAdQQ+PB7YlQ/BPkwCgYIKoZIzj0EAwIw
ZTELMAkGA1UEBhMCQkoxCzAJBgNVBAgMAkJqMQswCQYDVQQHDAJCSjEQMA4GA1UE
CgwHY29tcGFueTEQMA4GA1UECwwHc2VjdGlvbjEYMBYGA1UEAwwPaGVsbG8ud29y
bGQuY29tMB4XDTIyMDMyMDE1NDEwN1oXDTIzMDMyMDE1NDEwN1owZTELMAkGA1UE
BhMCQkoxCzAJBgNVBAgMAkJqMQswCQYDVQQHDAJCSjEQMA4GA1UECgwHY29tcGFu
eTEQMA4GA1UECwwHc2VjdGlvbjEYMBYGA1UEAwwPaGVsbG8ud29ybGQuY29tMFYw
EAYHKoZIzj0CAQYFK4EEAAoDQgAEs0Q1vsaw2BjdB6xjiXDG5vodM2M5vk3j2cCA
0slIFzVqnbGMEintj9lss2mieMuZdssHlJ+T0YHXJWEdKJu9ZaNTMFEwHQYDVR0O
BBYEFF4SScwUWfDNqviiolTtOfZ3LFKPMB8GA1UdIwQYMBaAFF4SScwUWfDNqvii
olTtOfZ3LFKPMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAM7x
MNgybzW2lI7aa7vpAiXGRs25UX9TtyTM/3+8Th8IAiEA9KBKeWF2SyW+MUbIjM7s
BGk7Sdu2Wog3AIVwsKm3FSY=
-----END CERTIFICATE-----

# 3. 生成子证书私钥
openssl ecparam -genkey -name secp256k1 -out child.key
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIJPXq0OVpGea8hSioBcNW1J5+8r4uP0d+/lb+dfuiObWoAcGBSuBBAAK
oUQDQgAEB+Q6FrDNZgTCCDFkZz4O+tIjVqBo+lhRJdiTiw3C7DD8sDJVbu/3ml1f
bVdnUXtIrRDVsHYdAzV7nd2fR7trTQ==
-----END EC PRIVATE KEY-----

# 4. 生成子证书请求文件
openssl req -new -key child.key -out child.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIBHTCBxQIBADBmMQswCQYDVQQGEwJCSjELMAkGA1UECAwCQkoxCzAJBgNVBAcM
AkJKMREwDwYDVQQKDAhjb21wYW55MTERMA8GA1UECwwIc2VjdGlvbjExFzAVBgNV
BAMMDmhlbGxvLndvcmxkLmNuMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEB+Q6FrDN
ZgTCCDFkZz4O+tIjVqBo+lhRJdiTiw3C7DD8sDJVbu/3ml1fbVdnUXtIrRDVsHYd
AzV7nd2fR7trTaAAMAoGCCqGSM49BAMCA0cAMEQCIFYoDrwqS4qtiMsh0QsoGdDL
953i2y4Oz+lsSGlli4ucAiBz5pLD/IpTMfkA+pB1Fi/Z6xHiqJSFJ9jKa1ZwAwfi
tw==
-----END CERTIFICATE REQUEST-----

# 5. 使用根证书签发子证书
openssl x509 -req -in child.csr -out child.crt -CA root.crt -CAkey root.key -CAcreateserial
-----BEGIN CERTIFICATE-----
MIIBwzCCAWkCFBV2qyP5KfhOQ32q8PwUjGME46wWMAoGCCqGSM49BAMCMGUxCzAJ
BgNVBAYTAkJKMQswCQYDVQQIDAJCajELMAkGA1UEBwwCQkoxEDAOBgNVBAoMB2Nv
bXBhbnkxEDAOBgNVBAsMB3NlY3Rpb24xGDAWBgNVBAMMD2hlbGxvLndvcmxkLmNv
bTAeFw0yMjAzMjAxNTUxNDRaFw0yMjA0MTkxNTUxNDRaMGYxCzAJBgNVBAYTAkJK
MQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxETAPBgNVBAoMCGNvbXBhbnkxMREw
DwYDVQQLDAhzZWN0aW9uMTEXMBUGA1UEAwwOaGVsbG8ud29ybGQuY24wVjAQBgcq
hkjOPQIBBgUrgQQACgNCAAQH5DoWsM1mBMIIMWRnPg760iNWoGj6WFEl2JOLDcLs
MPywMlVu7/eaXV9tV2dRe0itENWwdh0DNXud3Z9Hu2tNMAoGCCqGSM49BAMCA0gA
MEUCIA8LypbB/axp3QsZFJKd+nw+jILR5WSj8PvJ7T5m2aMEAiEA8Xj5eMBBgO7E
wptXl+3ontoG76+WVFnyU7veQNVhObM=
-----END CERTIFICATE-----

# 6. 验证子证书是否是根证书签发的
openssl verify -verbose -CAfile root.crt child.crt
child.crt: OK

6.3 解析证书私钥

# 1. 查看证书
openssl x509 -in secp256k1cert.pem -noout -text          
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            f5:b0:70:c0:5e:43:cd:6d:6e:62:6b:b7:87:37:1a:df
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=CN, ST=BJ, L=BJ, O=youngz, OU=youngz, CN=hello.world.com
        Validity
            Not Before: Mar 20 09:29:04 2022 GMT
            Not After : Mar 20 09:29:00 2023 GMT
        Subject: C=CN, ST=BJ, L=BJ, O=youngz, OU=youngz, CN=hello.world.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub: 
                    04:45:ac:26:db:c1:52:11:9f:aa:2d:b5:02:cd:c6:
                    34:c5:26:14:18:0b:26:e7:ce:7d:23:44:0b:25:d7:
                    47:9e:cf:44:b6:1a:54:8b:43:ce:f2:cd:12:f2:71:
                    01:3f:23:dc:a3:93:58:7a:da:de:c8:67:a1:50:d5:
                    e9:4f:e6:c6:84
                ASN1 OID: secp256k1
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                F3:57:40:A5:E8:81:81:1E:25:27:99:BE:56:6A:86:12:2A:BB:87:91
            X509v3 Subject Alternative Name: 
                DNS:hello.world, IP Address:127.0.0.1
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:74:79:17:b3:4b:15:a7:b1:bc:bd:74:c0:22:40:
         97:5d:ef:9f:f3:2b:7f:29:38:68:cd:be:14:3d:eb:7b:e8:dd:
         02:20:4c:84:4e:51:da:ba:f7:cd:a3:79:0b:ee:47:cb:72:ae:
         39:1d:c2:08:a4:5a:50:16:9f:96:9a:fe:f9:e9:43:77
# 2. 查看私钥
openssl ec -in secp256k1key.pem -noout -text
read EC key
Private-Key: (256 bit)
priv:
    3a:90:38:dd:39:e8:bd:c3:ad:09:e8:8b:04:fa:a7:
    54:d8:1f:3b:81:e2:fc:4a:6d:f6:fd:13:c6:e0:52:
    81:be
pub: 
    04:45:ac:26:db:c1:52:11:9f:aa:2d:b5:02:cd:c6:
    34:c5:26:14:18:0b:26:e7:ce:7d:23:44:0b:25:d7:
    47:9e:cf:44:b6:1a:54:8b:43:ce:f2:cd:12:f2:71:
    01:3f:23:dc:a3:93:58:7a:da:de:c8:67:a1:50:d5:
    e9:4f:e6:c6:84
ASN1 OID: secp256k1

# 3. 查看证书请求文件
openssl req -in child.csr -noout -text
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = BJ, ST = BJ, L = BJ, O = company1, OU = section1, CN = hello.world.cn
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:07:e4:3a:16:b0:cd:66:04:c2:08:31:64:67:3e:
                    0e:fa:d2:23:56:a0:68:fa:58:51:25:d8:93:8b:0d:
                    c2:ec:30:fc:b0:32:55:6e:ef:f7:9a:5d:5f:6d:57:
                    67:51:7b:48:ad:10:d5:b0:76:1d:03:35:7b:9d:dd:
                    9f:47:bb:6b:4d
                ASN1 OID: secp256k1
        Attributes:
            a0:00
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:56:28:0e:bc:2a:4b:8a:ad:88:cb:21:d1:0b:28:
         19:d0:cb:f7:9d:e2:db:2e:0e:cf:e9:6c:48:69:65:8b:8b:9c:
         02:20:73:e6:92:c3:fc:8a:53:31:f9:00:fa:90:75:16:2f:d9:
         eb:11:e2:a8:94:85:27:d8:ca:6b:56:70:03:07:e2:b7

7. go生成证书

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"math/big"
	"os"
	"time"
)

func main() {
	// 生成公私钥对
	caPrivkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		panic(err)
	}

	// 生成证书模板文件
	template := newTemplate()

	// 生成自签证书(template=parent)
	rootCertDer, err := x509.CreateCertificate(rand.Reader, template, template, &caPrivkey.PublicKey, caPrivkey) //DER 格式
	if err != nil {
		panic(err)
	}

	// 将私钥编码为pkcs8格式
	caPrivBytes, err := x509.MarshalPKCS8PrivateKey(caPrivkey)
	if err != nil {
		panic(err)
	}

	// 将私钥转为pem格式
	rootKeyFile, err := os.Create("./root.key")
	if err != nil {
		panic(err)
	}
	if err = pem.Encode(rootKeyFile, &pem.Block{Type: "EC PRIVATE KEY", Bytes: caPrivBytes}); err != nil {
		panic(err)
	}
	rootKeyFile.Close()

	// 将证书转为pem格式
	rootCertFile, err := os.Create("./root.crt")
	if err != nil {
		panic(err)
	}
	if err = pem.Encode(rootCertFile, &pem.Block{Type: "CERTIFICATE", Bytes: rootCertDer}); err != nil {
		panic(err)
	}
	rootCertFile.Close()

}

func newTemplate() *x509.Certificate {
	max := new(big.Int).Lsh(big.NewInt(1), 128)   //把 1 左移 128 位,返回给 big.Int
	serialNumber, _ := rand.Int(rand.Reader, max) //返回在 [0, max) 区间均匀随机分布的一个随机值

	template := &x509.Certificate{
		SerialNumber: serialNumber, // SerialNumber 是 CA 颁布的唯一序列号,在此使用一个大随机数来代表它
		Subject: pkix.Name{ // 证书的主题信息
			Country:            []string{"CN"},         // 证书所属的国家
			Organization:       []string{"company"},    // 证书存放的公司名称
			OrganizationalUnit: []string{"department"}, // 证书所属的部门名称
			Province:           []string{"BeiJing"},    // 证书签发机构所在省
			CommonName:         "hello.world.com",      // 证书域名
			Locality:           []string{"BeiJing"},    // 证书签发机构所在市
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(10, 0, 0),
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, // 典型用法是指定叶子证书中的公钥的使用目的。它包括一系列的OID,每一个都指定一种用途。例如{id pkix 31}表示用于服务器端的TLS/SSL连接;{id pkix 34}表示密钥可以用于保护电子邮件。
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,                      // 指定了这份证书包含的公钥可以执行的密码操作,例如只能用于签名,但不能用来加密
		IsCA:                  true,                                                                       // 指示证书是不是ca证书
		BasicConstraintsValid: true,                                                                       // 指示证书是不是ca证书
	}

	return template
}

8. 参考文档

https://blog.csdn.net/weixin_43255133/article/details/84025214

https://blog.csdn.net/weixin_38451161/article/details/108180919

https://www.cnblogs.com/f-ck-need-u/p/6091105.html

http://www.rfc2cn.com/rfc5280.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值