diff --git a/zh-cn/application-dev/reference/apis/js-apis-huks.md b/zh-cn/application-dev/reference/apis/js-apis-huks.md index d43a4d0105efba5b2c84282915114bdb593c614c..497f9b584c34dbb8335308446dc1c933e9f12f0d 100755 --- a/zh-cn/application-dev/reference/apis/js-apis-huks.md +++ b/zh-cn/application-dev/reference/apis/js-apis-huks.md @@ -1773,10 +1773,12 @@ async function huksAbort() { **系统能力**:SystemCapability.Security.Huks -| 名称 | 值 | 说明 | -| ----------------------- | ---- | ------------------------------ | -| HUKS_STORAGE_TEMP | 0 | 表示通过本地直接管理密钥。 | -| HUKS_STORAGE_PERSISTENT | 1 | 表示通过HUKS service管理密钥。 | +| 名称 | 值 | 说明 | +| -------------------------------------------- | ---- | ------------------------------ | +| HUKS_STORAGE_TEMP | 0 | 表示通过本地直接管理密钥。 | +| HUKS_STORAGE_PERSISTENT | 1 | 表示通过HUKS service管理密钥。 | +| HUKS_STORAGE_ONLY_USED_IN_HUKS10+ | 2 | 表示密钥只存储在huks中。 | +| HUKS_STORAGE_KEY_EXPORT_ALLOWED10+ | 3 | 表示密钥从huks中导出,不存储。 | ## HuksSendType @@ -1812,6 +1814,17 @@ async function huksAbort() { | HUKS_KEY_TYPE_PRIVATE_KEY | 1 | 表示导入的密钥类型为私钥。 | | HUKS_KEY_TYPE_KEY_PAIR | 2 | 表示导入的密钥类型为公私钥对。 | +## HuksRsaPssSaltLenType10+ + +表示Rsa在签名验签、padding为pss时需指定的salt_len类型。 + +**系统能力**:SystemCapability.Security.Huks + +| 名称 | 值 | 说明 | +| ------------------------------------------ | ---- | ---------------------------- | +| HUKS_RSA_PSS_SALT_LEN_DIGEST10+ | 0 | 表示以摘要长度设置salt_len。 | +| HUKS_RSA_PSS_SALT_LEN_MAX10+ | 1 | 表示以最大长度设置salt_len。 | + ## HuksUserAuthType9+ 表示用户认证类型。 @@ -1920,6 +1933,8 @@ async function huksAbort() { | HUKS_TAG_DERIVE_KEY_SIZE | HuksTagType.HUKS_TAG_TYPE_UINT \| 24 | 表示派生密钥的大小。 | | HUKS_TAG_IMPORT_KEY_TYPE9+ | HuksTagType.HUKS_TAG_TYPE_UINT \| 25 | 表示导入的密钥类型。 | | HUKS_TAG_UNWRAP_ALGORITHM_SUITE9+ | HuksTagType.HUKS_TAG_TYPE_UINT \| 26 | 表示导入加密密钥的套件。 | +| HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG10+ | HuksTagType.HUKS_TAG_TYPE_UINT \|29 | 表示派生密钥/协商密钥的存储类型。 | +| HUKS_TAG_RSA_PSS_SALT_LEN_TYPE10+ | HuksTagType.HUKS_TAG_TYPE_UINT \|30 | 表示rsa_pss_salt_length的类型。 | | HUKS_TAG_ACTIVE_DATETIME(deprecated) | HuksTagType.HUKS_TAG_TYPE_ULONG \| 201 | 原为证书业务预留字段,当前证书管理已独立,此字段废弃,不再预留。 | | HUKS_TAG_ORIGINATION_EXPIRE_DATETIME(deprecated) | HuksTagType.HUKS_TAG_TYPE_ULONG \| 202 | 原为证书业务预留字段,当前证书管理已独立,此字段废弃,不再预留。 | | HUKS_TAG_USAGE_EXPIRE_DATETIME(deprecated) | HuksTagType.HUKS_TAG_TYPE_ULONG \| 203 | 原为证书业务预留字段,当前证书管理已独立,此字段废弃,不再预留。 | @@ -1934,6 +1949,7 @@ async function huksAbort() { | HUKS_TAG_KEY_SECURE_SIGN_TYPE9+ | HuksTagType.HUKS_TAG_TYPE_UINT \| 308 | 表示生成或导入密钥时,指定该密钥的签名类型。 | | HUKS_TAG_CHALLENGE_TYPE9+ | HuksTagType.HUKS_TAG_TYPE_UINT \| 309 | 表示密钥使用时生成的challenge类型。从[HuksChallengeType](#hukschallengetype9)中选择 | | HUKS_TAG_CHALLENGE_POS9+ | HuksTagType.HUKS_TAG_TYPE_UINT \| 310 | 表示challenge类型为用户自定义类型时,huks产生的challenge有效长度仅为8字节连续的数据。从[HuksChallengePosition](#hukschallengeposition9)中选择。 | +| HUKS_TAG_KEY_AUTH_PURPOSE10+ | HuksTagType.HUKS_TAG_TYPE_UINT \|311 | 表示密钥认证用途的tag | | HUKS_TAG_ATTESTATION_CHALLENGE | HuksTagType.HUKS_TAG_TYPE_BYTES \| 501 | 表示attestation时的挑战值。 | | HUKS_TAG_ATTESTATION_APPLICATION_ID | HuksTagType.HUKS_TAG_TYPE_BYTES \| 502 | 表示attestation时拥有该密钥的application的Id。 | | HUKS_TAG_ATTESTATION_ID_BRAND | HuksTagType.HUKS_TAG_TYPE_BYTES \| 503 | 表示设备的品牌。 | diff --git a/zh-cn/application-dev/security/huks-guidelines.md b/zh-cn/application-dev/security/huks-guidelines.md index 793d9cf38adf98302ac0401bf9ff4c1ee784a182..6468aeb707e7543f8eeb9f046c65a9d55aa1f15f 100644 --- a/zh-cn/application-dev/security/huks-guidelines.md +++ b/zh-cn/application-dev/security/huks-guidelines.md @@ -961,6 +961,9 @@ struct Index { ``` ### 密钥协商 + +应用在协商密钥时建议传入[HuksKeyStorageType](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。 + ```ts /* * 以下以X25519 256 TEMP密钥的Callback操作使用为例 @@ -1005,6 +1008,10 @@ properties[5] = { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_CBC, } +properties[6] = { + tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, + value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, +} let HuksOptions = { properties: properties, inData: new Uint8Array(new Array()) @@ -1013,8 +1020,8 @@ let HuksOptions = { /* 集成第一个协商参数集 */ let finishProperties = new Array(); finishProperties[0] = { - tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG, - value: huks.HuksKeyStorageType.HUKS_STORAGE_TEMP, + tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, + value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, } finishProperties[1] = { tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, @@ -1325,6 +1332,9 @@ async function testAgree() { ``` ### 密钥派生 + +应用在派生密钥时建议传入[HuksKeyStorageType](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。 + ```ts /* * 以下以HKDF256密钥的Promise操作使用为例 @@ -1358,6 +1368,10 @@ properties[3] = { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128, } +properties[4] = { + tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, + value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, +} let huksOptions = { properties: properties, inData: new Uint8Array(new Array()) @@ -1389,8 +1403,8 @@ let initOptions = { /* 集成finish时密钥参数集 */ let finishProperties = new Array(); finishProperties[0] = { - tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG, - value: huks.HuksKeyStorageType.HUKS_STORAGE_PERSISTENT, + tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, + value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, } finishProperties[1] = { tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, @@ -1649,7 +1663,7 @@ HUKS提供了全面完善的密钥访问控制能力,确保存储在HUKS中的 其次,支持密钥的用户身份认证访问控制,对于高安敏感的业务密钥,需要在使用密钥的时候,再次要求用户即时的验证锁屏密码或生物特征,验证通过后,才能使用业务密钥。 除此之外,HUKS还支持严格限制密钥的使用用途,如支持只允许AES密钥进行加密解密,只允许RSA密钥进行签名验签。 -**用户身份认证访问控制** +### 用户身份认证访问控制 生成或导入密钥时,可以指定密钥必须经过用户身份认证后才能使用。您可以指定用于解锁设备锁屏的凭据(锁屏密码、指纹、人脸)的子集进行身份认证。在生成/导入密钥后,即使应用进程被攻击也不会导致未经用户授权的密钥访问,一般用于高敏感且高级别安全保护的场景,比如免密登录、免密支付、自动填充密码保护场景。 @@ -2073,6 +2087,446 @@ async function testSm4Cipher() { } ``` +### 细粒度用户身份认证访问控制 + +该功能是基于已有[密钥访问控制](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-guidelines.md#%E5%AF%86%E9%92%A5%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6)能力的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。比如,业务需要使用HUKS密钥加密保存账号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。 + +**开发流程** +1. 基于用户身份认证访问控制的流程,在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukstag)值,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。 +2. 基于用户身份认证访问控制的流程,在密钥使用阶段,业务无需再次指定HUKS_TAG_KEY_AUTH_PURPOSE值,同用户身份认证访问控制的开发流程。 + +**接口说明** + +新增用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukstag),该Tag值取值范围为枚举类[HuksKeyAlg](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukskeyalg)。 + +**表8** 细粒度用户身份认证访问控制Tag类型介绍 +| 名称 | 描述 | +| -------------------------------------- | ----------------------------| +|HUKS_TAG_KEY_AUTH_PURPOSE| 表示密钥认证用途的tag,用于设置某种算法用途下需要用户身份认证访问控制| + +**注意** +1. 当业务未指定用户认证类型[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示默认都不需要用户身份认证访问控制能力,则此时设置HUKS_TAG_KEY_AUTH_PURPOSE是默认无效的; 当业务指定了[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示需要用户身份认证访问控制能力,此时若不设置HUKS_TAG_KEY_AUTH_PURPOSE值,则生成密钥阶段指定的算法用途在密钥使用时都默认需要进行用户身份认证访问控制。 +2. 当指定的算法是对称算法AES和SM4时,且同时指定用于加解密用途,则只允许设置CBC模式,其它模式不支持细粒度用户身份认证访问控制能力。 + +**开发步骤** + +示例场景:密钥生成阶段,生成用于加解密的密钥并指定只有解密的时候需要用户身份认证访问控制;密钥使用阶段,加密时不需要用户身份认证访问控制,解密时需要用户身份认证访问控制 + +1. 生成密钥并指定指纹访问控制和相关属性,以及HUKS_TAG_KEY_AUTH_PURPOSE值 +```ts +import huks from '@ohos.security.huks'; + +/* + * 确定密钥别名和封装密钥属性参数集 + */ +let keyAlias = 'dh_key_fingerprint_access'; +let properties = new Array(); +properties[0] = { + tag: huks.HuksTag.HUKS_TAG_ALGORITHM, + value: huks.HuksKeyAlg.HUKS_ALG_SM4, +} +properties[1] = { + tag: huks.HuksTag.HUKS_TAG_PURPOSE, + value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, +} +properties[2] = { + tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, + value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, +} +properties[3] = { + tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, + value: huks.HuksCipherMode.HUKS_MODE_CBC, +} +properties[4] = { + tag: huks.HuksTag.HUKS_TAG_PADDING, + value: huks.HuksKeyPadding.HUKS_PADDING_NONE, +} +// 指定密钥身份认证的类型:指纹 +properties[5] = { + tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, + value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT +} +// 指定密钥安全授权的类型(失效类型):新录入生物特征(指纹)后无效 +properties[6] = { + tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, + value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL +} +// 指定挑战值的类型:默认类型 +properties[7] = { + tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, + value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL +} +// 指定某种算法用途时需要用户身份认证访问控制:比如解密需要 +properties[8] = { + tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE, + value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT +} +let huksOptions = { + properties: properties, + inData: new Uint8Array(new Array()) +} + +/* + * 生成密钥 + */ +async function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) { + return new Promise((resolve, reject) => { + try { + huks.generateKeyItem(keyAlias, huksOptions, function (error, data) { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + } catch (error) { + throwObject.isThrow = true; + throw(error); + } + }); +} + +async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { + console.info(`enter callback generateKeyItem`); + let throwObject = {isThrow: false}; + try { + await generateKeyItem(keyAlias, huksOptions, throwObject) + .then((data) => { + console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); + }) + .catch(error => { + if (throwObject.isThrow) { + throw(error); + } else { + console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`); + } + }); + } catch (error) { + console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`); + } +} + +async function TestGenKeyForFingerprintAccessControl() { + await publicGenKeyFunc(keyAlias, huksOptions); +} +``` + +2. 使用密钥-加密场景-加密时不需要进行用户身份认证访问控制 +```ts +import huks from '@ohos.security.huks'; + +/* + * 确定密钥别名和封装密钥属性参数集 + */ +let srcKeyAlias = 'sm4_key_fingerprint_access'; +let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据 +let IV = '1234567890123456'; +let handle; +let cipherText; // 加密后的密文数据 + +function StringToUint8Array(str) { + let arr = []; + for (let i = 0, j = str.length; i < j; ++i) { + arr.push(str.charCodeAt(i)); + } + return new Uint8Array(arr); +} + +/* 集成生成密钥参数集 & 加密参数集 */ +let propertiesEncrypt = new Array(); +propertiesEncrypt[0] = { + tag: huks.HuksTag.HUKS_TAG_ALGORITHM, + value: huks.HuksKeyAlg.HUKS_ALG_SM4, +} +propertiesEncrypt[1] = { + tag: huks.HuksTag.HUKS_TAG_PURPOSE, + value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, +} +propertiesEncrypt[2] = { + tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, + value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, +} +propertiesEncrypt[3] = { + tag: huks.HuksTag.HUKS_TAG_PADDING, + value: huks.HuksKeyPadding.HUKS_PADDING_NONE, +} +propertiesEncrypt[4] = { + tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, + value: huks.HuksCipherMode.HUKS_MODE_CBC, +} +propertiesEncrypt[5] = { + tag: huks.HuksTag.HUKS_TAG_IV, + value: StringToUint8Array(IV), +} +let encryptOptions = { + properties: propertiesEncrypt, + inData: new Uint8Array(new Array()) +} + +function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise { + return new Promise((resolve, reject) => { + try { + huks.initSession(keyAlias, huksOptions, function (error, data) { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + } catch (error) { + throwObject.isThrow = true; + throw(error); + } + }); +} + +async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { + console.info(`enter callback doInit`); + let throwObject = {isThrow: false}; + try { + await initSession(keyAlias, huksOptions, throwObject) + .then ((data) => { + console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); + handle = data.handle; + }) + .catch((error) => { + if (throwObject.isThrow) { + throw(error); + } else { + console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`); + } + }); + } catch (error) { + console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`); + } +} + +function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise { + return new Promise((resolve, reject) => { + try { + huks.finishSession(handle, huksOptions, function (error, data) { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + } catch (error) { + throwObject.isThrow = true; + throw(error); + } + }); +} + +async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) { + console.info(`enter callback doFinish`); + let throwObject = {isThrow: false}; + try { + await finishSession(handle, huksOptions, throwObject) + .then ((data) => { + cipherText = data.outData; + console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); + }) + .catch(error => { + if (throwObject.isThrow) { + throw(error); + } else { + console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`); + } + }); + } catch (error) { + console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`); + } +} + +async function testSm4Cipher() { + /* 初始化密钥会话获取挑战值 */ + await publicInitFunc(srcKeyAlias, encryptOptions); + + /* 加密 */ + encryptOptions.inData = StringToUint8Array(cipherInData); + await publicFinishFunc(handle, encryptOptions); +} +``` + +3. 使用密钥-解密场景-解密时需要进行用户身份认证访问控制 +```ts +import huks from '@ohos.security.huks'; +import userIAM_userAuth from '@ohos.userIAM.userAuth'; + +/* + * 确定密钥别名和封装密钥属性参数集 + */ +let srcKeyAlias = 'sm4_key_fingerprint_access'; +let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // 加密时得到的密文数据, 业务需根据实际加密结果修改 +let IV = '1234567890123456'; +let handle; +let finishOutData; // 解密后的明文数据 +let fingerAuthToken; +let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; +let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; + +function StringToUint8Array(str) { + let arr = []; + for (let i = 0, j = str.length; i < j; ++i) { + arr.push(str.charCodeAt(i)); + } + return new Uint8Array(arr); +} + +/* 集成生成密钥参数集 & 加密参数集 */ +let propertiesDecrypt = new Array(); +propertiesDecrypt[0] = { + tag: huks.HuksTag.HUKS_TAG_ALGORITHM, + value: huks.HuksKeyAlg.HUKS_ALG_SM4, +} +propertiesDecrypt[1] = { + tag: huks.HuksTag.HUKS_TAG_PURPOSE, + value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, +} +propertiesDecrypt[2] = { + tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, + value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, +} +propertiesDecrypt[3] = { + tag: huks.HuksTag.HUKS_TAG_PADDING, + value: huks.HuksKeyPadding.HUKS_PADDING_NONE, +} +propertiesDecrypt[4] = { + tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, + value: huks.HuksCipherMode.HUKS_MODE_CBC, +} +propertiesDecrypt[5] = { + tag: huks.HuksTag.HUKS_TAG_IV, + value: StringToUint8Array(IV), +} +let decryptOptions = { + properties: propertiesDecrypt, + inData: new Uint8Array(new Array()) +} + +function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise { + return new Promise((resolve, reject) => { + try { + huks.initSession(keyAlias, huksOptions, function (error, data) { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + } catch (error) { + throwObject.isThrow = true; + throw(error); + } + }); +} + +async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { + console.info(`enter callback doInit`); + let throwObject = {isThrow: false}; + try { + await initSession(keyAlias, huksOptions, throwObject) + .then ((data) => { + console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); + handle = data.handle; + challenge = data.challenge; + }) + .catch((error) => { + if (throwObject.isThrow) { + throw(error); + } else { + console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`); + } + }); + } catch (error) { + console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`); + } +} + +function userIAMAuthFinger(huksChallenge:Uint8Array) { + // 获取认证对象 + let auth; + try { + auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel); + console.log("get auth instance success"); + } catch (error) { + console.log("get auth instance failed" + error); + } + + // 订阅认证结果 + try { + auth.on("result", { + callback: (result: userIAM_userAuth.AuthResultInfo) => { + /* 认证成功获取认证令牌 */ + fingerAuthToken = result.token; + } + }); + console.log("subscribe authentication event success"); + } catch (error) { + console.log("subscribe authentication event failed " + error); + } + + // 开始认证 + try { + auth.start(); + console.info("authV9 start auth success"); + } catch (error) { + console.info("authV9 start auth failed, error = " + error); + } +} + +function finishSession(handle:number, huksOptions:huks.HuksOptions, token:Uint8Array, throwObject) : Promise { + return new Promise((resolve, reject) => { + try { + huks.finishSession(handle, huksOptions, token, function (error, data) { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + } catch (error) { + throwObject.isThrow = true; + throw(error); + } + }); +} + +async function publicFinishFunc(handle:number, token:Uint8Array, huksOptions:huks.HuksOptions) { + console.info(`enter callback doFinish`); + let throwObject = {isThrow: false}; + try { + await finishSession(handle, huksOptions, token, throwObject) + .then ((data) => { + finishOutData = data.outData; + console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); + }) + .catch(error => { + if (throwObject.isThrow) { + throw(error); + } else { + console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`); + } + }); + } catch (error) { + console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`); + } +} + +async function testSm4Cipher() { + /* 初始化密钥会话获取挑战值 */ + await publicInitFunc(srcKeyAlias, decryptOptions); + + /* 调用userIAM进行身份认证 */ + userIAMAuthFinger(challenge); + + /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */ + decryptOptions.inData = StringToUint8Array(cipherText); + await publicFinishFunc(handle, fingerAuthToken, decryptOptions); +} +``` + ## 密钥证明 HUKS为密钥提供合法性证明能力,主要应用于非对称密钥的公钥的证明。基于PKI证书链技术,HUKS可以为存储在HUKS中的非对称密钥对的公钥签发证书,证明其公钥的合法性。业务可以通过OpenHarmony提供的根CA证书,逐级验证HUKS签发的密钥证明证书,来确保证书中的公钥以及对应的私钥,确实来自合法的硬件设备,且存储管理在HUKS中。 @@ -2084,7 +2538,7 @@ HUKS为密钥提供合法性证明能力,主要应用于非对称密钥的公 **接口说明** -**表7** 密钥认证接口介绍 +**表8** 密钥认证接口介绍 | 接口名 | 描述 | | -------------------------------------- | ----------------------------| |attestKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\) : void| 密钥认证| diff --git a/zh-cn/release-notes/changelogs/OpenHarmony_4.0.7.1/changelog-huks.md b/zh-cn/release-notes/changelogs/OpenHarmony_4.0.7.1/changelog-huks.md new file mode 100755 index 0000000000000000000000000000000000000000..7d075b26a0a989fafe1c979975ffb8acb921d157 --- /dev/null +++ b/zh-cn/release-notes/changelogs/OpenHarmony_4.0.7.1/changelog-huks.md @@ -0,0 +1,98 @@ +# HUKS子系统ChangeLog + +## cl.huks.1 HUKS支持可选设置rsa_pss_salt_length类型 + +变更之前,应用在签名/验签时,HUKS默认使用RSA_PSS_SALT_LEN_MAX进行处理; + +变更之后,应用在签名/验签需传入HuksRsaPssSaltLenType中定义的类型。若不传入,则默认使用RSA_PSS_SALT_LEN_MAX进行处理。 + +**变更影响** + +影响已发布的JS接口,接口行为发生变更。 + +**关键的接口/组件变更** + +发布的JS接口不变, 传入接口的参数集合发生变更。 + +**适配指导** + +以RSA签名为例,示例代码如下: + +```js +import huks from '@ohos.security.huks'; + +let keyAlias = 'rsa_Key'; +let inData = new Uint8Array( + 0x4B, 0x1E, 0x22, 0x64, 0xA9, 0x89, 0x60, 0x1D, 0xEC, 0x78, 0xC0, 0x5D, 0xBE, 0x46, 0xAD, 0xCF, + 0x1C, 0x35, 0x16, 0x11, 0x34, 0x01, 0x4E, 0x9B, 0x7C, 0x00, 0x66, 0x0E, 0xCA, 0x09, 0xC0, 0xF3, +); +/* 签名参数 */ +let signProperties = new Array(); +signProperties[0] = { + tag: huks.HuksTag.HUKS_TAG_ALGORITHM, + value: huks.HuksKeyAlg.HUKS_ALG_RSA, +} +signProperties[1] = { + tag: huks.HuksTag.HUKS_TAG_PURPOSE, + value: + huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN +} +signProperties[2] = { + tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, + value: huks.HuksKeySize.HUKS_RSA_KEY_SIZE_2048, +} +signProperties[3] = { + tag: huks.HuksTag.HUKS_TAG_PADDING, + value: huks.HuksKeyPadding.HUKS_PADDING_PSS, +} +signProperties[4] = { + tag: huks.HuksTag.HUKS_TAG_DIGEST, + value: huks.HuksKeyDigest.HUKS_DIGEST_SHA1, +} +signProperties[5] = { + tag: huks.HuksTag.HUKS_TAG_RSA_PSS_SALT_LEN_TYPE, + value: huks.HuksRsaPssSaltLenType.HUKS_RSA_PSS_SALT_LEN_MAX, +} +let signOptions = { + properties: signProperties, + inData: inData +} + +huks.initSession(keyAlias, signOptions); +``` + +更多接口的示例代码可参考[HUKS-guidelines](../../../application-dev/security/huks-guidelines.md)和[HUKS API](../../../application-dev/reference/apis/js-apis-huks.md)。 + +## cl.huks.2 HUKS解决派生密钥/协商密钥的存储/导出问题 + +变更之前,派生密钥/协商密钥既支持存储,又支持导出,存在安全风险; + +变更之后,应用在派生密钥/协商密钥时需传入HuksKeyStorageType中定义的类型。应用只能选择存储,或者选择导出。若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。 + +**变更影响** + +影响已发布的JS接口,接口行为发生变更。 + +**关键的接口/组件变更** + +发布的JS接口不变, 传入接口的参数集合发生变更。 + +**适配指导** + +接口使用的示例代码可参考[HUKS-guidelines](../../../application-dev/security/huks-guidelines.md)和[HUKS API](../../../application-dev/reference/apis/js-apis-huks.md)。 + +## cl.huks.3 新增用于细粒度用户身份访问控制的Tag + +新增用于细粒度用户身份访问控制的HuksTag: HUKS_TAG_KEY_AUTH_PURPOSE,业务可在原有用户身份访问控制能力上,选择某种特定算法用途下需要用户身份访问控制能力。 + +**变更影响** + +新增的HuksTag,不影响已有的接口。 + +**关键的接口/组件变更** + +只新增了HuksTag: HUKS_TAG_KEY_AUTH_PURPOSE, 用于支持细粒度用户身份访问控制。 + +**适配指导** + +接口使用的示例代码可参考[密钥访问控制_细粒度用户身份认证访问控制](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-guidelines.md#%E5%AF%86%E9%92%A5%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6),接口定义参考[HuksTag](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#hukstag)。 \ No newline at end of file