1# Certificate Development 2 3> **NOTE** 4> 5> This development guide applies to API version 9, OpenHarmony SDK version 3.2.9 or later, and JS development. 6 7## Using Certificates 8 9**When to Use** 10 11Typical operations involve the following: 12 131. Parse X.509 certificate data to generate a certificate object. 142. Obtain certificate information, such as the version and serial number of the certificate. 153. Obtains the serialized data of the certificate object. 164. Obtain the certificate public key. 175. Verify the certificate signature. 186. Verify the certificate validity period. 19 20**Available APIs** 21 22For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). 23 24The table below describes the APIs used in this guide. 25 26| Instance | API | Description | 27| --------------- | ------------------------------------------------------------ | -------------------------------------------- | 28| cryptoCert | createX509Cert(inStream : EncodingBlob, callback : AsyncCallback\<X509Cert>) : void | Parses certificate data to create an **X509Cert** instance. This API uses an asynchronous callback to return the result.| 29| cryptoCert | createX509Cert(inStream : EncodingBlob) : Promise\<X509Cert> | Parses certificate data to create an **X509Cert** instance. This API uses a promise to return the result. | 30| X509Cert | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\<void>) : void | Verifies the certificate signature. This API uses an asynchronous callback to return the result. | 31| X509Cert | verify(key : cryptoFramework.PubKey) : Promise\<void> | Verifies the certificate signature. This API uses a promise to return the result. | 32| X509Cert | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void | Obtains serialized certificate data. This API uses an asynchronous callback to return the result. | 33| X509Cert | getEncoded() : Promise\<EncodingBlob> | Obtains serialized certificate data. This API uses a promise to return the result. | 34| X509Cert | getPublicKey() : cryptoFramework.PubKey | Obtains the certificate public key. | 35| X509Cert | checkValidityWithDate(date: string) : void | Checks the certificate validity period. | 36| X509Cert | getVersion() : number | Obtains the certificate version. | 37| X509Cert | getSerialNumber() : number | Obtains the certificate serial number. | 38| X509Cert | getIssuerName() : DataBlob | Obtains the certificate issuer. | 39| X509Cert | getSubjectName() : DataBlob | Obtains the certificate subject. | 40| X509Cert | getNotBeforeTime() : string | Obtains the time from which the certificate takes effect. | 41| X509Cert | getNotAfterTime() : string | Obtains the expiration time of the certificate. | 42| X509Cert | getSignature() : DataBlob | Obtains the certificate signature. | 43| X509Cert | getSignatureAlgName() : string | Obtain the certificate signing algorithm. | 44| X509Cert | getSignatureAlgOid() : string | Obtains the certificate signing algorithm object identifier (OID). | 45| X509Cert | getSignatureAlgParams() : DataBlob | Obtains the certificate signing algorithm parameters. | 46| X509Cert | getKeyUsage() : DataBlob | Obtains the key usage of the certificate. | 47| X509Cert | getExtKeyUsage() : DataArray | Obtains the usage of the certificate extension key. | 48| X509Cert | getBasicConstraints() : number | Obtains the basic constraints on the certificate. | 49| X509Cert | getSubjectAltNames() : DataArray | Obtains the Subject Alternative Names (SANs) of the certificate. | 50| X509Cert | getIssuerAltNames() : DataArray | Obtains the Issuer Alternative Names (IANs) of the certificate. | 51 52**How to Develop** 53 54Example: Parse the X.509 certificate data to create an **X509Cert** instance and call APIs to perform certificate operations. 55 56```javascript 57import cryptoCert from '@ohos.security.cert'; 58import cryptoFramework from '@ohos.security.cryptoFramework'; 59 60// Certificate data, which is only an example. The certificate data varies with the service. 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// Convert the certificate data form a string to a 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// Certificate example 84function certSample() { 85 let encodingBlob = { 86 // Convert the certificate data string to a Uint8Array. 87 data: stringToUint8Array(certData), 88 // Certificate format. Only PEM and DER are supported. In this example, the certificate is in PEM format. 89 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 90 }; 91 92 // Create an X509Cert instance. 93 cryptoCert.createX509Cert(encodingBlob, function (err, x509Cert) { 94 if (err != null) { 95 // Failed to create the X509Cert instance. 96 console.log("createX509Cert failed, errCode: " + err.code + ", errMsg: " + err.message); 97 return; 98 } 99 // The X509Cert instance is successfully created. 100 console.log("createX509Cert success"); 101 102 // Obtain the certificate version. 103 let version = x509Cert.getVersion(); 104 105 // Obtain the serialized data of the certificate. 106 x509Cert.getEncoded(function (err, data) { 107 if (err != null) { 108 // Failed to obtain the serialized data of the certificate. 109 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 110 } else { 111 // The serialized data of the certificate is successfully obtained. 112 console.log("getEncoded success"); 113 } 114 }); 115 116 // Obtain the public key object using the getPublicKey() of the upper-level certificate object or this (self-signed) certificate object. 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 // Verify the certificate signature. 125 x509Cert.verify(pubKey, function (err, data) { 126 if (err == null) { 127 // The signature verification is successful. 128 console.log("verify success"); 129 } else { 130 // The signature verification failed. 131 console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); 132 } 133 }); 134 135 // Time represented in a string. 136 let date = "150527000001Z"; 137 138 // Verify the certificate validity period. 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## Using the CRL 149 150**When to Use** 151 152Typical operations involve the following: 153 1541. Parse the X.509 CRL data to create an **X509Crl** instance. 1552. Obtain the CRL information, such as the CRL version and type. 1563. Obtain the serialized data of the CRL. 1574. Check whether the certificate is revoked. 1585. Verify the CRL signature. 1596. Obtain the revoked certificates. 160 161**Available APIs** 162 163For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). 164 165The table below describes the APIs used in this guide. 166 167| Instance | API | Description | 168| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 169| cryptoCert | createX509Crl(inStream : EncodingBlob, callback : AsyncCallback\<X509Crl>) : void | Parses the X.509 CRL data to create an **X509Crl** instance. This API uses an asynchronous callback to return the result.| 170| cryptoCert | createX509Crl(inStream : EncodingBlob) : Promise\<X509Crl> | Parses the X.509 CRL data to create an **X509Crl** instance. This API uses a promise to return the result. | 171| X509Crl | isRevoked(cert : X509Cert) : boolean | Checks whether the certificate is revoked. | 172| X509Crl | getType() : string | Obtains the CRL type. | 173| X509Crl | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void | Obtains the serialized CRL data. This API uses an asynchronous callback to return the result. | 174| X509Crl | getEncoded() : Promise\<EncodingBlob> | Obtains the serialized CRL data. This API uses a promise to return the result. | 175| X509Crl | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\<void>) : void | Verifies the CRL signature. This API uses an asynchronous callback to return the result. | 176| X509Crl | verify(key : cryptoFramework.PubKey) : Promise\<void> | Verifies the CRL signature. This API uses a promise to return the result. | 177| X509Crl | getVersion() : number | Obtains the CRL version. | 178| X509Crl | getIssuerName() : DataBlob | Obtains the CRL issuer. | 179| X509Crl | getLastUpdate() : string | Obtains the date when the CRL was last updated. | 180| X509Crl | getNextUpdate() : string | Obtains the next update date of the CRL. | 181| X509Crl | getRevokedCert(serialNumber : number) : X509CrlEntry | Obtains the revoked certificate in the CRL based on the serial number. | 182| X509Crl | getRevokedCertWithCert(cert : X509Cert) : X509CrlEntry | Obtains the revoked certificate in the CRL based on the X.509 certificate. | 183| X509Crl | getRevokedCerts(callback : AsyncCallback\<Array\<X509CrlEntry>>) : void | Obtains all revoked certificates in the CRL. This API uses an asynchronous callback to return the result. | 184| X509Crl | getRevokedCerts() : Promise\<Array\<X509CrlEntry>> | Obtains all revoked certificates in the CRL. This API uses a promise to return the result. | 185| X509Crl | getTbsInfo() : DataBlob | Obtains **tbsCertList** of the CRL. | 186| X509Crl | getSignature() : DataBlob | Obtains the CRL signature. | 187| X509Crl | getSignatureAlgName() : string | Obtains the CRL signing algorithm. | 188| X509Crl | getSignatureAlgOid() : string | Obtains the signing algorithm OID of the CRL. | 189| X509Crl | getSignatureAlgParams() : DataBlob | Obtains the signing algorithm parameters of the CRL. | 190 191**How to Develop** 192 193Example: Parse the X.509 CRL data to create an **X509Crl** instance and call APIs to perform CRL operations. 194 195```javascript 196import cryptoCert from '@ohos.security.cert'; 197import cryptoFramework from '@ohos.security.cryptoFramework'; 198 199// CRL data, which is only an example. The CRL data varies with the service. 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// Convert the certificate data form a string to a 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// Example of a CRL. 222function crlSample() { 223 let encodingBlob = { 224 // Convert the CRL data from a string to a Uint8Array. 225 data: stringToUint8Array(crlData), 226 // CRL format. Only PEM and DER are supported. In this example, the CRL is in PEM format. 227 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 228 }; 229 230 // Create an X509Crl instance. 231 cryptoCert.createX509Crl(encodingBlob, function (err, x509Crl) { 232 if (err != null) { 233 // Failed to create the X509Crl instance. 234 console.log("createX509Crl failed, errCode: " + err.code + ", errMsg: " + err.message); 235 return; 236 } 237 // The X509Crl instance is successfully created. 238 console.log("createX509Crl success"); 239 240 // Obtain the CRL version. 241 let version = x509Crl.getVersion(); 242 243 // Obtain the serialized data of the CRL. 244 x509Crl.getEncoded(function (err, data) { 245 if (err != null) { 246 // Failed to obtain the serialized data of the certificate. 247 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 248 } else { 249 // The serialized data of the certificate is successfully obtained. 250 console.log("getEncoded success"); 251 } 252 }); 253 254 // Create an X509Cert instance by using createX509Cert() of cryptoFramework. 255 let x509Cert = null; 256 // Check whether the certificate is revoked. 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 // The binary data of the public key needs to be passed to convertKey() of @ohos.security.cryptoFramework to obtain the PubKey object. The process is omitted here. 264 let pubKey = null; 265 266 // Verify the CRL signature. 267 x509Crl.verify(pubKey, function (err, data) { 268 if (err == null) { 269 // The signature verification is successful. 270 console.log("verify success"); 271 } else { 272 // The signature verification failed. 273 console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); 274 } 275 }); 276 277 // Certificate serial number, which must be set based on the service. 278 let serialNumber = 1000; 279 280 // Obtain the revoked certificate based on the serial number. 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## Verifying Certificate Chains 291 292**When to Use** 293 294You need to use the certificate chain validator in certificate chain verification. 295 296**Available APIs** 297 298For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). 299 300The table below describes the APIs used in this guide. 301 302| Instance | API | Description | 303| ------------------ | ------------------------------------------------------------ | -------------------------------- | 304| cryptoCert | createCertChainValidator(algorithm :string) : CertChainValidator | Creates a **CertChainValidator** instance.| 305| CertChainValidator | validate(certChain : CertChainData, callback : AsyncCallback\<void>) : void | Verifies the certificate chain. This API uses an asynchronous callback to return the result. | 306| CertChainValidator | validate(certChain : CertChainData) : Promise\<void> | Verifies the certificate chain. This API uses a promise to return the result. | 307| CertChainValidator | algorithm : string | Obtains the certificate chain validator algorithm. | 308 309**How to Develop** 310 311Example: Create a **CertChainValidator** instance and verify the certificate chain. 312 313```javascript 314import cryptoCert from '@ohos.security.cert'; 315 316// CA certificate data, which is only an example. The CA certificate data varies with the service. 317let caCertData = "-----BEGIN CERTIFICATE-----\n" 318+ "...\n" 319+ "...\n" 320+ "...\n" 321+ "-----END CERTIFICATE-----\n"; 322 323// End-entity certificate data, which is only an example. The certificate data varies with the service. 324let secondCaCertData = "-----BEGIN CERTIFICATE-----\n" 325+ "...\n" 326+ "...\n" 327+ "...\n" 328+ "-----END CERTIFICATE-----\n"; 329 330// Convert the certificate data form a string to a 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// Certificate chain validator example. In this example, a two-level certificate chain is verified. 340function certChainValidatorSample() { 341 // Certificate chain validator algorithm. Currently, only PKIX is supported. 342 let algorithm = "PKIX"; 343 344 // Create a CertChainValidator instance. 345 let validator = cryptoCert.createCertChainValidator(algorithm); 346 347 // CA certificate data. 348 let uint8ArrayOfCaCertData = stringToUint8Array(caCertData); 349 350 // Length of the CA certificate data. 351 let uint8ArrayOfCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOfCaCertData.byteLength]).buffer); 352 353 // End-entity certificate data. 354 let uint8ArrayOf2ndCaCertData = stringToUint8Array(secondCaCertData); 355 356 // Length of the end-entity certificate data. 357 let uint8ArrayOf2ndCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOf2ndCaCertData.byteLength]).buffer); 358 359 // Certificate chain binary data: end-entity certificate data length + end-entity certificate data + CA certificate data length + CA certificate data (in L-V format). 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 type: L-V format (certificate data length-certificate data) 378 data: encodingData, 379 // Number of certificates. It is 2 in this example. 380 count: 2, 381 // Certificate format. PEM and DER are supported. In this example, the certificate is in PEM format. 382 encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM 383 }; 384 385 // Verify the certificate chain. 386 validator.validate(certChainData, function (err, data) { 387 if (err != null) { 388 // The operation fails. 389 console.log("validate failed, errCode: " + err.code + ", errMsg: " + err.message); 390 } else { 391 // The operation is successful. 392 console.log("validate success"); 393 } 394 }); 395} 396``` 397 398## Managing Revoked Certificates 399 400**When to Use** 401 402Typical operations involve the following: 403 4041. Obtain a revoked certificate instance. 4052. Obtain information, such as the serial number, issuer, and certificate revocation date, of the revoked certificate. 4063. Obtain the serialized data of the revoked certificate. 407 408**Available APIs** 409 410For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). 411 412The table below describes the APIs used in this guide. 413 414| Instance | API | Description | 415| ------------ | ----------------------------------------------------------- | ---------------------------------------- | 416| X509CrlEntry | getEncoded(callback : AsyncCallback\<EncodingBlob>) : void; | Obtains the serialized data of the revoked certificate. This API uses an asynchronous callback to return the result.| 417| X509CrlEntry | getEncoded() : Promise\<EncodingBlob>; | Obtains the serialized data of the revoked certificate. This API uses a promise to return the result. | 418| X509CrlEntry | getSerialNumber() : number; | Obtains the serial number of the revoked certificate. | 419| X509CrlEntry | getCertIssuer() : DataBlob; | Obtains the issuer of the revoked certificate. | 420| X509CrlEntry | getRevocationDate() : string; | Obtains the revocation date of the revoked certificate. | 421 422**How to Develop** 423 424Example: Obtain a revoked certificate instance and call the APIs. 425 426```javascript 427import cryptoCert from '@ohos.security.cert'; 428 429// Example of a revoked certificate. 430function crlEntrySample() { 431 // Create an **X509Crl** instance by using createX509Crl() of cryptoFramework. 432 let x509Crl = null; 433 434 // Obtain a revoked certificate instance. In this example, the instance is obtained by using 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 // Obtain the serial number of the revoked certificate. 444 serialNumber = crlEntry.getSerialNumber(); 445 446 // Obtain the revocation date of the revoked certificate. 447 try { 448 crlEntry.getRevocationDate(); 449 } catch (error) { 450 console.log("getRevocationDate failed, errCode: " + error.code + ", errMsg: " + error.message); 451 } 452 453 // Obtain the serialized data of the revoked certificate instance. 454 crlEntry.getEncoded(function (err, data) { 455 if (err != null) { 456 // Failed to obtain the serialized data of the certificate. 457 console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); 458 } else { 459 // The serialized data of the certificate is successfully obtained. 460 console.log("getEncoded success"); 461 } 462 }); 463} 464``` 465