Merge branch 'master' of https://gitee.com/openharmony/applications_app_samples
@ -8,6 +8,9 @@ This sample shows how `@ohos.security.huks` works to implement encryption and de
|
||||
|
||||
2. Using an old key for message encryption and decryption transmission: Import an old key using HUKS' import key interface to simulate the scenario of encrypting the sent message on the old device and decrypting the received message on the new device.
|
||||
|
||||
3. Click the **Minimum Access Control** button on the main page, enter the password to be saved in the input box of the new key interface, and click ** Save password **
|
||||
Button, after entering the PIN code, the encrypted password content will be displayed in the lower text box, and then click ** Read Password ** button, and the decrypted message content will be displayed in the lower text box.
|
||||
|
||||
### Usage
|
||||
|
||||
1. Click the **New Key** button on the main page, enter the message content to be sent in the input box of the new key interface, and click **Send Message**
|
||||
@ -15,12 +18,13 @@ button, the encrypted message content will be displayed in the text box below, a
|
||||
2. Click the **Back** button in the upper left corner to return to the main interface.
|
||||
3. Click on the **Old Key** button on the main page, enter the message content to be sent in the input box of the old key interface, and click **Send Message**
|
||||
button, the encrypted message content will be displayed in the text box below. First, click the **Import Key** button, and a pop-up window will prompt that the key was successfully imported. Then, click the **Receive Message** button, and the decrypted message content will be displayed in the text box below.
|
||||
4. Click the **Back** button in the upper left corner to return to the main interface.
|
||||
4. Click the **Minimum Access Control** button on the main page, enter the message content to be sent in the input box of the new key interface, and click **Save Password**
|
||||
button, the encrypted password content will be displayed in the text box below, and then click the **Read Password** button. After entering the PIN code, the decrypted password content will be displayed in the text box below.
|
||||
|
||||
### Constraints
|
||||
|
||||
1. This sample can only be run on standard-system devices.
|
||||
|
||||
2. This sample has been adapted to the API version 9 SDK, version number 3.2.11.9.
|
||||
2. This sample has been adapted to the API version 10 SDK (4.0.10.1).
|
||||
|
||||
3. This sample requires DevEco Studio 3.1 Canary1 (Build Version: 3.1.0.400) to compile and run.
|
||||
3. This sample requires DevEco Studio 3.1.1 Release (Build Version: 3.1.0.501) to compile and run.
|
@ -10,23 +10,24 @@
|
||||
|
||||
2)使用旧密钥进行消息加解密传输:使用HUKS的导入密钥接口导入一个旧密钥,模拟在旧设备上对发送的消息进行加密,在新设备上对接收的消息进行解密的场景。
|
||||
|
||||
3)使用低安访问控制进行密码加解密:使用HUKS的生成密钥接口在本地生成一个新密钥,模拟设备对密码进行加密和对接收的密码进行解密场景。
|
||||
|
||||
### 效果预览
|
||||
|
||||
|主页| 使用新密钥消息加解密页面 | 使用旧密钥消息加解密页面 |
|
||||
|--------------------------------|--------------------|------------------------------------|
|
||||
|![](screenshots/device/index.png)| ![](screenshots/device/newKey.png) | ![](screenshots/device/oldKey.png) |
|
||||
| 主页 | 使用新密钥消息加解密页面 | 使用旧密钥消息加解密页面 | 使用低安访问控制保存/读取密码 |
|
||||
|-----------------------------------|--------------------|------------------------------------|----------------------------------------------|
|
||||
| ![](screenshots/device/index.png) | ![](screenshots/device/newKey.png) | ![](screenshots/device/oldKey.png) | ![](screenshots/device/minAccessControl.png) |
|
||||
|
||||
使用说明
|
||||
|
||||
1.点击主页面的**新密钥**按钮,在新密钥界面的输入框中输入待发送的消息内容,点击**发送消息**
|
||||
按钮,下方文本框中显示加密后的消息内容,然后点击**接收消息**按钮,下方文本框中显示解密后的消息内容。
|
||||
|
||||
2.点击左上方**返回**按钮,返回主界面。
|
||||
|
||||
3.点击主页面的**旧密钥**按钮,在旧密钥界面的输入框中输入待发送的消息内容,点击**发送消息**
|
||||
2.点击主页面的**旧密钥**按钮,在旧密钥界面的输入框中输入待发送的消息内容,点击**发送消息**
|
||||
按钮,下方文本框中显示加密后的消息内容,首先点击**导入密钥**按钮,弹窗提示导入密钥成功,然后点击**接收消息**按钮,下方文本框中显示解密后的消息内容。
|
||||
|
||||
4.点击左上方**返回**按钮,返回主界面。
|
||||
3.点击主页面的**低安访问控制**按钮,在新密钥界面的输入框中输入待保存的密码内容,点击**保存密码**
|
||||
按钮,下方文本框中显示加密后的密码内容,录入锁屏密码, 然后点击**读取密码**按钮,在输入PIN码(锁屏密码)之后,下方文本框中显示解密后的消息内容。
|
||||
|
||||
### 工程目录
|
||||
|
||||
@ -35,6 +36,7 @@ entry/src/main/ets/
|
||||
|---common
|
||||
| |---NewKey.ets // 新密钥组件
|
||||
| |---OldKey.ets // 旧密钥组件
|
||||
| |---MinAccessControl.ets // 低安访问控制组件
|
||||
|---entryability
|
||||
| |---EntryAbility.ts
|
||||
|---model
|
||||
@ -47,7 +49,7 @@ entry/src/main/ets/
|
||||
|
||||
### 具体实现
|
||||
|
||||
* 使用新密钥和旧密钥进行消息的加密和解密的功能接口封装在HuksModel中,源码参考:[HuksModel.ts](entry/src/main/ets/model/HuksModel.ts)
|
||||
* 使用新密钥、旧密钥与低安访问控制进行消息的加密和解密的功能接口封装在HuksModel中,源码参考:[HuksModel.ts](entry/src/main/ets/model/HuksModel.ts)
|
||||
* 使用新密钥加密:在[NewKey.ets](entry/src/main/ets/common/NewKey.ets)文件中通过HuksModel.encryptData方式调用加密函数实现对发送的消息内容进行加密,设置好生成密钥和解密密钥的密钥属性信息,加密前会先调用生成密钥接口
|
||||
[huks.generateKeyItem](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#huksgeneratekeyitem9-1)
|
||||
生成用于加密的密钥,对消息加密的过程中采用三段式接口[huks.initSession,huks.updateSession,huks.finishSession](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#huksinitsession9-1)
|
||||
@ -56,10 +58,12 @@ entry/src/main/ets/
|
||||
[huks.deleteKeyItem](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-huks.md#huksdeletekeyitem9-1)清除本地保存的密钥。
|
||||
* 使用旧密钥加密:在[OldKey.ets](entry/src/main/ets/common/OldKey.ets)文件中通过HuksModel.encryptDataUserOldKey方式调用加密函数对发送的消息内容进行加密,设置好加密密钥的密钥属性信息,采用三段式接口使用本地已保存的旧密钥完成加密操作。
|
||||
* 使用旧密钥解密:在[OldKey.ets](entry/src/main/ets/common/OldKey.ets)文件中通过HuksModel.decryptDataUserOldKey方式调用解密函数对发送的消息内容进行解密,首先模拟在新设备上导入旧设备的加密密钥,同样采用三段式接口完成解密操作,解密完成后删除密钥。
|
||||
* 使用低安访问控制管理密码:在[MinAccessControl.ets](entry/src/main/ets/common/MinAccessControl.ets)文件中通过 huksModel.encryptDataUseSm2 方式调用加密函数对发送的消息内容进行加密,设置好加密密钥的密钥属性信息,采用三段式接口使用本地已保存的旧密钥完成加密操作。读取密码时(需先设定系统锁屏密码)调用IAM的PIN码(锁屏密码)接口进行验证。
|
||||
|
||||
|
||||
### 相关权限
|
||||
|
||||
不涉及。
|
||||
ohos.permission.ACCESS_BIOMETRIC
|
||||
|
||||
### 依赖
|
||||
|
||||
@ -69,9 +73,9 @@ entry/src/main/ets/
|
||||
|
||||
1.本示例仅支持标准系统上运行。
|
||||
|
||||
2.本示例已适配API version 9版本SDK,版本号:3.2.11.9。
|
||||
2.本示例已适配API version 10 版本SDK,版本号:4.0.10.1。
|
||||
|
||||
3.本示例需要使用DevEco Studio 3.1 Canary1 (Build Version: 3.1.0.400)及以上版本才可编译运行。
|
||||
3.本示例需要使用DevEco Studio 3.1.1 Release (Build Version: 3.1.0.501)及以上版本才可编译运行。
|
||||
|
||||
### 下载
|
||||
|
||||
|
@ -16,12 +16,12 @@
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [],
|
||||
"compileSdkVersion": 9,
|
||||
"compatibleSdkVersion": 9,
|
||||
"compileSdkVersion": 10,
|
||||
"compatibleSdkVersion": 10,
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"signingConfig": "default"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -19,7 +19,8 @@
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
"name": "default",
|
||||
"runtimeOS": "OpenHarmony"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
|
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import prompt from '@ohos.prompt'
|
||||
import Logger from '../model/Logger'
|
||||
import { HuksModel } from '../model/HuksModel'
|
||||
|
||||
const TAG: string = '[HUKS]'
|
||||
|
||||
@Component
|
||||
export struct MinAccessControl {
|
||||
@State cipherTextinfo: string = ''
|
||||
@State plainTextinfo: string = ''
|
||||
@State inputPassword: string = ''
|
||||
huksModel: HuksModel = new HuksModel()
|
||||
|
||||
build() {
|
||||
Stack({ alignContent: Alignment.Center }) {
|
||||
Column() {
|
||||
GridRow() {
|
||||
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
List() {
|
||||
ListItem() {
|
||||
Row() {
|
||||
Text($r('app.string.input_save_password'))
|
||||
.fontSize(16)
|
||||
.textAlign(TextAlign.Start)
|
||||
.lineHeight(22)
|
||||
}
|
||||
.backgroundColor(0xFFFFFF)
|
||||
.width('100%')
|
||||
.height('52vp')
|
||||
.padding({ top: 4, left: 12, right: 12 })
|
||||
}
|
||||
|
||||
ListItem() {
|
||||
Row() {
|
||||
TextInput()
|
||||
.enableKeyboardOnFocus(false)
|
||||
.margin(4)
|
||||
.width('90%')
|
||||
.id('passwordInput')
|
||||
.fontSize(16)
|
||||
.textAlign(TextAlign.Start)
|
||||
.onChange((value: string) => {
|
||||
this.inputPassword = value
|
||||
})
|
||||
}
|
||||
.backgroundColor(0xFFFFFF)
|
||||
.width('100%')
|
||||
.height('48vp')
|
||||
.padding({ left: 12, right: 12 })
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.borderRadius(16)
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('100vp')
|
||||
.margin({ left: 12, right: 12, bottom: 12 })
|
||||
|
||||
GridRow() {
|
||||
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Column() {
|
||||
Row() {
|
||||
Text($r('app.string.cipher_text'))
|
||||
.fontSize(16)
|
||||
.textAlign(TextAlign.Start)
|
||||
.fontWeight(500)
|
||||
.lineHeight(22)
|
||||
}
|
||||
.padding({ left: 12, right: 12 })
|
||||
.width('100%')
|
||||
.height('48vp')
|
||||
|
||||
Row() {
|
||||
Text() {
|
||||
Span(this.cipherTextinfo)
|
||||
.fontSize(16)
|
||||
.fontWeight(400)
|
||||
.fontColor(0x808080)
|
||||
.fontColor('#182431')
|
||||
}.textAlign(TextAlign.Start)
|
||||
.id('cipherTextinfo')
|
||||
}
|
||||
.padding({ left: 12, right: 12, bottom: 4 })
|
||||
.width('100%')
|
||||
.height('52vp')
|
||||
}
|
||||
.borderRadius(16)
|
||||
.width('100%')
|
||||
.height('100')
|
||||
.backgroundColor(0xFFFFFF)
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('100vp')
|
||||
.margin({ left: 12, right: 12, bottom: 12 })
|
||||
|
||||
GridRow() {
|
||||
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Column() {
|
||||
Row() {
|
||||
Text($r('app.string.plain_text'))
|
||||
.fontSize(16)
|
||||
.textAlign(TextAlign.Start)
|
||||
.fontWeight(500)
|
||||
.lineHeight(22)
|
||||
}
|
||||
.padding({ left: 12, right: 12 })
|
||||
.width('100%')
|
||||
.height('48vp')
|
||||
|
||||
Row() {
|
||||
Text() {
|
||||
Span(this.plainTextinfo)
|
||||
.fontSize(16)
|
||||
.fontWeight(400)
|
||||
.fontColor(0x808080)
|
||||
.fontColor('#182431')
|
||||
}.textAlign(TextAlign.Start)
|
||||
.id('plainTextinfo')
|
||||
}
|
||||
.padding({ left: 12, right: 12, bottom: 4 })
|
||||
.width('100%')
|
||||
.height('52vp')
|
||||
}
|
||||
.borderRadius(16)
|
||||
.width('100%')
|
||||
.height('100')
|
||||
.backgroundColor(0xFFFFFF)
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('100vp')
|
||||
.margin({ left: 12, right: 12, bottom: 12 })
|
||||
|
||||
Column() {
|
||||
GridRow() {
|
||||
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
|
||||
Column() {
|
||||
Button() {
|
||||
Text($r('app.string.save_password')).fontSize(16).fontWeight(500)
|
||||
.lineHeight(22)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
.id('save_password')
|
||||
.borderRadius(20)
|
||||
.type(ButtonType.Capsule)
|
||||
.width('100%')
|
||||
.height('40vp')
|
||||
.margin({ bottom: 16 })
|
||||
.backgroundColor('#007DFF')
|
||||
.onClick(() => {
|
||||
if (this.inputPassword === '') {
|
||||
prompt.showToast({
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.encryptDataUseSm2(this.inputPassword, (result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.cipherTextinfo = `${result}`
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.read_password')).fontSize(16).fontWeight(500)
|
||||
.lineHeight(22)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
.borderRadius(20)
|
||||
.id('read_password')
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({ left: 24, right: 24 })
|
||||
.width('100%')
|
||||
.height('40vp')
|
||||
.backgroundColor('#007DFF')
|
||||
.onClick(() => {
|
||||
|
||||
if (this.inputPassword === '') {
|
||||
prompt.showToast({
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.decryptDataUseSm2((result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.plainTextinfo = `${result}`
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}.margin({ left: 24, right: 24 })
|
||||
}.width('100%').height('296vp').justifyContent(FlexAlign.End)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ export struct NewKey {
|
||||
Stack({alignContent:Alignment.Center}) {
|
||||
Column() {
|
||||
Text($r('app.string.input_message')).fontSize(20).margin({ left: 1, top:1 })
|
||||
TextArea()
|
||||
TextInput()
|
||||
.enableKeyboardOnFocus(false)
|
||||
.margin(4)
|
||||
.width('90%')
|
||||
.id('encryptionInput')
|
||||
@ -51,7 +52,7 @@ export struct NewKey {
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.encryptData(this.message, (result) => {
|
||||
this.huksModel.encryptData(this.message, (result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.cipherTextinfo = `${result}`
|
||||
})
|
||||
@ -80,7 +81,7 @@ export struct NewKey {
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.decryptData((result) => {
|
||||
this.huksModel.decryptData((result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.plainTextinfo = `${result}`
|
||||
})
|
||||
|
@ -30,7 +30,8 @@ export struct OldKey {
|
||||
Stack({alignContent:Alignment.Center}) {
|
||||
Column() {
|
||||
Text($r('app.string.input_message')).fontSize(20).margin({ left: 1, top:1 })
|
||||
TextArea()
|
||||
TextInput()
|
||||
.enableKeyboardOnFocus(false)
|
||||
.margin(4)
|
||||
.width('90%')
|
||||
.id('encryptionInput')
|
||||
@ -51,7 +52,7 @@ export struct OldKey {
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.encryptDataUserOldKey(this.message, (result) => {
|
||||
this.huksModel.encryptDataUserOldKey(this.message, (result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.cipherTextInfo = `${result}`
|
||||
})
|
||||
@ -80,7 +81,7 @@ export struct OldKey {
|
||||
message: 'This message is null.'
|
||||
})
|
||||
} else {
|
||||
this.huksModel.decryptDataUserOldKey((result) => {
|
||||
this.huksModel.decryptDataUserOldKey((result: string) => {
|
||||
Logger.info(TAG, `this result = ${result}`)
|
||||
this.plainTextInfo = `${result}`
|
||||
})
|
||||
|
@ -15,13 +15,15 @@
|
||||
|
||||
import util from '@ohos.util';
|
||||
import huks from '@ohos.security.huks';
|
||||
import userAuth from '@ohos.userIAM.userAuth';
|
||||
import promptAction from '@ohos.promptAction';
|
||||
import Logger from './Logger';
|
||||
|
||||
const TAG: string = '[HUKS]';
|
||||
|
||||
const CHALLENG_LEN = 6;
|
||||
const IV: string = '001122334455';
|
||||
let cipherData:Uint8Array;
|
||||
let challengeNew = new Uint8Array(CHALLENG_LEN);
|
||||
|
||||
// 密钥明文
|
||||
let PLAIN_TEXT_SIZE_16 = new Uint8Array([
|
||||
@ -37,6 +39,69 @@ function stringToUint8Array(str: string): Uint8Array {
|
||||
return new Uint8Array(arr);
|
||||
}
|
||||
|
||||
// 生成Sm2密钥属性信息
|
||||
function getSm2GenerateProperties(properties): void {
|
||||
let index = 0;
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
|
||||
value: huks.HuksKeyAlg.HUKS_ALG_SM2
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
|
||||
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
|
||||
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
|
||||
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// Sm2加密密钥属性信息
|
||||
function getSm2EncryptProperties(properties): void {
|
||||
let index = 0;
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
|
||||
value: huks.HuksKeyAlg.HUKS_ALG_SM2
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
|
||||
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
|
||||
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_DIGEST,
|
||||
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// Sm2解密密钥属性信息
|
||||
function getSm2DecryptProperties(properties): void {
|
||||
let index = 0;
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
|
||||
value: huks.HuksKeyAlg.HUKS_ALG_SM2
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
|
||||
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
|
||||
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
|
||||
};
|
||||
properties[index++] = {
|
||||
tag: huks.HuksTag.HUKS_TAG_DIGEST,
|
||||
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
function uint8ArrayToString(fileData): string {
|
||||
let dataString = '';
|
||||
for (let i = 0; i < fileData.length; i++) {
|
||||
@ -261,6 +326,7 @@ export class HuksModel {
|
||||
let emptyOptions = {
|
||||
properties: []
|
||||
};
|
||||
|
||||
await huks.initSession(aesKeyAlias, options).then((data) => {
|
||||
Logger.info(TAG, `decrypt initSession success, data: ${JSON.stringify(data)}`);
|
||||
handle = data.handle;
|
||||
@ -284,6 +350,115 @@ export class HuksModel {
|
||||
});
|
||||
}
|
||||
|
||||
// 模拟使用Sm2 生成密钥并进行加密
|
||||
async encryptDataUseSm2(plainText: string, resultCallback): Promise<void> {
|
||||
let sm2KeyAlias = 'test_sm2KeyAlias';
|
||||
let handle;
|
||||
let generateKeyProperties = new Array();
|
||||
getSm2GenerateProperties(generateKeyProperties);
|
||||
let generateKeyOptions = {
|
||||
properties: generateKeyProperties
|
||||
};
|
||||
await huks.generateKeyItem(sm2KeyAlias, generateKeyOptions).then((data) => {
|
||||
Logger.info(TAG, `generate key success, data: ${JSON.stringify(data)}`);
|
||||
}).catch((err)=>{
|
||||
Logger.error(TAG, `generate key failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`);
|
||||
});
|
||||
|
||||
let encryptProperties = new Array();
|
||||
getSm2EncryptProperties(encryptProperties);
|
||||
let encryptOptions = {
|
||||
properties:encryptProperties,
|
||||
inData: stringToUint8Array(plainText)
|
||||
};
|
||||
await huks.initSession(sm2KeyAlias, encryptOptions).then((data) => {
|
||||
Logger.info(TAG, `encrypt initSession success, data: ${JSON.stringify(data)}`);
|
||||
handle = data.handle;
|
||||
}).catch((err)=>{
|
||||
Logger.error(TAG, `encrypt initSession failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`);
|
||||
});
|
||||
await huks.finishSession(handle, encryptOptions).then((data) => {
|
||||
Logger.info(TAG, `encrypt finishSession success, data: ${JSON.stringify(data)}`);
|
||||
cipherData = data.outData;
|
||||
let that = new util.Base64Helper();
|
||||
resultCallback(that.encodeToStringSync(cipherData));
|
||||
}).catch((err)=>{
|
||||
Logger.error(TAG, `encrypt finishSession failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`);
|
||||
promptAction.showToast({
|
||||
message: `send message failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`,
|
||||
duration: 6500,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async finishSession(handle, options, resultCallback): Promise<void> {
|
||||
await huks.finishSession(handle, options).then((data) => {
|
||||
Logger.info(TAG, `decrypt finishSession success, data: ${JSON.stringify(data)}`);
|
||||
resultCallback(uint8ArrayToString(data.outData));
|
||||
}).catch((err) => {
|
||||
Logger.error(TAG, `decrypt finishSession failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`);
|
||||
promptAction.showToast({
|
||||
message: `receive message failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`,
|
||||
duration: 6500,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async userIAMAuthFinger(finishSessionFunction, param) : Promise<void> {
|
||||
const authParam : userAuth.AuthParam = {
|
||||
challenge: challengeNew,
|
||||
authType: [userAuth.UserAuthType.PIN],
|
||||
authTrustLevel: userAuth.AuthTrustLevel.ATL1
|
||||
};
|
||||
const widgetParam :userAuth.WidgetParam = {
|
||||
title: 'PIN'
|
||||
};
|
||||
try {
|
||||
let userAuthInstance = await userAuth.getUserAuthInstance(authParam, widgetParam);
|
||||
Logger.info(TAG, 'get userAuth instance success');
|
||||
await userAuthInstance.on('result', {
|
||||
onResult(result) {
|
||||
Logger.info(TAG, 'userAuthInstance callback result = ' + JSON.stringify(result));
|
||||
finishSessionFunction(param.handleParam, param.optionsParam, param.resultCallbackParam);
|
||||
}
|
||||
});
|
||||
Logger.info(TAG, 'auth on success');
|
||||
await userAuthInstance.start();
|
||||
Logger.info(TAG, 'auth on success');
|
||||
} catch (error) {
|
||||
Logger.error(TAG, 'auth catch error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟使用HUKS生成的新密钥进行低安访问控制与解密
|
||||
async decryptDataUseSm2(resultCallback): Promise<void> {
|
||||
let decryptOptions = new Array();
|
||||
getSm2DecryptProperties(decryptOptions);
|
||||
let sm2KeyAlias = 'test_sm2KeyAlias';
|
||||
let handle;
|
||||
let options = {
|
||||
properties: decryptOptions,
|
||||
inData: cipherData
|
||||
};
|
||||
let emptyOptions = {
|
||||
properties: []
|
||||
};
|
||||
await huks.initSession(sm2KeyAlias, options).then((data) => {
|
||||
Logger.info(TAG, `decrypt initSession success, data: ${JSON.stringify(data)}`);
|
||||
handle = data.handle;
|
||||
}).catch((err) => {
|
||||
Logger.error(TAG, `decrypt initSession failed, ${JSON.stringify(err.code)}: ${JSON.stringify(err.message)}`);
|
||||
});
|
||||
let finishSessionFunction = this.finishSession;
|
||||
let param = {
|
||||
handleParam : handle,
|
||||
optionsParam : options,
|
||||
resultCallbackParam : resultCallback,
|
||||
};
|
||||
await this.userIAMAuthFinger(finishSessionFunction, param);
|
||||
}
|
||||
|
||||
|
||||
// 模拟设备1使用旧密钥在本地进行加密
|
||||
async encryptDataUserOldKey(plainText: string, resultCallback): Promise<void> {
|
||||
let device1KeyAlias = 'device_1_key_alias';
|
||||
|
@ -13,8 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import router from '@ohos.router'
|
||||
import router from '@ohos.router';
|
||||
|
||||
export class Flag {
|
||||
public static value : number = 0;
|
||||
public static set(v : number): void {
|
||||
Flag.value = v;
|
||||
}
|
||||
}
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@ -34,36 +40,70 @@ struct Index {
|
||||
Navigation() {
|
||||
Stack({ alignContent: Alignment.Center }) {
|
||||
Column() {
|
||||
Button($r('app.string.new_key'))
|
||||
GridRow() {
|
||||
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
|
||||
Column() {
|
||||
Button() {
|
||||
Text($r('app.string.new_key')).fontSize(16).fontWeight(500)
|
||||
.lineHeight(22)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
.id('new_key')
|
||||
.margin(10)
|
||||
.fontSize(20)
|
||||
.width('40%')
|
||||
.height('10%')
|
||||
.borderRadius(20)
|
||||
.type(ButtonType.Capsule)
|
||||
.width('100%')
|
||||
.height('40vp')
|
||||
.margin({ bottom: 16 })
|
||||
.backgroundColor('#007DFF')
|
||||
.onClick(() => {
|
||||
router.push({
|
||||
url: 'pages/SelectPage',
|
||||
params: {
|
||||
flag: true
|
||||
Flag.set(1);
|
||||
router.pushUrl({
|
||||
url: 'pages/SelectPage'
|
||||
})
|
||||
});
|
||||
Button() {
|
||||
Text($r('app.string.old_key')).fontSize(16).fontWeight(500)
|
||||
.lineHeight(22)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Button($r('app.string.old_key'))
|
||||
.borderRadius(20)
|
||||
.id('old_key')
|
||||
.margin(10)
|
||||
.fontSize(20)
|
||||
.width('40%')
|
||||
.height('10%')
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({ left: 24, right: 24 })
|
||||
.margin({ bottom: 16 })
|
||||
.width('100%')
|
||||
.height('40vp')
|
||||
.backgroundColor('#007DFF')
|
||||
.onClick(() => {
|
||||
router.push({
|
||||
url: 'pages/SelectPage',
|
||||
params: {
|
||||
flag: false
|
||||
}
|
||||
})
|
||||
Flag.set(2);
|
||||
router.pushUrl({
|
||||
url: 'pages/SelectPage'
|
||||
})
|
||||
});
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.min_access_control')).fontSize(16).fontWeight(500)
|
||||
.lineHeight(22)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
.borderRadius(20)
|
||||
.id('min_access_control')
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({ left: 24, right: 24 })
|
||||
.margin({ bottom: 16 })
|
||||
.width('100%')
|
||||
.height('40vp')
|
||||
.backgroundColor('#007DFF')
|
||||
.onClick(() => {
|
||||
Flag.set(3);
|
||||
router.pushUrl({
|
||||
url: 'pages/SelectPage'
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}.margin({ left: 24, right: 24 })
|
||||
}.width('100%').height('296vp').justifyContent(FlexAlign.End)
|
||||
}
|
||||
.height('94%')
|
||||
}
|
||||
|
@ -16,19 +16,15 @@
|
||||
import router from '@ohos.router'
|
||||
import { NewKey } from '../common/NewKey'
|
||||
import { OldKey } from '../common/OldKey'
|
||||
import { MinAccessControl } from '../common/MinAccessControl'
|
||||
import { Flag } from '../pages/Index'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct SelectPage {
|
||||
private flag: boolean = router.getParams()['flag']
|
||||
|
||||
@State Params: number = Flag.value;
|
||||
@Builder NavigationTitle() {
|
||||
Column() {
|
||||
Text($r('app.string.back'))
|
||||
.fontColor('#182431')
|
||||
.fontSize(20)
|
||||
.lineHeight(25)
|
||||
.fontWeight(700)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
@ -36,10 +32,12 @@ struct SelectPage {
|
||||
build() {
|
||||
Column() {
|
||||
Navigation() {
|
||||
if (this.flag) {
|
||||
if (this.Params === 1) {
|
||||
NewKey()
|
||||
} else {
|
||||
} else if (this.Params === 2) {
|
||||
OldKey()
|
||||
} else {
|
||||
MinAccessControl()
|
||||
}
|
||||
}
|
||||
.title({ builder: this.NavigationTitle, height: 56 })
|
||||
|
@ -33,6 +33,11 @@
|
||||
"value": "all"
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.ACCESS_BIOMETRIC"
|
||||
}
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
|
@ -39,6 +39,34 @@
|
||||
{
|
||||
"name": "input_message",
|
||||
"value": "Input the message you want to send"
|
||||
},
|
||||
{
|
||||
"name": "input_save_password",
|
||||
"value": "Input the password you want to save"
|
||||
},
|
||||
{
|
||||
"name": "min_access_control",
|
||||
"value": "Minimum Access Control"
|
||||
},
|
||||
{
|
||||
"name": "save_password",
|
||||
"value": "Save Password"
|
||||
},
|
||||
{
|
||||
"name": "read_password",
|
||||
"value": "Read Password"
|
||||
},
|
||||
{
|
||||
"name": "cipher_text",
|
||||
"value": "Cipher_Text"
|
||||
},
|
||||
{
|
||||
"name": "plain_text",
|
||||
"value": "Plain Text"
|
||||
},
|
||||
{
|
||||
"name": "pinInput",
|
||||
"value": "Please Input Pin"
|
||||
}
|
||||
]
|
||||
}
|
@ -39,6 +39,34 @@
|
||||
{
|
||||
"name": "input_message",
|
||||
"value": "Input the message you want to send"
|
||||
},
|
||||
{
|
||||
"name": "input_save_password",
|
||||
"value": "Input the password you want to save"
|
||||
},
|
||||
{
|
||||
"name": "min_access_control",
|
||||
"value": "Minimum Access Control"
|
||||
},
|
||||
{
|
||||
"name": "save_password",
|
||||
"value": "Save Password"
|
||||
},
|
||||
{
|
||||
"name": "read_password",
|
||||
"value": "Read Password"
|
||||
},
|
||||
{
|
||||
"name": "cipher_text",
|
||||
"value": "Cipher_Text"
|
||||
},
|
||||
{
|
||||
"name": "plain_text",
|
||||
"value": "Plain Text"
|
||||
},
|
||||
{
|
||||
"name": "pinInput",
|
||||
"value": "Please Input Pin"
|
||||
}
|
||||
]
|
||||
}
|
@ -39,6 +39,35 @@
|
||||
{
|
||||
"name": "input_message",
|
||||
"value": "输入您要发送的消息"
|
||||
},
|
||||
{
|
||||
"name": "input_save_password",
|
||||
"value": "输入需要保存到的密码"
|
||||
},
|
||||
{
|
||||
"name": "min_access_control",
|
||||
"value": "低安访问控制"
|
||||
},
|
||||
{
|
||||
"name": "save_password",
|
||||
"value": "保存密码"
|
||||
},
|
||||
{
|
||||
"name": "read_password",
|
||||
"value": "读取密码"
|
||||
},
|
||||
{
|
||||
"name": "cipher_text",
|
||||
"value": "密码密文"
|
||||
},
|
||||
{
|
||||
"name": "plain_text",
|
||||
"value": "密码明文"
|
||||
},
|
||||
{
|
||||
"name": "pinInput",
|
||||
"value": "PIN"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
@ -178,5 +178,44 @@ export default function abilityTest() {
|
||||
Logger.info(TAG, BUNDLE + 'CipherByOldKeyFunction_002 end');
|
||||
done();
|
||||
})
|
||||
|
||||
/**
|
||||
* 使用HUKS进行低安访问控制加密
|
||||
*/
|
||||
it(BUNDLE + 'MinAccessControlFunction_001', 0, async function (done) {
|
||||
Logger.info(TAG, BUNDLE + 'MinAccessControlFunction_001 begin');
|
||||
// 点击低安访问控制按钮,跳转至使用低安访问控制页面
|
||||
Logger.info(TAG, BUNDLE + 'MinAccessControlFunction_001 encryption');
|
||||
await driver.delayMs(1000);
|
||||
await driver.assertComponentExist(ON.id('min_access_control'));
|
||||
let encryption = await driver.findComponent(ON.id('min_access_control'));
|
||||
await encryption.click();
|
||||
await driver.delayMs(1000);
|
||||
// 未输入发送的消息内容时,点击发送按钮,弹出toast弹窗提示信息:This message is null,toast弹窗信息暂不支持测试
|
||||
await driver.assertComponentExist(ON.id('save_password'));
|
||||
let encryptionBtn = await driver.findComponent(ON.id('save_password'));
|
||||
await encryptionBtn.click();
|
||||
await driver.delayMs(1000);
|
||||
Logger.info(TAG, BUNDLE + 'MinAccessControlFunction_001 input encryption content');
|
||||
await driver.assertComponentExist(ON.id('passwordInput'));
|
||||
let encryptionInput = await driver.findComponent(ON.id('passwordInput'));
|
||||
// encryptionInput.enableKeyboradOnFocus(false);
|
||||
await encryptionInput.inputText('test');
|
||||
let encryptionContent = await encryptionInput.getText();
|
||||
Logger.info(TAG, BUNDLE + `MinAccessControlFunction_001 select encryptionContent:${encryptionContent}`);
|
||||
expect(encryptionContent).assertEqual('test');
|
||||
// 点击发送按钮进行加密并发送密文消息
|
||||
await encryptionBtn.click();
|
||||
// 文本框显示加密后的消息内容
|
||||
Logger.info(TAG, BUNDLE + 'MinAccessControlFunction_001 show encryption content');
|
||||
await driver.assertComponentExist(ON.id('cipherTextinfo'));
|
||||
let encryptionInfo = await driver.findComponent(ON.id('cipherTextinfo'));
|
||||
let encryptionMessage = await encryptionInfo.getText();
|
||||
Logger.info(TAG, BUNDLE + `MinAccessControlFunction_001 select encryptionMessage:${encryptionMessage}`);
|
||||
expect(encryptionMessage === 'test').assertFalse();
|
||||
Logger.info(TAG, BUNDLE + 'MinAccessControlFunction_001 end');
|
||||
done();
|
||||
})
|
||||
|
||||
})
|
||||
}
|
@ -15,4 +15,3 @@
|
||||
|发送消息|成功跳转至旧密钥页面|输入内容,点击发送消息按钮|下方文本框显示加密后的消息内容|Pass|
|
||||
|导入旧密钥|发送消息不为空,且文本框中包含密文信息|点击导入密钥按钮|弹出toast提示:import old key success|Pass|
|
||||
|接收消息|发送消息不为空,且文本框中包含密文信息, 且导入密钥显示成功|点击接收消息按钮|下方文本框显示解密后的消息内容|Pass|
|
||||
|返回首页|旧密钥界面中所有操作全部执行完毕|点击返回|成功返回首页|Pass|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 218 KiB |
After Width: | Height: | Size: 206 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 252 KiB |
@ -24,7 +24,7 @@ import Logger from '../utils/Logger';
|
||||
|
||||
const TAG: string = 'ChatListDisplayView';
|
||||
// 搜索框中搜索栏的ID
|
||||
const ID_SEARCH: string = "search";
|
||||
const ID_SEARCH: string = 'search';
|
||||
// 删除item后,下方的item顶上来的动画的播放时间
|
||||
const DELETE_ANIMATION_DURATION: number = 500;
|
||||
const ABOUT_TO_APPEAR_TRACE: string = 'ChatListPage_AboutToAppear_HiTrace';
|
||||
|
@ -45,7 +45,7 @@ export struct DiscoverPage {
|
||||
[new SettingViewData($r('app.media.icon_de_nearby'), $r('app.string.around'))],
|
||||
[new SettingViewData($r('app.media.icon_de_shop'), $r('app.string.shopping')),
|
||||
new SettingViewData($r('app.media.icon_de_game'), $r('app.string.game'))]
|
||||
]
|
||||
];
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
|
@ -125,7 +125,7 @@ struct FriendsMomentsPage {
|
||||
struct OneMoment {
|
||||
private moment: FriendMoment = new FriendMoment('', new ChatContact('', ''), '', '', [], '', '');
|
||||
@State imageListMinLength: number = 2;
|
||||
@State liked: boolean = false // 是否点赞
|
||||
@State liked: boolean = false; // 是否点赞
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
|
@ -161,8 +161,8 @@ export struct FriendsPage {
|
||||
*/
|
||||
@Component
|
||||
export struct ChatContactItemView {
|
||||
private image: string | Resource = ''
|
||||
private text: string | Resource = ''
|
||||
private image: string | Resource = '';
|
||||
private text: string | Resource = '';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
|