1# 证书链校验器对象的创建和校验
2
3
4证书链是由一组证书组成的证书集合,以图中样例证书文件为例,即可放在一个证书链中。
5
6
7样例中可以看到GlobalSign自签名了证书,GlobalSign也签发了GlobalSign RSA OV SSL CA 2018的证书,GlobalSign RSA OV SSL CA 2018又签发了第三级证书。
8
9
10![zh-cn_image_0000001746997074](figures/zh-cn_image_0000001746997074.png)
11
12
13开发者可以参考示例将已有的多个证书构建出证书链数据。
14
15
16## 开发步骤
17
181. 导入[证书算法库框架模块](../../reference/apis-device-certificate-kit/js-apis-cert.md)。
19   ```ts
20   import { cert } from '@kit.DeviceCertificateKit';
21   ```
22
232. [cert.createCertChainValidator](../../reference/apis-device-certificate-kit/js-apis-cert.md#certcreatecertchainvalidator)创建证书链校验器对象。
24
253. 基于已有的证书数据,创建证书链数据对象[CertChainData](../../reference/apis-device-certificate-kit/js-apis-cert.md#certchaindata)。
26
27   证书算法库框架提供了证书链校验器对象可用于校验证书链,以验证信任链根源,但待校验的证书链数据对象应符合如下的数据结构定义。
28
29   | 名称 | 类型 | 可读 | 可写 | 说明 |
30   | -------- | -------- | -------- | -------- | -------- |
31   | data | Uint8Array | 是 | 是 | 证书数据,按照长度(2字节)-数据的形式传入。如08ABCDEFGH07ABCDEFG:第一本证书,前2个字节表示证书的长度为8字节,后面附加8字节的证书数据;第2本证书前2个字节表示证书的长度为7字节,后面附加7字节的证书数据。 |
32   | count | number | 是 | 是 | 传入的数据中,包含的证书数量。 |
33   | encodingFormat | [EncodingFormat](../../reference/apis-device-certificate-kit/js-apis-cert.md#encodingformat) | 是 | 是 | 指明证书编码格式。 |
34
354. 调用[CertChainValidator.validate](../../reference/apis-device-certificate-kit/js-apis-cert.md#validate)校验证书链数据。
36
37```ts
38import { cert } from '@kit.DeviceCertificateKit';
39import { util } from '@kit.ArkTS';
40
41// CA数据,这只是一个示例,需要根据具体业务来赋值
42let caCertData = '-----BEGIN CERTIFICATE-----\n' +
43  '...\n' +
44  '...\n' +
45  '...\n' +
46  '-----END CERTIFICATE-----\n';
47
48// 二级CA证书数据,这只是一个示例,需要根据具体业务来赋值
49let secondCaCertData = '-----BEGIN CERTIFICATE-----\n' +
50  '...\n' +
51  '...\n' +
52  '...\n' +
53  '-----END CERTIFICATE-----\n';
54
55// 证书链校验器示例。在这个示例中,验证了一个二级证书链
56function certChainValidatorSample(): void {
57  let textEncoder = new util.TextEncoder();
58  // 证书链校验器算法。目前仅支持PKIX
59  let algorithm = 'PKIX';
60
61  // 创建一个证书链校验器实例
62  let validator = cert.createCertChainValidator(algorithm);
63
64  // CA证书数据
65  let uint8ArrayOfCaCertData = textEncoder.encodeInto(caCertData);
66
67  // CA证书数据的长度
68  let uint8ArrayOfCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOfCaCertData.byteLength]).buffer);
69
70  // 二级CA证书数据
71  let uint8ArrayOf2ndCaCertData =  textEncoder.encodeInto(secondCaCertData);
72
73  // 二级CA证书数据的长度
74  let uint8ArrayOf2ndCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOf2ndCaCertData.byteLength]).buffer);
75
76  // 证书链二进制数据:二级CA证书数据长度+二级CA证书数据+CA证书数据长度+CA证书数据(L-V格式)
77  let encodingData = new Uint8Array(uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length +
78  uint8ArrayOfCaCertDataLen.length + uint8ArrayOfCaCertData.length);
79  for (let i = 0; i < uint8ArrayOf2ndCaCertDataLen.length; i++) {
80    encodingData[i] = uint8ArrayOf2ndCaCertDataLen[i];
81  }
82  for (let i = 0; i < uint8ArrayOf2ndCaCertData.length; i++) {
83    encodingData[uint8ArrayOf2ndCaCertDataLen.length + i] = uint8ArrayOf2ndCaCertData[i];
84  }
85  for (let i = 0; i < uint8ArrayOfCaCertDataLen.length; i++) {
86    encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + i] = uint8ArrayOfCaCertDataLen[i];
87  }
88  for (let i = 0; i < uint8ArrayOfCaCertData.length; i++) {
89    encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length +
90    uint8ArrayOfCaCertDataLen.length + i] = uint8ArrayOfCaCertData[i];
91  }
92
93  let certChainData: cert.CertChainData = {
94    // Uint8Array类型:L-V格式(证书数据长度-证书数据)
95    data: encodingData,
96    // 证书的数量。本例中为2
97    count: 2,
98    // 证书格式。仅支持 PEM 和 DER。在此示例中,证书为 PEM 格式
99    encodingFormat: cert.EncodingFormat.FORMAT_PEM
100  };
101
102  // 验证证书链
103  validator.validate(certChainData, (err, data) => {
104    if (err != null) {
105      // 校验失败
106      console.error(`validate failed, errCode: ${err.code}, errMsg: ${err.message}`);
107    } else {
108      // 校验成功
109      console.log('validate success');
110    }
111  });
112}
113```
114