X.509

编码格式

  1. PEM
  2. DER

PEM (Privacy Enhanced Mail)

最常见的编码格式,BASE64 ASCII 编码,首尾都包含纯文本

例如,证书请求文件

1
2
3
4
5
6
7
8
9
-----BEGIN CERTIFICATE REQUEST-----
MIIBJjCBzQIBADBrMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD
VQQHDAbljJfkuqwxDjAMBgNVBAoMBUpIX0NBMRIwEAYDVQQLDAlKSF9DbGllbnQx
FjAUBgNVBAMMDUpIX0NsaWVudF9SZXEwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNC
AARPUB7GFXr1Gj6FwkfTbsFXx6tDeY17YsVZBfUtvEPP9GMxgX9qpSi9uRdIYthx
syw++GDy5jXaUfr1hxdSWqcJoAAwCgYIKoEcz1UBg3UDSAAwRQIhAOlRvyHNVmD9
bNcuDByBmt97cTeAvbGDPgX7Fl97RqgNAiBMI321HHeTsOrR0ieP7yUB7tkNQCh7
lRYDDYygq2ATAg==
-----END CERTIFICATE REQUEST-----

PEM 文件可以包含一个或多个证书

  • FISCO BCOS 中的节点证书包含了服务器证书和节点本身的证书

通常,PEM 文件后缀包括 .pem.key.csr.crt

DER (Distinguished Encoding Rules)

二进制编码,不包含首尾文本,通常用于 Java ,文件后缀包括 .der.cer

注意:PEM 格式的文件和 DER 格式的文件可以相互转换

文件后缀及内容(字段)

PEM 格式的文件可以统一存储为后缀 .pem ,为了便于区分用途,假设根据文件内容设置不同的后缀

此外,假设使用国密证书

私钥文件

私钥文件(Private Key),后缀为 .key,用于签名

  1. SM2 椭圆曲线公钥密码算法 –> 生成公钥、私钥
  2. 将私钥以 PEM 格式存储 –> .key 文件

证书请求文件

全称 Certificate Signing Request,后缀为 .csr,用于向服务器申请证书

证书请求文件模板

  • 基于 Package x509
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type CertificateRequest struct {
Raw []byte // 完整的 ASN.1 DER 内容(证书,签名算法和签名)
RawTBSCertificateRequest []byte // 原始 ASN.1 DER 内容的证书部分
RawSubjectPublicKeyInfo []byte // DER 编码的主体公钥信息
RawSubject []byte // DER 编码的主体

Version int // 版本
Signature []byte // 签名
SignatureAlgorithm SignatureAlgorithm // 签名算法

PublicKeyAlgorithm PublicKeyAlgorithm // 公钥算法
PublicKey interface{} // 公钥

Subject pkix.Name // 主体名称

// Attributes is the dried husk of a bug and shouldn't be used.
// 提供关于证书持有者的额外信息
Attributes []pkix.AttributeTypeAndValueSET

Extensions []pkix.Extension // 原始的 X.509 扩展,序列化时被忽略
ExtraExtensions []pkix.Extension // 覆盖任何其它字段生成的扩展

// 主体的替用名称
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
// 改动,砍掉了 URI
}

证书文件

全称 Certificate,后缀为 .crt,用于身份认证

  • 版本
  • 序列号
  • 签名算法
  • 颁发者
  • 有效期
  • 主体
  • 主体公钥
  • 颁发者 ID(可选)
  • 主体 ID(可选)
  • 扩展(可选)
  • 签名

证书链即包含多个层级的证书

证书文件模板

  • 基于 Package x509
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
type Certificate struct {
Raw []byte // 完整的 ASN.1 DER 内容(证书,签名算法和签名)
RawTBSCertificate []byte // 原始 ASN.1 DER 内容的证书部分
RawSubjectPublicKeyInfo []byte // DER 编码的主体公钥信息
RawSubject []byte // DER 编码的主体
RawIssuer []byte // DER 编码的颁发者

Signature []byte // 签名
SignatureAlgorithm SignatureAlgorithm // 签名算法

PublicKeyAlgorithm PublicKeyAlgorithm // 公钥算法
PublicKey interface{} // 公钥

Version int // 版本
SerialNumber *big.Int // 序列号
Issuer pkix.Name // 颁发者
Subject pkix.Name // 主体
NotBefore, NotAfter time.Time // Validity bounds. // 有效期
KeyUsage KeyUsage // 用途(可选)

Extensions []pkix.Extension // 原始的X.509扩展,序列化时被忽略
ExtraExtensions []pkix.Extension // 覆盖任何其它字段生成的扩展

// UnhandledCriticalExtensions contains a list of extension IDs that
// were not (fully) processed when parsing. Verify will fail if this
// slice is non-empty, unless verification is delegated to an OS
// library which understands all the critical extensions.
//
// Users can access these extensions using Extensions and can remove
// elements from this slice if they believe that they have been
// handled.
UnhandledCriticalExtensions []asn1.ObjectIdentifier // 扩展

ExtKeyUsage []ExtKeyUsage // 密钥扩展用途的序列
UnknownExtKeyUsage []asn1.ObjectIdentifier // 遇到的本包不能识别的密钥扩展用途

// 改动,增加了字段 BasicConstraintsValid
BasicConstraintsValid bool // 基本的有效性约束,如果以下两个字段有值则为真
IsCA bool // 是否为 CA
MaxPathLen int //
// MaxPathLenZero indicates that BasicConstraintsValid==true and
// MaxPathLen==0 should be interpreted as an actual maximum path length
// of zero. Otherwise, that combination is interpreted as MaxPathLen
// not being set.
MaxPathLenZero bool //

SubjectKeyId []byte // 主体 ID
AuthorityKeyId []byte // 颁发者 ID

// RFC 5280, 4.2.2.1 (认证信息存储)
OCSPServer []string
IssuingCertificateURL []string

// 主体的替用名称
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
// 改动,砍掉了 URI

// 名称约束
PermittedDNSDomainsCritical bool // 如果为真,则名称约束被标记为关键的(critical)
PermittedDNSDomains []string
// 改动,只保留两项

// CRL 分发点(证书吊销列表)
CRLDistributionPoints []string
PolicyIdentifiers []asn1.ObjectIdentifier
}

国密改造细节

在 Package x509 的基础上进行改造

数字证书的每项都有对象标识 OID, SM2 数字证书与标准 X.509 证书的主要区别就是公钥算法、公钥参数、签名算法的标识不同

SignatureAlgorithm

1
2
3
SM2WithSM3
SM2WithSHA1
SM2WithSHA256

algoName

1
2
3
SM2WithSM3:       "SM2-SM3",
SM2WithSHA1: "SM2-SHA1",
SM2WithSHA256: "SM2-SHA256",

oidSignature

1
2
3
4
5
6
oidSignatureSM2WithSM3      = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 501}
oidSignatureSM2WithSHA1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 502}
oidSignatureSM2WithSHA256 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 503}

oidSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 1}
oidHashSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401}

signatureAlgorithmDetails

1
2
3
4
5
6
7
8
9
10
var signatureAlgorithmDetails = []struct {
algo SignatureAlgorithm
oid asn1.ObjectIdentifier
pubKeyAlgo PublicKeyAlgorithm
hash Hash
}

{SM2WithSM3, oidSignatureSM2WithSM3, ECDSA, SM3},
{SM2WithSHA1, oidSignatureSM2WithSHA1, ECDSA, SHA1},
{SM2WithSHA256, oidSignatureSM2WithSHA256, ECDSA, SHA256},

oidNamed

1
oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}

代码演示

  1. 自签证书
  • Root CA 使用自己的私钥对证书签名,生成自签证书
  1. 证书文件
  • CA 直接使用 Client 提供的公钥进行证书签发
  1. 证书请求文件 –> 证书文件
  • Client 向 CA 发送证书请求文件
  • CA 使用证书请求文件中的信息签发证书
  • CA 将证书文件返回给 Client

SSL/TLS

应用层协议

  • 以 TCP 连接为基础(传输层)

原理 - 三次握手

  1. SYN、SYN ACK、ACK

    • TCP 三次握手,建立 TCP 连接
  2. ClientHello

    • Client 发送 Hello
      • 协议版本(protocol version)
      • Client 随机数(用于后续的三次握手)
      • 支持的密码套件(cipher suites)
      • 支持的压缩算法(compression methods)
      • 支持的扩展(extensions)
      • 可选的 session id (恢复 resume)
  3. ServerHello、Certificate、ServerHelloDone

    • Server 发送 Hello
      • 选择的协议版本
      • Server 随机数
      • 选择的密码套件
      • 选择的压缩算法
      • 一系列扩展
      • session id
    • Server 发送证书
      • Server 主机名
      • Server 使用的公钥
      • 可信第三方签名(CA)
  4. ClientKeyExchange、ChangeCipherSpec、Finished

    • Client 验证证书,提供密钥交换的信息
    • Client 生成 pre Master Key(取决于密钥生成算法,通常是随机数,用于生成对称密钥)
    • Client 使用 Server 公钥加密 pre Master Key,并发送给 Server
  5. ChangeCipherSpec、Finished

    • Server 解密 pre Master Key,利用 MAC 验证消息完整性
    • 返回加密的 “Finished” 消息

Client 和 Server 使用相同的参数生成对称密钥,用于会话消息的加密,因此也称为会话密钥。

容易混淆的说法:将密钥称为加密密钥

国密算法要求双向认证

  • 在 3. 上多一步,Server 向 Client 要求证书
  • 在 4. 上多一步,Client 向 Server 提供自己的证书(证明身份)

代码演示

Server

  1. Root CA 证书
  2. Server 证书
  3. Server 私钥

Client

  1. Root CA 证书
  2. Client 证书
  3. Client 私钥

Server 与 Client 的逻辑基本一致

  • 读取自己的公钥证书和私钥
  • 载入证书(链)、根证书
    • 提供自己的证书
    • 验证对方的证书
  • 配置 TLS
    • 认证方式、证书(链)、根证书集合
  • 创建通道进行监听 / 发起连接请求

区块链身份认证方案

FISCO BCOS

FISCO BCOS网络采用面向CA的准入机制,支持任意多级的证书结构,保障信息保密性、认证性、完整性、不可抵赖性。

  1. 使用 openssl 命令
  2. 一般情况,三级结构
    • 链证书
    • 机构证书
    • 节点/SDK 证书

使用证书请求文件申请证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# CA
ca.crt # 链证书
ca.key # 链私钥

# Agency
ca.crt # 链证书
agency.crt # 机构证书
agency.csr # 机构证书请求文件
agency.key # 机构私钥

# Node
ca.crt # 链证书
node.crt # 节点证书 <-- 包括节点证书和机构证书信息
node.key # 节点私钥

# SDK
ca.crt # 链证书
sdk.crt # SDK 证书 <-- 包括节点证书和机构证书信息
sdk.key # SDK 私钥

Fabric

Fabric CA 在 Fabric 中的架构

Fabric CA 层级架构

CA 服务器

  • TLS CA
  • ORG CA
  • TCA(transaction)

使用用户名密码获得证书

  1. 注册 Register:获得凭据
  2. 登记 Enroll:返回私钥、公钥证书、CA 证书链

典型 PKI 架构

组成部分

  • 证书
  • 信任链
    • 根证书、中间证书、…
  • 证书颁发机构
    • Root CA:信任锚

总结

树形层级架构

1
2
3
4
5
6
7
8
9
10
Root CA                       # 信任锚
├─Intermediate CA1 # 为类型 A 的节点签发证书
| ├─ Client1-Cert
| ├─ Client2-Cert
| └─ ...
├─Intermediate CA2 # 为类型 B 的节点签发证书
| ├─ ClientA-Cert
| ├─ ClientB-Cert
| └─ ...
└─ ...

  1. FISCO BCOS 直接使用 openssl 进行签发,使用一个文件夹存储私钥、证书

    • 节点的黑名单机制,未提到撤销证书
      • 优先级:黑名单 > 白名单
    • 生成证书请求文件向服务器续期
  2. Fabric 结合数据库或 LDAP ,使用注册登记机制,通过 MSP 模块(成员服务提供者)管理私钥、证书

    • 向服务器进行证书撤销或续期

都是向服务器申请 CA 证书(链),以及签发证书。

参阅

关于国密 TLS

市面产品