# Certificate Development > **NOTE** > > This development guide applies to API version 9, OpenHarmony SDK version 3.2.9 or later, and JS development. ## Using Certificates **When to Use** Typical operations involve the following: 1. Parse X.509 certificate data to generate a certificate object. 2. Obtain certificate information, such as the version and serial number of the certificate. 3. Obtains the serialized data of the certificate object. 4. Obtain the certificate public key. 5. Verify the certificate signature. 6. Verify the certificate validity period. **Available APIs** For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). The table below describes the APIs used in this guide. | Instance | API | Description | | --------------- | ------------------------------------------------------------ | -------------------------------------------- | | cryptoCert | createX509Cert(inStream : EncodingBlob, callback : AsyncCallback\) : void | Parses certificate data to create an **X509Cert** instance. This API uses an asynchronous callback to return the result.| | cryptoCert | createX509Cert(inStream : EncodingBlob) : Promise\ | Parses certificate data to create an **X509Cert** instance. This API uses a promise to return the result. | | X509Cert | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\) : void | Verifies the certificate signature. This API uses an asynchronous callback to return the result. | | X509Cert | verify(key : cryptoFramework.PubKey) : Promise\ | Verifies the certificate signature. This API uses a promise to return the result. | | X509Cert | getEncoded(callback : AsyncCallback\) : void | Obtains serialized certificate data. This API uses an asynchronous callback to return the result. | | X509Cert | getEncoded() : Promise\ | Obtains serialized certificate data. This API uses a promise to return the result. | | X509Cert | getPublicKey() : cryptoFramework.PubKey | Obtains the certificate public key. | | X509Cert | checkValidityWithDate(date: string) : void | Checks the certificate validity period. | | X509Cert | getVersion() : number | Obtains the certificate version. | | X509Cert | getSerialNumber() : number | Obtains the certificate serial number. | | X509Cert | getIssuerName() : DataBlob | Obtains the certificate issuer. | | X509Cert | getSubjectName() : DataBlob | Obtains the certificate subject. | | X509Cert | getNotBeforeTime() : string | Obtains the time from which the certificate takes effect. | | X509Cert | getNotAfterTime() : string | Obtains the expiration time of the certificate. | | X509Cert | getSignature() : DataBlob | Obtains the certificate signature. | | X509Cert | getSignatureAlgName() : string | Obtain the certificate signing algorithm. | | X509Cert | getSignatureAlgOid() : string | Obtains the certificate signing algorithm object identifier (OID). | | X509Cert | getSignatureAlgParams() : DataBlob | Obtains the certificate signing algorithm parameters. | | X509Cert | getKeyUsage() : DataBlob | Obtains the key usage of the certificate. | | X509Cert | getExtKeyUsage() : DataArray | Obtains the usage of the certificate extension key. | | X509Cert | getBasicConstraints() : number | Obtains the basic constraints on the certificate. | | X509Cert | getSubjectAltNames() : DataArray | Obtains the Subject Alternative Names (SANs) of the certificate. | | X509Cert | getIssuerAltNames() : DataArray | Obtains the Issuer Alternative Names (IANs) of the certificate. | **How to Develop** Example: Parse the X.509 certificate data to create an **X509Cert** instance and call APIs to perform certificate operations. ```javascript import cryptoCert from '@ohos.security.cert'; import cryptoFramework from '@ohos.security.cryptoFramework'; // Certificate data, which is only an example. The certificate data varies with the service. let certData = "-----BEGIN CERTIFICATE-----\n" + "IBzTCCAXCgAwIBAgIGAXKnMKNyMAwGCCqBHM9VAYN1BQAwSTELMAkGA1UEBhMC\n" + "04xDjAMBgNVBAoTBUdNU1NMMRAwDgYDVQQLEwdQS0kvU00yMRgwFgYDVQQDEw9S\n" + "290Q0EgZm9yIFRlc3QwIhgPMjAxNTEyMzExNjAwMDBaGA8yMDM1MTIzMDE2MDAw\n" + "FowSTELMAkGA1UEBhMCQ04xDjAMBgNVBAoTBUdNU1NMMRAwDgYDVQQLEwdQS0kv\n" + "00yMRgwFgYDVQQDEw9Sb290Q0EgZm9yIFRlc3QwWTATBgcqhkjOPQIBBggqgRzP\n" + "QGCLQNCAATj+apYlL+ddWXZ7+mFZXZJGbcJFXUN+Fszz6humeyWZP4qEEr2N0+a\n" + "dwo/21ft232yo0jPLzdscKB261zSQXSoz4wPDAZBgNVHQ4EEgQQnGnsD7oaOcWv\n" + "CTrspwSBDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIAxjAMBggqgRzP\n" + "QGDdQUAA0kAMEYCIQCEnW5BlQh0vmsOLxSoXYc/7zs++wWyFc1tnBHENR4ElwIh\n" + "I1Lwu6in1ruflZhzseWulXwcITf3bm/Y5X1g1XFWQUH\n" + "-----END CERTIFICATE-----\n"; // Convert the certificate data form a string to a Uint8Array. function stringToUint8Array(str) { var arr = []; for (var i = 0, j = str.length; i < j; i++) { arr.push(str.charCodeAt(i)); } return new Uint8Array(arr); } // Certificate example function certSample() { let encodingBlob = { // Convert the certificate data string to a Uint8Array. data: stringToUint8Array(certData), // Certificate format. Only PEM and DER are supported. In this example, the certificate is in PEM format. encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM }; // Create an X509Cert instance. cryptoCert.createX509Cert(encodingBlob, function (err, x509Cert) { if (err != null) { // Failed to create the X509Cert instance. console.log("createX509Cert failed, errCode: " + err.code + ", errMsg: " + err.message); return; } // The X509Cert instance is successfully created. console.log("createX509Cert success"); // Obtain the certificate version. let version = x509Cert.getVersion(); // Obtain the serialized data of the certificate. x509Cert.getEncoded(function (err, data) { if (err != null) { // Failed to obtain the serialized data of the certificate. console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); } else { // The serialized data of the certificate is successfully obtained. console.log("getEncoded success"); } }); // Obtain the public key object using the getPublicKey() of the upper-level certificate object or this (self-signed) certificate object. let pubKey = null; try { pubKey = x509Cert.getPublicKey(); } catch (error) { console.log("getPublicKey failed, errCode: " + error.code + ", errMsg: " + error.message); } // Verify the certificate signature. x509Cert.verify(pubKey, function (err, data) { if (err == null) { // The signature verification is successful. console.log("verify success"); } else { // The signature verification failed. console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); } }); // Time represented in a string. let date = "150527000001Z"; // Verify the certificate validity period. try { x509Cert.checkValidityWithDate(date); } catch (error) { console.log("checkValidityWithDate failed, errCode: " + error.code + ", errMsg: " + error.message); } }); } ``` ## Using the CRL **When to Use** Typical operations involve the following: 1. Parse the X.509 CRL data to create an **X509Crl** instance. 2. Obtain the CRL information, such as the CRL version and type. 3. Obtain the serialized data of the CRL. 4. Check whether the certificate is revoked. 5. Verify the CRL signature. 6. Obtain the revoked certificates. **Available APIs** For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). The table below describes the APIs used in this guide. | Instance | API | Description | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | cryptoCert | createX509Crl(inStream : EncodingBlob, callback : AsyncCallback\) : void | Parses the X.509 CRL data to create an **X509Crl** instance. This API uses an asynchronous callback to return the result.| | cryptoCert | createX509Crl(inStream : EncodingBlob) : Promise\ | Parses the X.509 CRL data to create an **X509Crl** instance. This API uses a promise to return the result. | | X509Crl | isRevoked(cert : X509Cert) : boolean | Checks whether the certificate is revoked. | | X509Crl | getType() : string | Obtains the CRL type. | | X509Crl | getEncoded(callback : AsyncCallback\) : void | Obtains the serialized CRL data. This API uses an asynchronous callback to return the result. | | X509Crl | getEncoded() : Promise\ | Obtains the serialized CRL data. This API uses a promise to return the result. | | X509Crl | verify(key : cryptoFramework.PubKey, callback : AsyncCallback\) : void | Verifies the CRL signature. This API uses an asynchronous callback to return the result. | | X509Crl | verify(key : cryptoFramework.PubKey) : Promise\ | Verifies the CRL signature. This API uses a promise to return the result. | | X509Crl | getVersion() : number | Obtains the CRL version. | | X509Crl | getIssuerName() : DataBlob | Obtains the CRL issuer. | | X509Crl | getLastUpdate() : string | Obtains the date when the CRL was last updated. | | X509Crl | getNextUpdate() : string | Obtains the next update date of the CRL. | | X509Crl | getRevokedCert(serialNumber : number) : X509CrlEntry | Obtains the revoked certificate in the CRL based on the serial number. | | X509Crl | getRevokedCertWithCert(cert : X509Cert) : X509CrlEntry | Obtains the revoked certificate in the CRL based on the X.509 certificate. | | X509Crl | getRevokedCerts(callback : AsyncCallback\>) : void | Obtains all revoked certificates in the CRL. This API uses an asynchronous callback to return the result. | | X509Crl | getRevokedCerts() : Promise\> | Obtains all revoked certificates in the CRL. This API uses a promise to return the result. | | X509Crl | getTbsInfo() : DataBlob | Obtains **tbsCertList** of the CRL. | | X509Crl | getSignature() : DataBlob | Obtains the CRL signature. | | X509Crl | getSignatureAlgName() : string | Obtains the CRL signing algorithm. | | X509Crl | getSignatureAlgOid() : string | Obtains the signing algorithm OID of the CRL. | | X509Crl | getSignatureAlgParams() : DataBlob | Obtains the signing algorithm parameters of the CRL. | **How to Develop** Example: Parse the X.509 CRL data to create an **X509Crl** instance and call APIs to perform CRL operations. ```javascript import cryptoCert from '@ohos.security.cert'; import cryptoFramework from '@ohos.security.cryptoFramework'; // CRL data, which is only an example. The CRL data varies with the service. let crlData = "-----BEGIN X509 CRL-----\n" + "MIIBijB0AgEBMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHJvb3QtY2ExFw0y\n" + "MDA2MTkxNjE1NDhaFw0yMDA3MTkxNjE1NDhaMBwwGgIJAMsozRATnap1Fw0yMDA2\n" + "MTkxNjEyMDdaoA8wDTALBgNVHRQEBAICEAIwDQYJKoZIhvcNAQELBQADggEBACPs\n" + "9gQB+djaXPHHRmAItebZpD3iJ/e36Dxr6aMVkn9FkI8OVpUI4RNcCrywyCZHQJte\n" + "995bbPjP7f1sZstOTZS0fDPgJ5SPAxkKOQB+SQnBFrlZSsxoUNU60gRqd2imR0Rn\n" + "1r09rP69F6E4yPc9biEld+llLGgoImP3zPOVDD6fbfcvVkjStY3bssVEQ/vjp4a3\n" + "/I12U7ZnSe3jaKqaQBoVJppkTFOIOq7IOxf5/IkMPmvRHDeC2IzDMzcUxym0dkny\n" + "EowHrjzo0bZVqpHMA2YgKZuwTpVLHk9GeBEK2hVkIoPVISkmiU4HFg0S6z68C5yd\n" + "DrAA7hErVgXhtURLbAI=\n" + "-----END X509 CRL-----\n"; // Convert the certificate data form a string to a Uint8Array. function stringToUint8Array(str) { var arr = []; for (var i = 0, j = str.length; i < j; i++) { arr.push(str.charCodeAt(i)); } return new Uint8Array(arr); } // Example of a CRL. function crlSample() { let encodingBlob = { // Convert the CRL data from a string to a Uint8Array. data: stringToUint8Array(crlData), // CRL format. Only PEM and DER are supported. In this example, the CRL is in PEM format. encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM }; // Create an X509Crl instance. cryptoCert.createX509Crl(encodingBlob, function (err, x509Crl) { if (err != null) { // Failed to create the X509Crl instance. console.log("createX509Crl failed, errCode: " + err.code + ", errMsg: " + err.message); return; } // The X509Crl instance is successfully created. console.log("createX509Crl success"); // Obtain the CRL version. let version = x509Crl.getVersion(); // Obtain the serialized data of the CRL. x509Crl.getEncoded(function (err, data) { if (err != null) { // Failed to obtain the serialized data of the certificate. console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); } else { // The serialized data of the certificate is successfully obtained. console.log("getEncoded success"); } }); // Create an X509Cert instance by using createX509Cert() of cryptoFramework. let x509Cert = null; // Check whether the certificate is revoked. try { let revokedFlag = x509Crl.isRevoked(x509Cert); } catch (error) { console.log("isRevoked failed, errCode: " + error.code + ", errMsg: " + error.message); } // 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. let pubKey = null; // Verify the CRL signature. x509Crl.verify(pubKey, function (err, data) { if (err == null) { // The signature verification is successful. console.log("verify success"); } else { // The signature verification failed. console.log("verify failed, errCode: " + err.code + ", errMsg: " + err.message); } }); // Certificate serial number, which must be set based on the service. let serialNumber = 1000; // Obtain the revoked certificate based on the serial number. try { let entry = x509Crl.getRevokedCert(serialNumber); } catch (error) { console.log("getRevokedCert failed, errCode: " + error.code + ", errMsg: " + error.message); } }); } ``` ## Verifying Certificate Chains **When to Use** You need to use the certificate chain validator in certificate chain verification. **Available APIs** For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). The table below describes the APIs used in this guide. | Instance | API | Description | | ------------------ | ------------------------------------------------------------ | -------------------------------- | | cryptoCert | createCertChainValidator(algorithm :string) : CertChainValidator | Creates a **CertChainValidator** instance.| | CertChainValidator | validate(certChain : CertChainData, callback : AsyncCallback\) : void | Verifies the certificate chain. This API uses an asynchronous callback to return the result. | | CertChainValidator | validate(certChain : CertChainData) : Promise\ | Verifies the certificate chain. This API uses a promise to return the result. | | CertChainValidator | algorithm : string | Obtains the certificate chain validator algorithm. | **How to Develop** Example: Create a **CertChainValidator** instance and verify the certificate chain. ```javascript import cryptoCert from '@ohos.security.cert'; // CA certificate data, which is only an example. The CA certificate data varies with the service. let caCertData = "-----BEGIN CERTIFICATE-----\n" + "...\n" + "...\n" + "...\n" + "-----END CERTIFICATE-----\n"; // End-entity certificate data, which is only an example. The certificate data varies with the service. let secondCaCertData = "-----BEGIN CERTIFICATE-----\n" + "...\n" + "...\n" + "...\n" + "-----END CERTIFICATE-----\n"; // Convert the certificate data form a string to a Uint8Array.. function stringToUint8Array(str) { var arr = []; for (var i = 0, j = str.length; i < j; i++) { arr.push(str.charCodeAt(i)); } return new Uint8Array(arr); } // Certificate chain validator example. In this example, a two-level certificate chain is verified. function certChainValidatorSample() { // Certificate chain validator algorithm. Currently, only PKIX is supported. let algorithm = "PKIX"; // Create a CertChainValidator instance. let validator = cryptoCert.createCertChainValidator(algorithm); // CA certificate data. let uint8ArrayOfCaCertData = stringToUint8Array(caCertData); // Length of the CA certificate data. let uint8ArrayOfCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOfCaCertData.byteLength]).buffer); // End-entity certificate data. let uint8ArrayOf2ndCaCertData = stringToUint8Array(secondCaCertData); // Length of the end-entity certificate data. let uint8ArrayOf2ndCaCertDataLen = new Uint8Array(new Uint16Array([uint8ArrayOf2ndCaCertData.byteLength]).buffer); // Certificate chain binary data: end-entity certificate data length + end-entity certificate data + CA certificate data length + CA certificate data (in L-V format). let encodingData = new Uint8Array(uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + uint8ArrayOfCaCertDataLen.length + uint8ArrayOfCaCertData.length); for (var i = 0; i < uint8ArrayOf2ndCaCertDataLen.length; i++) { encodingData[i] = uint8ArrayOf2ndCaCertDataLen[i]; } for (var i = 0; i < uint8ArrayOf2ndCaCertData.length; i++) { encodingData[uint8ArrayOf2ndCaCertDataLen.length + i] = uint8ArrayOf2ndCaCertData[i]; } for (var i = 0; i < uint8ArrayOfCaCertDataLen.length; i++) { encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + i] = uint8ArrayOfCaCertDataLen[i]; } for (var i = 0; i < uint8ArrayOfCaCertData.length; i++) { encodingData[uint8ArrayOf2ndCaCertDataLen.length + uint8ArrayOf2ndCaCertData.length + uint8ArrayOfCaCertDataLen.length + i] = uint8ArrayOfCaCertData[i]; } let certChainData = { // Uint8Array type: L-V format (certificate data length-certificate data) data: encodingData, // Number of certificates. It is 2 in this example. count: 2, // Certificate format. PEM and DER are supported. In this example, the certificate is in PEM format. encodingFormat: cryptoCert.EncodingFormat.FORMAT_PEM }; // Verify the certificate chain. validator.validate(certChainData, function (err, data) { if (err != null) { // The operation fails. console.log("validate failed, errCode: " + err.code + ", errMsg: " + err.message); } else { // The operation is successful. console.log("validate success"); } }); } ``` ## Managing Revoked Certificates **When to Use** Typical operations involve the following: 1. Obtain a revoked certificate instance. 2. Obtain information, such as the serial number, issuer, and certificate revocation date, of the revoked certificate. 3. Obtain the serialized data of the revoked certificate. **Available APIs** For details about the APIs, see [Certificate](../reference/apis/js-apis-cert.md). The table below describes the APIs used in this guide. | Instance | API | Description | | ------------ | ----------------------------------------------------------- | ---------------------------------------- | | X509CrlEntry | getEncoded(callback : AsyncCallback\) : void; | Obtains the serialized data of the revoked certificate. This API uses an asynchronous callback to return the result.| | X509CrlEntry | getEncoded() : Promise\; | Obtains the serialized data of the revoked certificate. This API uses a promise to return the result. | | X509CrlEntry | getSerialNumber() : number; | Obtains the serial number of the revoked certificate. | | X509CrlEntry | getCertIssuer() : DataBlob; | Obtains the issuer of the revoked certificate. | | X509CrlEntry | getRevocationDate() : string; | Obtains the revocation date of the revoked certificate. | **How to Develop** Example: Obtain a revoked certificate instance and call the APIs. ```javascript import cryptoCert from '@ohos.security.cert'; // Example of a revoked certificate. function crlEntrySample() { // Create an **X509Crl** instance by using createX509Crl() of cryptoFramework. let x509Crl = null; // Obtain a revoked certificate instance. In this example, the instance is obtained by using getRevokedCert(). let serialNumber = 1000; let crlEntry = null; try { crlEntry = x509Crl.getRevokedCert(serialNumber); } catch (error) { console.log("getRevokedCert failed, errCode: " + error.code + ", errMsg: " + error.message); } // Obtain the serial number of the revoked certificate. serialNumber = crlEntry.getSerialNumber(); // Obtain the revocation date of the revoked certificate. try { crlEntry.getRevocationDate(); } catch (error) { console.log("getRevocationDate failed, errCode: " + error.code + ", errMsg: " + error.message); } // Obtain the serialized data of the revoked certificate instance. crlEntry.getEncoded(function (err, data) { if (err != null) { // Failed to obtain the serialized data of the certificate. console.log("getEncoded failed, errCode: " + err.code + ", errMsg: " + err.message); } else { // The serialized data of the certificate is successfully obtained. console.log("getEncoded success"); } }); } ```