在对其他实体(设备、服务器)的证书凭据进行校验时,您的应用需要使用CA证书。例如您的应用使用预置的CA证书对应用服务器的HTTPS证书链进行可信校验。根据通信实现方式的不同,证书信任的配置方案也存在差异,下面分两种典型场景说明:
场景1:通过网络通信服务进行HTTPS连接。
您的应用可以参考Network Kit配置证书校验内容,利用Device Certificate Kit的系统CA证书、用户CA证书,对HTTPS证书链进行校验。

场景2:采用底层或自定义的安全协议进行通信。
如果您的应用需要采用底层或自定义的安全协议与应用服务器进行通信,则您的应用可能需要从Device Certificate Kit读取系统CA证书和用户CA证书对服务器的证书链进行校验。

Device Certificate Kit的CA证书管理功能包含如下能力:
系统CA证书管理:由操作系统预安装的CA证书,包括国密算法(SM算法)和国际算法(RSA和ECC算法)的CA证书。
只有通过《华为根证书计划》审核的CA证书才能预安装到HarmonyOS系统中。
系统CA证书包含了业界常用的商业CA证书,可以覆盖绝大部分互联网应用和网站的证书链校验需求。
设备的用户和应用只能读取系统CA证书,不能进行安装和更新。
用户CA证书管理:归属于设备用户的CA证书,由用户或MDM应用进行管理。仅当签发应用服务器证书的CA证书未包含在系统CA证书内,才需要安装用户CA证书,例如企业内部服务器使用的证书由企业自建CA证书颁发。
用户CA证书划分为两个作用范围(Scope):
当前用户级的CA证书:设备的用户间隔离,只有设备的当前登录用户才能访问和管理。设备用户可以通过系统设置应用进行管理,应用也可以通过API拉起证书管理服务的对话框(仅限PC/2in1设备支持),引导用户安装或卸载当前用户的CA证书。
所有用户级的CA证书:设备的所有用户都可以读取,当前只能通过MDM应用在企业设备上进行安装和管理。
| 用户CA证书的作用范围(Scope) | 作用范围说明 | 证书管理方式 | 设备用户可执行的操作 | 应用可执行的操作 | 典型应用场景 |
|---|---|---|---|---|---|
| 当前用户 | 用户间隔离 | 由用户管理 | 安装/卸载/查看 | 读取,拉起安装/卸载对话框 | 在BYOD设备访问企业内部的服务器。 |
| 所有用户 | 所有用户共享 | 由MDM应用管理 | 查看 | 读取 | 在企业设备访问企业内部的服务器。 |
本开发指导需使用API版本18及以上版本SDK。
使用并信任当前用户级的CA证书,设备的用户可以通过网络代理工具对您应用的通信消息进行中间人攻击,这可能导致您的应用产生安全风险。
具体请参考网络连接安全配置进行安全配置。
权限申请和声明。
MDM应用调用安装和卸载CA证书接口需要申请权限:ohos.permission.ACCESS_ENTERPRISE_USER_TRUSTED_CERT
调用其他接口需要申请权限:ohos.permission.ACCESS_CERT_MANAGER
声明权限请参考:声明权限
导入相关模块。
import { certificateManager, certificateManagerDialog } from '@kit.DeviceCertificateKit';
import { util } from '@kit.ArkTS';
import { common } from '@kit.AbilityKit';
import { UIContext } from '@kit.ArkUI'; 安装和卸载用户CA证书。
场景1:在BYOD设备安装用户CA证书。
应用调用openInstallCertificateDialog接口可拉起安装用户CA证书的对话框(certType参数设置为CA_CERT),安装页面需要对设备用户的身份进行认证。该接口只支持安装当前用户级的CA证书。
安装并信任用户CA证书,拥有CA证书的攻击者可能会获取到设备用户在访问网站或使用应用时传输的敏感信息。
拉起安装用户CA证书的对话框接口当前仅支持PC/2in1设备。
场景2:MDM应用在企业设备安装和卸载用户CA证书。
MDM应用可调用installUserTrustedCertificateSync接口安装用户CA证书,接口需要指定待安装的CA证书文件,并返回已安装的CA证书标识(certUri)。
MDM应用可调用uninstallUserTrustedCertificateSync接口卸载已安装的用户CA证书,输入已安装的CA证书标识certUri。
读取系统CA证书和用户CA证书。
证书管理服务提供了共享目录供应用读取系统CA证书和用户CA证书文件,您的应用可以先通过getCertificateStorePath接口获取对应CA证书的存储目录,然后从目录中读取CA证书文件(为pem格式的证书文件)。
系统CA证书按照国际和国密算法类型分别存储在两个目录,可以通过getCertificateStorePath接口的property.certAlg参数获取指定算法的证书存储目录。
用户CA证书按照当前用户级和所有用户级分别存储在不同的目录,可以通过getCertificateStorePath接口的property.certScope参数获取指定级别的证书存储目录。
import { certificateManager, certificateManagerDialog } from '@kit.DeviceCertificateKit';
import { util } from '@kit.ArkTS';
import { common } from '@kit.AbilityKit';
import { UIContext } from '@kit.ArkUI';
async function userCASample(): Promise<void> {
/* 安装的用户CA证书数据需要业务赋值。 */
let userCAData: Uint8Array = new util.TextEncoder().encodeInto('-----BEGIN CERTIFICATE-----\n' +
'MIIDSTCCAjECFFRZKkiBuiZ+zqfjJOg05yeTePM9MA0GCSqGSIb3DQEBCwUAMGEx\n' +
'CzAJBgNVBAYTAmNuMQ0wCwYDVQQIDARvaG9zMQswCQYDVQQHDAJjbTEhMB8GA1UE\n' +
'CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYDVQQDDApUZXN0Um9vdENB\n' +
'MB4XDTI1MTAxNTA3MzE0MloXDTI2MTAxNTA3MzE0MlowYTELMAkGA1UEBhMCY24x\n' +
'DTALBgNVBAgMBG9ob3MxCzAJBgNVBAcMAmNtMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n' +
'aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMClRlc3RSb290Q0EwggEiMA0GCSqGSIb3\n' +
'DQEBAQUAA4IBDwAwggEKAoIBAQC5p4eoQJyTBvn01M8SwEi8dguTIPGmD3a8SGIj\n' +
'KXaB6ltv742H5EBjgk+zC8+Gis0ehEqwk3pVnnmByeYvrERxsUqDt69/FndlfTxI\n' +
'C2/2MxWVk97g/6TpJ5Lt2mTrH+rSOgUDyU27aPn12ZnDF1mLsT+U+CBmfj4+J4tW\n' +
'yzdFNj7kcKMQQok+L1dtFlDNMNpMA1UqADzoC3XgFl49CpDtoFId9DVsgUPkPfX1\n' +
'89cCunomgJe1b17FzxfNu2yhbl5cnUEjeHGbmBgBIB7uG8tjGstnDPx7fl3Xrj+Q\n' +
'fRrwCpVKD9RxoyUBFbHttixxY5bHFUdvHRB251sxD+JfxxxLAgMBAAEwDQYJKoZI\n' +
'hvcNAQELBQADggEBAEGbNqcMU7C/lrIytI/OTtzYbkWDsfnRSPxlCUoZ2Xh3S83A\n' +
'SNQ9Ze5tDwWdW9Hlde9May6hzvuQSYeMLLnyM8WGResXCs7UbnSQe7fGfUu+xDGb\n' +
'h4tamnRFtZydxCCgDT9lIdHeutlPwOuxlR4HXpeowGeGJX0iFrdo6D0iXAY34hic\n' +
'yLQzuBqE/1s3PLA83Fi4EOOOV7P/ahmOLtBFlHbySHV68i9PNeNr9SDykH9/RgI9\n' +
'5G8ZTZj8oSmbTGGtfNuVXybMyJMRlz6BkxG++kYcg7STRBqHGX7RrWHiupguNreO\n' +
'4sJBdSpWBq172ZEyOvTqC4xX9lLYqwwBQ++TFoo=\n' +
'-----END CERTIFICATE-----');
let certUri: string = '';
/* 场景1:在BYOD设备安装用户CA证书 */
try {
certUri = await installUserCACertDialog(userCAData);
} catch (error) {
console.error(`Failed to install user CA certificate.`);
}
/* 获取CA证书 */
getUserCaCertSample();
/* 场景1:在BYOD设备卸载用户CA证书 */
uninstallUserCACertDialog(certUri);
/* 场景2:MDM应用在企业设备安装用户CA证书 */
certUri = installUserCACertEnterprise(userCAData);
/* 获取CA证书 */
getUserCaCertSample();
/* 场景2:MDM应用在企业设备卸载用户CA证书 */
uninstallUserCACertEnterprise(certUri);
}
async function installUserCACertDialog(userCAData: Uint8Array): Promise<string> {
return new Promise<string>((resolve, reject) => {
/* 场景1:在BYOD设备安装用户CA证书 */
try {
/* context为应用的上下文信息,调用方自行获取,此处仅为示例 */
let context: common.Context = new UIContext().getHostContext() as common.Context;
/* 安装用户CA证书 */
certificateManagerDialog.openInstallCertificateDialog(
context,
certificateManagerDialog.CertificateType.CA_CERT,
certificateManagerDialog.CertificateScope.CURRENT_USER,
userCAData
).then((keyUri: string) => {
console.info(`Installing user CA certificate successful, keyUri: ${keyUri}`);
resolve(keyUri);
}).catch((error: BusinessError) => {
console.error(`Failed to install user CA certificate. Code: ${error.code}, message: ${error.message}`);
reject(error);
});
} catch (error) {
console.error(`Failed to install user CA certificate. Code: ${error.code}, message: ${error.message}`);
reject(error);
}
})
}
function installUserCACertEnterprise(userCAData: Uint8Array): string {
/* 场景2:MDM应用在企业设备安装用户CA证书 */
try {
/* 在当前用户下,安装用户CA证书。 */
let result = certificateManager.installUserTrustedCertificateSync(
userCAData,
certificateManager.CertScope.CURRENT_USER
);
let certUri = result.uri ?? '';
console.info(`Sync install user CA certificate successful, certUri is ${certUri}`);
return certUri
} catch (err) {
console.error(`Failed to sync install user CA certificate. Code: ${err.code}, message: ${err.message}`);
}
return '';
}
async function uninstallUserCACertDialog(certUri: string): Promise<void> {
try {
/* 场景1:在BYOD设备卸载用户CA证书 */
/* context为应用的上下文信息,调用方自行获取,此处仅为示例 */
let context: common.Context = new UIContext().getHostContext() as common.Context;
certificateManagerDialog.openUninstallCertificateDialog(
context,
certificateManagerDialog.CertificateType.CA_CERT,
certUri
).then(() => {
console.info(`Uninstall user ca certificate successful.`);
}).catch((error: BusinessError) => {
console.error(`Failed to uninstall user ca certificate. Code: ${error.code}, message: ${error.message}`);
});
} catch (err) {
console.error(`Failed to uninstall user ca certificate. Code: ${err.code}, message: ${err.message}`);
}
}
function getUserCaCertSample(): void {
try {
/* 获取系统CA的存储位置。 */
let property1: certificateManager.CertStoreProperty = {
certType: certificateManager.CertType.CA_CERT_SYSTEM,
}
/* 您可以从systemCAPath目录读取CA证书。 */
let systemCAPath = certificateManager.getCertificateStorePath(property1);
console.info(`Success to get system ca path: ${systemCAPath}`);
/* 获取当前用户的用户CA存储位置。 */
let property2: certificateManager.CertStoreProperty = {
certType: certificateManager.CertType.CA_CERT_USER,
certScope: certificateManager.CertScope.CURRENT_USER,
}
/* 您可以从userCACurrentPath目录读取CA证书。 */
let userCACurrentPath = certificateManager.getCertificateStorePath(property2);
console.info(`Success to get current user's user ca path: ${userCACurrentPath}`);
/* 获取设备公共的用户CA存储位置。 */
let property3: certificateManager.CertStoreProperty = {
certType: certificateManager.CertType.CA_CERT_USER,
certScope: certificateManager.CertScope.GLOBAL_USER,
}
/* 您可以从globalCACurrentPath目录读取CA证书。 */
let globalCACurrentPath = certificateManager.getCertificateStorePath(property3);
console.info(`Success to get global user's user ca path: ${globalCACurrentPath}`);
} catch (error) {
console.error(`Failed to get store path. Code: ${error.code}, message: ${error.message}`);
}
}
async function uninstallUserCACertEnterprise(certUri: string): Promise<void> {
try {
/* 场景2:MDM应用在企业设备卸载用户CA证书 */
certificateManager.uninstallUserTrustedCertificateSync(certUri);
console.info(`Uninstall user ca certificate successful.`);
} catch (err) {
console.error(`Failed to uninstall user ca certificate. Code: ${err.code}, message: ${err.message}`);
}
}