鴻蒙HarmonyOS:深入Device Certificate Kit API:從整合到實戰鴻蒙HarmonyOS:深入Device Certificate Kit API:從整合到實戰

SameX發表於2024-11-10

本文旨在深入探討華為鴻蒙HarmonyOS Next系統(截止目前API12)的技術細節,基於實際開發實踐進行總結。主要作為技術分享與交流載體,難免錯漏,歡迎各位同仁提出寶貴意見和問題,以便共同進步。本文為原創內容,任何形式的轉載必須註明出處及原作者。

在鴻蒙系統的開發之旅中,Device Certificate Kit的API就像是一把把神奇的鑰匙,能夠幫助開發者開啟裝置安全的大門。今天,咱們就深入研究一下這些API,看看如何巧妙地呼叫和整合它們,讓我們的應用更加安全可靠。

首先,咱們來認識一下Device Certificate Kit的一些核心API。比如說,在證書管理方面,有installPrivateCertificate用於安裝私有憑據,它需要傳入憑據資料(keystore)、密碼(keystorePwd)以及證書別名(certAlias)等引數。這就好比你要把一個重要檔案放進保險櫃,需要提供檔案本身、保險櫃密碼以及給檔案起個容易識別的名字。呼叫示例如下:

import { certificateManager } from '@kit.DeviceCertificateKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 假設的憑據資料
let keystore: Uint8Array = new Uint8Array([0x30, 0x82, 0x04, 0x6a, 0x02, 0x01]);
let keystorePwd: string = '123456';
let appKeyUri: string = '';

try {
    const res: certificateManager.CMResult = await certificateManager.installPrivateCertificate(keystore, keystorePwd, "testPriCredential");
    appKeyUri = (res.uri!= undefined)? res.uri : '';
} catch (err) {
    let e: BusinessError = err as BusinessError;
    console.error(`Failed to install private certificate. Code: ${e.code}, message: ${e.message}`);
}

再比如getPrivateCertificate用於獲取私有憑據,透過傳入證書的標識(keyUri)來獲取相應的證書資訊。這就像是你在圖書館根據圖書編號查詢特定的書籍一樣。

在證書驗證方面,有verify方法。以X509證書驗證為例,需要先獲取證書中的公鑰,然後使用verify方法傳入公鑰和相關資料進行驗證。就像你在驗證一個人的身份時,需要檢視他的身份證(公鑰)是否真實有效。

下面是一個更完整的裝置證書API呼叫示例,涵蓋了初始化、管理、驗證等一系列操作。假設我們要建立一個證書鏈並進行驗證:

import { cert } from '@kit.DeviceCertificateKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { util } from '@kit.ArkTS';

// 證書鏈資料(示例,需根據實際情況替換)
let certChainData = "-----BEGIN CERTIFICATE-----\n" +
"MIID6jCCAtKgAwIBAgIIIM2q/TmRoLcwDQYJKoZIhvcNAQELBQAwWjELMAkGA1\n" +
"UEBhMCRU4xEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEMMA\n" +
"oGA1UEChMDdHMyMQwwCgYDVQQLEwN0czIxDDAKBgNVBAMTA3RzMjAeFw0yMzEy\n" +
"MDUwNzM5MDBaFw0yNDEwMzEyMzU5MDBaMGExCzAJBgNVBAYTAkNOMRAwDgYDVQQI\n" +
"EwdKaWFuZ3N1MRAwDgYDVQQHEwdOYW5qaW5nMQwwCgYDVQQKEwN0czMxDDAKBg\n" +
"NVBAsTA3RzMzESMBAGA1UEAxMJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAtt+2QxUevbolYLp51QGcUpageI4fwGLIqv4fj4aoVnHFOOBqVOVpfCLR\n" +
"p26LFV/F8ebwPyo8YEBKSwXzMD1573rMSbaH9BalscH5lZYAbetXoio6YRvzlcmc\n" +
"rVvLBNMeVnxY86xHpo0MTNyP7W024rZsxWO98xFQVdoiaBC+7+midlisx2Y+7u0\n" +
"zT9GjeUP6JLdLFUZJKUPSTK3jVzw9v1eZQZKYoNfU6vFMd6ndtwW6qEnwpzmmX\n" +
"/UT+p5ThAMH593zszlz330nTSXBjIsGkyvOz9gSB0Z0LAuJj06XUNhGL5xKJYKbdI3\n" +
"8MFQFJKvRHfgTAvVsvAvpBUM2DuBKwIDAQABo4GsMIGpMAkGA1UdEwQCMAA\n" +
"wHQYDVR0OBBYEFDfsHTMZwoA6eaDFlBUyDpka+sYtMAsGA1UdDwQEAwID+DAnBgN\n" +
"VHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMEMBQGA1UdEQQNM\n" +
"AuCCTEyNy4wLjAuMTARBglghkgBhvhCAQEEBAMCBkAwHgYJYIZIAYb4QgENBBEWD3hj\n" +
"YSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAp5vTvXrt8ZpgRJVtzv9ss0lJ\n" +
"izp1fJf+ft5cDXrs7TSD5oHrSW2vk/ZieIMhexU4LFwhs4OE7jK6pgI48Dseqxx7\n" +
"B/KktxhVMJUmVXd9Ayjp6f+BtZlIk0cArPuoXToXjsV8caTGBXHRdzxpAk/w9syc\n" +
"GYrbH9TrdNMuTizOb+k268oKXUageZNxHmd7YvOXkcNgrd29jzwXKDYYiUa1DI\n" +
"SzDnYaJOgPt0B/5izhoWNK7GhJDy9KEuLURcTSWFysbbnljwO9INPT9MmlS83PdAg\n" +
"NiS8VXF4pce1W9U5jH7d7k0JDVSXybebe1iPFphsZpYM/NE+jap+mPy1nTCbf9g==\n" +
"-----END CERTIFICATE-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIC0zCCAoWgAwIBAgIIXpLoPpQVWnkwBQYDK2VwMFoxCzAJBgNVBAYTAkV\n" +
"OMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xDDAKBgNVBAoT\n" +
"A3RzMTEMMAoGA1UECxMDdHMxMQwwCgYDVQQDEwN0czEwHhcNMjMxMjA1MDczNzA\n" +
"wWhcNMjQwOTAxMjM1OTAwWjBaMQswCQYDVQQGEwJFTjEQMA4GA1UECBMHRW5nbGFu\n" +
"ZDEPMA0GA1UEBxMGTG9uZG9uMQwwCgYDVQQKEwN0czIxDDAKBgNVBAsTA3RzMjEMM\n" +
"AoGA1UEAxMDdHMyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtt+2QxUev\n" +
"bolYLp51QGcUpageI4fwGLIqv4fj4aoVnHFOOBqVOVpfCLRp26LFV/F8ebwPyo8YEBK\n" +
"SwXzMD1573rMSbaH9BalscH5lZYAbetXoio6YRvzlcmcrVvLBNMeVnxY86xHpo0\n" +
"MNTyP7W024rZsxWO98xFQVdoiaBC+7+midlisx2Y+7u0jzT9GjeUP6JLdLFUZJKUP\n" +
"STK3jVzw9v1eZQZKYoNfU6vFMd6ndtwW6qEnwpzmmX/UT+p5ThAMH593zszlz\n" +
"330nTSXBjIsGkyvOz9gSB0Z0LAuJj06XUNhGL5xKJYKbdI38MFQFJKvRHfgTAvVsvAv\n" +
"pBUM2DuBKwIDAQABo28wbTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBQ3\n" +
"7B0zGcKAOnmgxZQVMg6ZGvrGLTALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAg\n" +
"AHMB4GCGCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwBQYDK2VwA0EAuasLBe\n" +
"55YgvFb4wmHeohylc9r8cFGS1LNQ5UcSn3sGqMYf6ehnef16NLuCW6upHCs8Sui4iAMvs\n" +
"uKPWR9dKBA==\n" +
"-----END CERTIFICATE-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIB3zCCAZGgAwIBAgIIWQvOEDl+ya4wBQYDK2VwMFoxCzAJBgNVBAYTAkVO\n" +
"MRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xDDAKBgNVBAoT\n" +
"A3RzMTEMMAoGA1UECxMDdHMxMQwwCgYDVQQDEwN0czEwHhcNMjMxMjA1MDAwMD\n" +
"AwWhcNMjQxMjA0MjM1OTU5WjBaMQswCQYDVQQGEwJFTjEQMA4GA1UECBMHRW5nbGFuZ\n" +
"DEPMA0GA1UEBxMGTG9uZG9uMQwwCgYDVQQKEwN0czExDDAKBgNVBAsTA3RzMTEM\n" +
"AoGA1UEAxMDdHMxMCowBQYDK2VwAyEAuxadj1ww0LqPN24zr28jcSOlSWAe0QdLyRF+Z\n" +
"gG6klKjdTBzMBIGA1UdEwEB/wQIMAYBAf8CARQwHQYDVR0OBBYEFNSgpoQvfxR8\n" +
"A1Y4St8NjOHkRpm4MAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJ\n" +
"YIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTAFBgMrZXADQQAblBgoa72X/K13W\n" +
"OvcKW0fqBgFKvLy85hWD6Ufi61k4ProQiZzMK+0+y9jReKelPx/zRdCCgSbQroAR2mV\n" +
"xjoE\n" +
"-----END CERTIFICATE-----\n";

// 證書鏈校驗資料(示例,需根據實際情況替換)
const param: cert.CertChainValidationParameters = {
    date: '20231212080000Z',
    trustAnchors: [{
        CAPubKey: new Uint8Array([0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
            0x03, 0x21, 0x00, 0xbb, 0x16, 0x9d, 0x8f, 0x5c, 0x30, 0xd0, 0xba, 0x8f, 0x37, 0x6e,
            0x33, 0xaf, 0x6f, 0x23, 0x71, 0x23, 0xa5, 0x49, 0x60, 0x1e, 0xd1, 0x07, 0x4b, 0xc9,
            0x11, 0x7e, 0x66, 0x01, 0xba, 0x92, 0x52]),
        CASubject: new Uint8Array([0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
            0x04, 0x06, 0x13, 0x02, 0x45, 0x4e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
            0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,
            0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x31,
            0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,
            0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,
            0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x74, 0x73, 0x31])
    }]
};

let textEncoder = new util.TextEncoder();
const encodingBlob: cert.EncodingBlob = {
    data: textEncoder.encodeInto(certChainData),
    encodingFormat: cert.EncodingFormat.FORMAT_PEM
};

let x509CertChain: cert.X509CertChain = {} as cert.X509CertChain;

try {
    x509CertChain = await cert.createX509CertChain(encodingBlob);
} catch (err) {
    let e: BusinessError = err as BusinessError;
    console.error(`createX509CertChain failed, errCode: ${e.code}, errMsg: ${e.message}`);
}

try {
    let certList = x509CertChain.getCertList();
} catch (err) {
    let e: BusinessError = err as BusinessError;
    console.error(`X509CertChain getCertList failed, errCode: ${e.code}, errMsg: ${e.message}`);
}
try {
    const validationRes = await x509CertChain.validate(param);
    console.log('X509CertChain validate success');
} catch (err) {
    console.error('X509CertChain validate failed');
}

在使用這些API的過程中,我們可能會遇到一些常見錯誤。比如,引數傳遞錯誤,可能會導致API呼叫失敗。就像你給一個函式傳入了錯誤型別的引數,函式當然不知道該怎麼處理啦。這時,我們需要仔細檢查引數的型別、格式以及取值範圍是否符合API的要求。另外,許可權不足也可能是一個問題。如果沒有正確配置相關許可權,API呼叫可能會被系統拒絕。這就好比你沒有鑰匙卻想開啟一扇門,那肯定是不行的。我們需要確保在module.json5檔案中正確配置了ohos.permission.ACCESS_CERT_MANAGER許可權等相關許可權。

為了讓大家更方便地瞭解Device Certificate Kit的常用API,下面是一個API列表和功能說明表格:

API名稱 功能說明 引數說明
installPrivateCertificate 安裝私有憑據 keystore(憑據資料)、keystorePwd(密碼)、certAlias(證書別名)
getPrivateCertificate 獲取私有憑據 keyUri(證書標識)
createX509CertChain 建立X509證書鏈物件 證書鏈資料(encodingBlob
getCertList 獲取證書鏈中的證書列表 無(針對已建立的證書鏈物件)
validate 校驗證書鏈 校驗引數(param,包含日期、信任錨等資訊)

總之,掌握Device Certificate Kit的API呼叫和整合是構建安全可靠鴻蒙應用的關鍵一步。透過合理使用這些API,我們能夠有效地管理證書,保障裝置之間的通訊安全。就像熟練的工匠使用各種工具打造出精美的作品一樣,開發者們也可以利用這些API打造出安全穩定的鴻蒙應用。希望大家在實際開發中多實踐、多探索,如果遇到問題,不要輕易放棄,參考文件、仔細排查,相信你一定能夠順利解決問題,讓你的應用在鴻蒙生態中綻放光彩。加油哦,各位開發者小夥伴們!

相關文章