1# 证书开发指导 2 3> **说明** 4> 5> 本开发指导基于API version 9,OH SDK版本3.2.9及以上,适用于JS语言开发 6 7## 使用证书操作 8 9**场景说明** 10 11使用证书操作中,典型的场景有: 12 131. 解析X509证书数据生成证书对象。 142. 获取证书信息,比如:证书版本、证书序列号等。 153. 获取证书对象的序列化数据。 164. 获取证书公钥。 175. 证书验签。 186. 校验证书有效期。 19 20**接口及参数说明** 21 22详细接口说明可参考[API参考](../reference/apis/js-apis-cert.md)。 23 24以上场景涉及的常用接口如下表所示: 25 26| 实例名 | 接口名 | 描述 | 27| --------------- | ------------------------------------------------------------ | -------------------------------------------- | 28| cryptoCert | createX509Cert(inStream : EncodingBlob, callback : AsyncCallback\<X509Cert>) : void | 使用callback方式解析X509证书数据生成证书对象 | 29| cryptoCert | createX509Cert(inStream : EncodingBlob) : Promise\<X509Cert> | 使用promise方式解析X509证书数据生成证书对象 | 30| X509Cert | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\<void>) : void | 使用callback方式进行证书验签 | 31| X509Cert | verify(key : cryptoFramework.PubKey) : Promise\<void> | 使用promise方式进行证书验签 | 32| X509Cert | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void | 使用callback方式获取证书序列化数据 | 33| X509Cert | getEncoded() : Promise\<EncodingBlob> | 使用promise方式获取证书序列化数据 | 34| X509Cert | getPublicKey() : cryptoFramework.PubKey | 获取证书公钥 | 35| X509Cert | checkValidityWithDate(date: string) : void | 校验证书有效期 | 36| X509Cert | getVersion() : number | 获取证书版本 | 37| X509Cert | getSerialNumber() : number | 获取证书序列号 | 38| X509Cert | getIssuerName() : DataBlob | 获取证书颁发者名称 | 39| X509Cert | getSubjectName() : DataBlob | 获取证书主体名称 | 40| X509Cert | getNotBeforeTime() : string | 获取证书有效期起始时间 | 41| X509Cert | getNotAfterTime() : string | 获取证书有效期截至时间 | 42| X509Cert | getSignature() : DataBlob | 获取证书签名 | 43| X509Cert | getSignatureAlgName() : string | 获取证书签名算法名称 | 44| X509Cert | getSignatureAlgOid() : string | 获取证书签名算法OID | 45| X509Cert | getSignatureAlgParams() : DataBlob | 获取证书签名算法参数 | 46| X509Cert | getKeyUsage() : DataBlob | 获取证书秘钥用途 | 47| X509Cert | getExtKeyUsage() : DataArray | 获取证书扩展秘钥用途 | 48| X509Cert | getBasicConstraints() : number | 获取证书基本约束 | 49| X509Cert | getSubjectAltNames() : DataArray | 获取证书主体可选名称 | 50| X509Cert | getIssuerAltNames() : DataArray | 获取证书颁发者可选名称 | 51 52**开发步骤** 53 54示例:解析X509证书数据生成证书对象,并调用对象方法(包含场景1-6) 55 56```javascript 57import cryptoCert from '@ohos.security.cert'; 58import cryptoFramework from '@ohos.security.cryptoFramework'; 59 60// 证书数据,此处仅示例,业务需根据场景自行设置 61let certData = "-----BEGIN CERTIFICATE-----\n" 62+ "IBzTCCAXCgAwIBAgIGAXKnMKNyMAwGCCqBHM9VAYN1BQAwSTELMAkGA1UEBhMC\n" 63+ "04xDjAMBgNVBAoTBUdNU1NMMRAwDgYDVQQLEwdQS0kvU00yMRgwFgYDVQQDEw9S\n" 64+ "290Q0EgZm9yIFRlc3QwIhgPMjAxNTEyMzExNjAwMDBaGA8yMDM1MTIzMDE2MDAw\n" 65+ "FowSTELMAkGA1UEBhMCQ04xDjAMBgNVBAoTBUdNU1NMMRAwDgYDVQQLEwdQS0kv\n" 66+ "00yMRgwFgYDVQQDEw9Sb290Q0EgZm9yIFRlc3QwWTATBgcqhkjOPQIBBggqgRzP\n" 67+ "QGCLQNCAATj+apYlL+ddWXZ7+mFZXZJGbcJFXUN+Fszz6humeyWZP4qEEr2N0+a\n" 68+ "dwo/21ft232yo0jPLzdscKB261zSQXSoz4wPDAZBgNVHQ4EEgQQnGnsD7oaOcWv\n" 69+ "CTrspwSBDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIAxjAMBggqgRzP\n" 70+ "QGDdQUAA0kAMEYCIQCEnW5BlQh0vmsOLxSoXYc/7zs++wWyFc1tnBHENR4ElwIh\n" 71+ "I1Lwu6in1ruflZhzseWulXwcITf3bm/Y5X1g1XFWQUH\n" 72+ "-----END CERTIFICATE-----\n"; 73 74// string转Uint8Array 75function stringToUint8Array(str) { 76 var arr = []; 77 for (var i = 0, j = str.length; i < j; i++) { 78 arr.push(str.charCodeAt(i)); 79 } 80 return new Uint8Array(arr); 81} 82 83// 证书示例 84function certSample() { 85 let encodingBlob = { 86 // 将string类型证书数据转为Uint8Array 87 data: stringToUint8Array(certData), 88 // 证书格式:支持PEM和DER,此例中对应PEM 89 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 90 }; 91 92 // 创建证书对象 93 cryptoCert.createX509Cert(encodingBlob, function (err, x509Cert) { 94 if (err != null) { 95 // 创建证书对象失败 96 console.log("createX509Cert failed, errCode: " + err.code + ", errMsg: " + err.message); 97 return; 98 } 99 // 创建证书对象成功 100 console.log("createX509Cert success"); 101 102 // 获取证书版本 103 let version = x509Cert.getVersion(); 104 105 // 获取证书对象的序列化数据 106 x509Cert.getEncoded(function (err, data) { 107 if (err != null) { 108 // 获取序列化数据失败 109 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 110 } else { 111 // 获取序列化数据成功 112 console.log("getEncoded success"); 113 } 114 }); 115 116 // 业务需通过上级证书对象或本证书对象(自签名)的getPublicKey接口获取公钥对象,此处省略 117 let pubKey = null; 118 try { 119 pubKey = x509Cert.getPublicKey(); 120 } catch (error) { 121 console.log("getPublicKey failed, errCode: " + error.code + ", errMsg: " + error.message); 122 } 123 124 // 证书验签 125 x509Cert.verify(pubKey, function (err, data) { 126 if (err == null) { 127 // 验签成功 128 console.log("verify success"); 129 } else { 130 // 验签失败 131 console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); 132 } 133 }); 134 135 // 时间字符串 136 let date = "150527000001Z"; 137 138 // 校验证书有效期 139 try { 140 x509Cert.checkValidityWithDate(date); 141 } catch (error) { 142 console.log("checkValidityWithDate failed, errCode: " + error.code + ", errMsg: " + error.message); 143 } 144 }); 145} 146``` 147 148## 使用证书吊销列表操作 149 150**场景说明** 151 152使用证书吊销列表操作中,典型的场景有: 153 1541. 解析X509证书吊销列表数据生成吊销列表对象。 1552. 获取证书吊销列表信息,比如:证书吊销列表版本、证书吊销列表类型等。 1563. 获取证书吊销列表对象的序列化数据。 1574. 检查证书是否被吊销。 1585. 证书吊销列表验签。 1596. 获取被吊销证书。 160 161**接口及参数说明** 162 163详细接口说明可参考[API参考](../reference/apis/js-apis-cert.md)。 164 165以上场景涉及的常用接口如下表所示: 166 167| 实例名 | 接口名 | 描述 | 168| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 169| cryptoCert | createX509Crl(inStream : EncodingBlob, callback : AsyncCallback\<X509Crl>) : void | 使用callback方式解析X509证书吊销列表数据生成证书吊销列表对象 | 170| cryptoCert | createX509Crl(inStream : EncodingBlob) : Promise\<X509Crl> | 使用promise方式解析X509证书吊销列表数据生成证书吊销列表对象 | 171| X509Crl | isRevoked(cert : X509Cert) : boolean | 检查证书是否被吊销 | 172| X509Crl | getType() : string | 获取证书吊销列表类型 | 173| X509Crl | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void | 使用callback方式获取证书吊销列表序列化数据 | 174| X509Crl | getEncoded() : Promise\<EncodingBlob> | 使用promise方式获取证书吊销列表序列化数据 | 175| X509Crl | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\<void>) : void | 使用callback方式进行证书吊销列表验签 | 176| X509Crl | verify(key : cryptoFramework.PubKey) : Promise\<void> | 使用Promise方式进行证书吊销列表验签 | 177| X509Crl | getVersion() : number | 获取证书吊销列表版本 | 178| X509Crl | getIssuerName() : DataBlob | 获取证书吊销列表颁发者名称 | 179| X509Crl | getLastUpdate() : string | 获取证书吊销列表lastUpdate日期 | 180| X509Crl | getNextUpdate() : string | 获取证书吊销列表nextUpdate日期 | 181| X509Crl | getRevokedCert(serialNumber : number) : X509CrlEntry | 通过序列号获取证书吊销列表中的被吊销证书 | 182| X509Crl | getRevokedCertWithCert(cert : X509Cert) : X509CrlEntry | 通过X509证书获取证书吊销列表中的被吊销证书 | 183| X509Crl | getRevokedCerts(callback : AsyncCallback\<Array\<X509CrlEntry>>) : void | 使用callback方式获取证书吊销列表的所有被吊销证书 | 184| X509Crl | getRevokedCerts() : Promise\<Array\<X509CrlEntry>> | 使用Promise方式获取证书吊销列表的所有被吊销证书 | 185| X509Crl | getTbsInfo() : DataBlob | 获取证书吊销列表的tbsCertList | 186| X509Crl | getSignature() : DataBlob | 获取证书吊销列表的签名 | 187| X509Crl | getSignatureAlgName() : string | 获取证书吊销列表的签名算法名称 | 188| X509Crl | getSignatureAlgOid() : string | 获取证书吊销列表的签名算法OID | 189| X509Crl | getSignatureAlgParams() : DataBlob | 获取证书吊销列表的签名算法参数 | 190 191**开发步骤** 192 193示例:解析X509证书吊销列表数据生成证书吊销列表对象,并调用对象方法(包含场景1-6) 194 195```javascript 196import cryptoCert from '@ohos.security.cert'; 197import cryptoFramework from '@ohos.security.cryptoFramework'; 198 199// 证书吊销列表数据,此处仅示例,业务需根据场景自行设置 200let crlData = "-----BEGIN X509 CRL-----\n" 201+ "MIIBijB0AgEBMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHJvb3QtY2ExFw0y\n" 202+ "MDA2MTkxNjE1NDhaFw0yMDA3MTkxNjE1NDhaMBwwGgIJAMsozRATnap1Fw0yMDA2\n" 203+ "MTkxNjEyMDdaoA8wDTALBgNVHRQEBAICEAIwDQYJKoZIhvcNAQELBQADggEBACPs\n" 204+ "9gQB+djaXPHHRmAItebZpD3iJ/e36Dxr6aMVkn9FkI8OVpUI4RNcCrywyCZHQJte\n" 205+ "995bbPjP7f1sZstOTZS0fDPgJ5SPAxkKOQB+SQnBFrlZSsxoUNU60gRqd2imR0Rn\n" 206+ "1r09rP69F6E4yPc9biEld+llLGgoImP3zPOVDD6fbfcvVkjStY3bssVEQ/vjp4a3\n" 207+ "/I12U7ZnSe3jaKqaQBoVJppkTFOIOq7IOxf5/IkMPmvRHDeC2IzDMzcUxym0dkny\n" 208+ "EowHrjzo0bZVqpHMA2YgKZuwTpVLHk9GeBEK2hVkIoPVISkmiU4HFg0S6z68C5yd\n" 209+ "DrAA7hErVgXhtURLbAI=\n" 210+ "-----END X509 CRL-----\n"; 211 212// string转Uint8Array 213function stringToUint8Array(str) { 214 var arr = []; 215 for (var i = 0, j = str.length; i < j; i++) { 216 arr.push(str.charCodeAt(i)); 217 } 218 return new Uint8Array(arr); 219} 220 221// 证书吊销列表示例 222function crlSample() { 223 let encodingBlob = { 224 // 将string类型证书吊销列表数据转为Uint8Array 225 data: stringToUint8Array(crlData), 226 // 证书吊销列表格式:支持PEM和DER,此例中对应PEM 227 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 228 }; 229 230 // 创建证书吊销列表对象 231 cryptoCert.createX509Crl(encodingBlob, function (err, x509Crl) { 232 if (err != null) { 233 // 创建证书吊销列表对象失败 234 console.log("createX509Crl failed, errCode: " + err.code + ", errMsg: " + err.message); 235 return; 236 } 237 // 创建证书吊销列表对象成功 238 console.log("createX509Crl success"); 239 240 // 获取证书吊销列表版本 241 let version = x509Crl.getVersion(); 242 243 // 获取证书吊销列表对象的序列化数据 244 x509Crl.getEncoded(function (err, data) { 245 if (err != null) { 246 // 获取序列化数据失败 247 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 248 } else { 249 // 获取序列化数据成功 250 console.log("getEncoded success"); 251 } 252 }); 253 254 // 业务需通过cryptoFramework的createX509Cert生成X509Cert证书对象,此处省略 255 let x509Cert = null; 256 // 检查证书是否被吊销 257 try { 258 let revokedFlag = x509Crl.isRevoked(x509Cert); 259 } catch (error) { 260 console.log("isRevoked failed, errCode: " + error.code + ", errMsg: " + error.message); 261 } 262 263 // 业务需通过将public key二进制数据输入 @ohos.security.cryptoFramework的convertKey接口获取PubKey对象,此处省略 264 let pubKey = null; 265 266 // 证书吊销列表验签 267 x509Crl.verify(pubKey, function (err, data) { 268 if (err == null) { 269 // 验签成功 270 console.log("verify success"); 271 } else { 272 // 验签失败 273 console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); 274 } 275 }); 276 277 // 证书序列号,业务需自行设置 278 let serialNumber = 1000; 279 280 // 获取被吊销证书对象 281 try { 282 let entry = x509Crl.getRevokedCert(serialNumber); 283 } catch (error) { 284 console.log("getRevokedCert failed, errCode: " + error.code + ", errMsg: " + error.message); 285 } 286 }); 287} 288``` 289 290## 使用证书链校验器操作 291 292**场景说明** 293 294使用证书链校验器操作中,典型的场景:证书链校验。 295 296**接口及参数说明** 297 298详细接口说明可参考[API参考](../reference/apis/js-apis-cert.md)。 299 300以上场景涉及的常用接口如下表所示: 301 302| 实例名 | 接口名 | 描述 | 303| ------------------ | ------------------------------------------------------------ | -------------------------------- | 304| cryptoCert | createCertChainValidator(algorithm :string) : CertChainValidator | 使用指定算法生成证书链校验器对象 | 305| CertChainValidator | validate(certChain : CertChainData, callback : AsyncCallback\<void>) : void | 使用callback方式校验证书链 | 306| CertChainValidator | validate(certChain : CertChainData) : Promise\<void> | 使用promise方式校验证书链 | 307| CertChainValidator | algorithm : string | 证书链校验器算法名称 | 308 309**开发步骤** 310 311示例:创建证书链校验器对象,并对证书链数据进行校验(场景1) 312 313```javascript 314import cryptoCert from '@ohos.security.cert'; 315 316// 一级证书数据,此处仅示例,业务需自行设置真实数据 317let caCertData = "-----BEGIN CERTIFICATE-----\n" 318+ "...\n" 319+ "...\n" 320+ "...\n" 321+ "-----END CERTIFICATE-----\n"; 322 323// 二级证书数据,此处仅示例,业务需自行设置真实数据 324let secondCaCertData = "-----BEGIN CERTIFICATE-----\n" 325+ "...\n" 326+ "...\n" 327+ "...\n" 328+ "-----END CERTIFICATE-----\n"; 329 330// string转Uint8Array 331function stringToUint8Array(str) { 332 var arr = []; 333 for (var i = 0, j = str.length; i < j; i++) { 334 arr.push(str.charCodeAt(i)); 335 } 336 return new Uint8Array(arr); 337} 338 339// 证书链校验器示例:此示例中以校验二级证书链为例,业务需根据场景自行修改 340function certChainValidatorSample() { 341 // 证书链校验器算法,当前仅支持PKIX 342 let algorithm = "PKIX"; 343 344 // 创建证书链校验器对象 345 let validator = cryptoCert.createCertChainValidator(algorithm); 346 347 // 一级证书数据 348 let uint8ArrayOfCaCertData = stringToUint8Array(caCertData); 349 350 // 一级证书数据长度 351 let uint8ArrayOfCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOfCaCertData.byteLength]).buffer); 352 353 // 二级证书数据 354 let uint8ArrayOf2ndCaCertData = stringToUint8Array(secondCaCertData); 355 356 // 二级证书数据长度 357 let uint8ArrayOf2ndCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOf2ndCaCertData.byteLength]).buffer); 358 359 // 证书链二进制数据:二级证书数据长度+二级证书数据+一级证书数据长度+一级证书数据(L-V格式) 360 let encodingData = new Uint8Array(uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + 361 uint8ArrayOfCaCertDataLen.length + uint8ArrayOfCaCertData.length); 362 for (var i = 0; i < uint8ArrayOf2ndCaCertDataLen.length; i++) { 363 encodingData[i] = uint8ArrayOf2ndCaCertDataLen[i]; 364 } 365 for (var i = 0; i < uint8ArrayOf2ndCaCertData.length; i++) { 366 encodingData[uint8ArrayOf2ndCaCertDataLen.length + i] = uint8ArrayOf2ndCaCertData[i]; 367 } 368 for (var i = 0; i < uint8ArrayOfCaCertDataLen.length; i++) { 369 encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + i] = uint8ArrayOfCaCertDataLen[i]; 370 } 371 for (var i = 0; i < uint8ArrayOfCaCertData.length; i++) { 372 encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + 373 uint8ArrayOfCaCertDataLen.length + i] = uint8ArrayOfCaCertData[i]; 374 } 375 376 let certChainData = { 377 // Uint8Array类型:L-V格式(证书数据长度-证书数据) 378 data: encodingData, 379 // 证书数量,此示例中为2 380 count: 2, 381 // 证书格式:支持PEM和DER,此例中对应PEM 382 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 383 }; 384 385 // 校验证书链 386 validator.validate(certChainData, function (err, data) { 387 if (err != null) { 388 // 证书链校验失败 389 console.log("validate failed, errCode: " + err.code + ", errMsg: " + err.message); 390 } else { 391 // 证书链校验成功 392 console.log("validate success"); 393 } 394 }); 395} 396``` 397 398## 使用被吊销证书操作 399 400**场景说明** 401 402使用被吊销证书操作中,典型的场景有: 403 4041. 获取被吊销证书对象。 4052. 获取被吊销证书信息,比如:序列号、证书颁发者、证书吊销日期。 4063. 获取被吊销证书对象的序列化数据。 407 408**接口及参数说明** 409 410详细接口说明可参考[API参考](../reference/apis/js-apis-cert.md)。 411 412以上场景涉及的常用接口如下表所示: 413 414| 实例名 | 接口名 | 描述 | 415| ------------ | ----------------------------------------------------------- | ---------------------------------------- | 416| X509CrlEntry | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void; | 使用callback方式获取被吊销证书的序列化数据 | 417| X509CrlEntry | getEncoded() : Promise\<EncodingBlob>; | 使用promise方式获取被吊销证书的序列化数据 | 418| X509CrlEntry | getSerialNumber() : number; | 获取被吊销证书的序列号 | 419| X509CrlEntry | getCertIssuer() : DataBlob; | 获取被吊销证书颁发者 | 420| X509CrlEntry | getRevocationDate() : string; | 获取被吊销证书的吊销日期 | 421 422**开发步骤** 423 424示例:获取被吊销证书对象,并调用对象方法(包含场景1-3) 425 426```javascript 427import cryptoCert from '@ohos.security.cert'; 428 429// 被吊销证书示例 430function crlEntrySample() { 431 // 业务需自行通过cryptoFramework的createX509Crl接口创建X509Crl对象,此处省略 432 let x509Crl = null; 433 434 // 获取被吊销证书对象,业务需根据场景调用X509Crl的接口获取,此示例使用getRevokedCert获取 435 let serialNumber = 1000; 436 let crlEntry = null; 437 try { 438 crlEntry = x509Crl.getRevokedCert(serialNumber); 439 } catch (error) { 440 console.log("getRevokedCert failed, errCode: " + error.code + ", errMsg: " + error.message); 441 } 442 443 // 获取被吊销证书的序列号 444 serialNumber = crlEntry.getSerialNumber(); 445 446 // 获取被吊销证书的吊销日期 447 try { 448 crlEntry.getRevocationDate(); 449 } catch (error) { 450 console.log("getRevocationDate failed, errCode: " + error.code + ", errMsg: " + error.message); 451 } 452 453 // 获取被吊销证书对象的序列化数据 454 crlEntry.getEncoded(function (err, data) { 455 if (err != null) { 456 // 获取序列化数据失败 457 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 458 } else { 459 // 获取序列化数据成功 460 console.log("getEncoded success"); 461 } 462 }); 463} 464``` 465