Browse Source

first commit

Jianghan 10 months ago
parent
commit
ef4dd9397c
48 changed files with 3051 additions and 0 deletions
  1. 12 0
      .gitignore
  2. 10 0
      AppScope/app.json5
  3. 8 0
      AppScope/resources/base/element/string.json
  4. BIN
      AppScope/resources/base/media/app_icon.png
  5. 79 0
      build-profile.json5
  6. 20 0
      code-linter.json5
  7. 6 0
      entry/.gitignore
  8. 28 0
      entry/build-profile.json5
  9. 6 0
      entry/hvigorfile.ts
  10. 23 0
      entry/obfuscation-rules.txt
  11. 19 0
      entry/oh-package-lock.json5
  12. 12 0
      entry/oh-package.json5
  13. 44 0
      entry/src/main/ets/entryability/EntryAbility.ets
  14. 12 0
      entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
  15. 130 0
      entry/src/main/ets/pages/Index.ets
  16. 163 0
      entry/src/main/ets/pages/LocalFunc.ets
  17. 66 0
      entry/src/main/ets/pages/MyPreferences.ets
  18. 382 0
      entry/src/main/ets/pages/utils/AES.ets
  19. 78 0
      entry/src/main/ets/pages/utils/Base64Util.ets
  20. 122 0
      entry/src/main/ets/pages/utils/CharUtil.ets
  21. 244 0
      entry/src/main/ets/pages/utils/CryptoHelper.ets
  22. 627 0
      entry/src/main/ets/pages/utils/CryptoUtil.ets
  23. 133 0
      entry/src/main/ets/pages/utils/LogUtil.ets
  24. 104 0
      entry/src/main/ets/pages/utils/MD5.ets
  25. 21 0
      entry/src/main/ets/pages/utils/MyContext.ets
  26. 389 0
      entry/src/main/ets/pages/utils/StrUtil.ets
  27. 11 0
      entry/src/main/ets/pages/utils/crypto.ets
  28. 72 0
      entry/src/main/module.json5
  29. 8 0
      entry/src/main/resources/base/element/color.json
  30. 16 0
      entry/src/main/resources/base/element/string.json
  31. BIN
      entry/src/main/resources/base/media/background.png
  32. BIN
      entry/src/main/resources/base/media/foreground.png
  33. 7 0
      entry/src/main/resources/base/media/layered_image.json
  34. BIN
      entry/src/main/resources/base/media/startIcon.png
  35. 3 0
      entry/src/main/resources/base/profile/backup_config.json
  36. 5 0
      entry/src/main/resources/base/profile/main_pages.json
  37. 16 0
      entry/src/main/resources/en_US/element/string.json
  38. 16 0
      entry/src/main/resources/zh_CN/element/string.json
  39. 2 0
      entry/src/mock/mock-config.json5
  40. 35 0
      entry/src/ohosTest/ets/test/Ability.test.ets
  41. 5 0
      entry/src/ohosTest/ets/test/List.test.ets
  42. 12 0
      entry/src/ohosTest/module.json5
  43. 7 0
      entry/src/test/List.test.ets
  44. 33 0
      entry/src/test/LocalUnit.test.ets
  45. 22 0
      hvigor/hvigor-config.json5
  46. 6 0
      hvigorfile.ts
  47. 27 0
      oh-package-lock.json5
  48. 10 0
      oh-package.json5

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer

+ 10 - 0
AppScope/app.json5

@@ -0,0 +1,10 @@
+{
+  "app": {
+    "bundleName": "com.jianyu.bidding",
+    "vendor": "example",
+    "versionCode": 1000000,
+    "versionName": "3.1.2",
+    "icon": "$media:app_icon",
+    "label": "$string:app_name"
+  }
+}

+ 8 - 0
AppScope/resources/base/element/string.json

@@ -0,0 +1,8 @@
+{
+  "string": [
+    {
+      "name": "app_name",
+      "value": "剑鱼标讯"
+    }
+  ]
+}

BIN
AppScope/resources/base/media/app_icon.png


+ 79 - 0
build-profile.json5

@@ -0,0 +1,79 @@
+{
+  "app": {
+    "signingConfigs": [
+      {
+        "name": "release",
+        "type": "HarmonyOS",
+        "material": {
+          "certpath": "/Users/jianghan/Project/DevEcoPro/janyu-release.cer",
+          "storePassword": "0000001A93B60407E8E0C6583906C20D67FECDCAD9F41046D33C0DF7A330AEBE7DD5D57751EC06C1FAAD",
+          "keyAlias": "jianyu",
+          "keyPassword": "0000001AA066778DE4BCAD3B19FF3DF053A883A1108F03E4F9FB180919ACF26B236BF191E10749AAB5C8",
+          "profile": "/Users/jianghan/Project/DevEcoPro/jianyuRelease.p7b",
+          "signAlg": "SHA256withECDSA",
+          "storeFile": "/Users/jianghan/Project/DevEcoPro/jianyu.p12"
+        }
+      },
+      {
+        "name": "default",
+        "type": "HarmonyOS",
+        "material": {
+          "certpath": "/Users/jianghan/.ohos/config/default_jianyu_-z0r0Xy6ucplVnETOLa9oB0wMlu8yIFPkQAuCM1jIkw=.cer",
+          "storePassword": "0000001BBBFB873734441806E5AF600B59B8D7BD25FD15F1C796166CE020C7BE01682E42C3C6F868D3A057",
+          "keyAlias": "debugKey",
+          "keyPassword": "0000001BCB2BB67E6197598BE386A965905747004731994BB70AD14AA5674AC1982DE72F42FAB716E12E67",
+          "profile": "/Users/jianghan/.ohos/config/default_jianyu_-z0r0Xy6ucplVnETOLa9oB0wMlu8yIFPkQAuCM1jIkw=.p7b",
+          "signAlg": "SHA256withECDSA",
+          "storeFile": "/Users/jianghan/.ohos/config/default_jianyu_-z0r0Xy6ucplVnETOLa9oB0wMlu8yIFPkQAuCM1jIkw=.p12"
+        }
+      }
+    ],
+    "products": [
+      {
+        "name": "default",
+        "signingConfig": "default",
+        "compatibleSdkVersion": "5.0.0(12)",
+        "runtimeOS": "HarmonyOS",
+        "buildOption": {
+          "strictMode": {
+            "caseSensitiveCheck": true
+          }
+        }
+      },
+      {
+        "name": "release",
+        "signingConfig": "release",
+        "compatibleSdkVersion": "5.0.0(12)",
+        "runtimeOS": "HarmonyOS",
+        "buildOption": {
+          "strictMode": {
+            "caseSensitiveCheck": true
+          }
+        }
+      }
+    ],
+    "buildModeSet": [
+      {
+        "name": "debug",
+      },
+      {
+        "name": "release"
+      }
+    ]
+  },
+  "modules": [
+    {
+      "name": "entry",
+      "srcPath": "./entry",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default",
+            "release"
+          ]
+        }
+      ]
+    }
+  ]
+}

+ 20 - 0
code-linter.json5

@@ -0,0 +1,20 @@
+{
+  "files": [
+    "**/*.ets"
+  ],
+  "ignore": [
+    "**/src/ohosTest/**/*",
+    "**/src/test/**/*",
+    "**/src/mock/**/*",
+    "**/node_modules/**/*",
+    "**/oh_modules/**/*",
+    "**/build/**/*",
+    "**/.preview/**/*"
+  ],
+  "ruleSet": [
+    "plugin:@performance/recommended",
+    "plugin:@typescript-eslint/recommended"
+  ],
+  "rules": {
+  }
+}

+ 6 - 0
entry/.gitignore

@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test

+ 28 - 0
entry/build-profile.json5

@@ -0,0 +1,28 @@
+{
+  "apiType": "stageMode",
+  "buildOption": {
+  },
+  "buildOptionSet": [
+    {
+      "name": "release",
+      "arkOptions": {
+        "obfuscation": {
+          "ruleOptions": {
+            "enable": false,
+            "files": [
+              "./obfuscation-rules.txt"
+            ]
+          }
+        }
+      }
+    },
+  ],
+  "targets": [
+    {
+      "name": "default"
+    },
+    {
+      "name": "ohosTest",
+    }
+  ]
+}

+ 6 - 0
entry/hvigorfile.ts

@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+    system: hapTasks,  /* Built-in plugin of Hvigor. It cannot be modified. */
+    plugins:[]         /* Custom plugin to extend the functionality of Hvigor. */
+}

+ 23 - 0
entry/obfuscation-rules.txt

@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+#   https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation

+ 19 - 0
entry/oh-package-lock.json5

@@ -0,0 +1,19 @@
+{
+  "meta": {
+    "stableOrder": true
+  },
+  "lockfileVersion": 3,
+  "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+  "specifiers": {
+    "@ohos/crypto-js@2.0.0": "@ohos/crypto-js@2.0.0"
+  },
+  "packages": {
+    "@ohos/crypto-js@2.0.0": {
+      "name": "@ohos/crypto-js",
+      "version": "2.0.0",
+      "integrity": "sha512-SAPr0jdRS45kidxIqtSeBj4Eo7LMGSFRE+y8XxDNEDuqEvIA7Yv+2tEkFuFtcgxF7tATfHV16cazRC7/muocCQ==",
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/crypto-js/-/crypto-js-2.0.0.har",
+      "registryType": "ohpm"
+    }
+  }
+}

+ 12 - 0
entry/oh-package.json5

@@ -0,0 +1,12 @@
+{
+  "name": "entry",
+  "version": "1.0.0",
+  "description": "Please describe the basic information.",
+  "main": "",
+  "author": "",
+  "license": "",
+  "dependencies": {
+    "@ohos/crypto-js": "2.0.0"
+  }
+}
+

+ 44 - 0
entry/src/main/ets/entryability/EntryAbility.ets

@@ -0,0 +1,44 @@
+import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+import PreferencesUtils from '../pages/MyPreferences'
+
+export default class EntryAbility extends UIAbility {
+  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+
+    PreferencesUtils.createPreferences(this.context)
+  }
+
+  onDestroy(): void {
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+  }
+
+  onWindowStageCreate(windowStage: window.WindowStage): void {
+    // Main window is created, set main page for this ability
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+    windowStage.loadContent('pages/Index', (err) => {
+      if (err.code) {
+        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+        return;
+      }
+      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
+    });
+  }
+
+  onWindowStageDestroy(): void {
+    // Main window is destroyed, release UI related resources
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+  }
+
+  onForeground(): void {
+    // Ability has brought to foreground
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+  }
+
+  onBackground(): void {
+    // Ability has back to background
+    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+  }
+}

+ 12 - 0
entry/src/main/ets/entrybackupability/EntryBackupAbility.ets

@@ -0,0 +1,12 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+  async onBackup() {
+    hilog.info(0x0000, 'testTag', 'onBackup ok');
+  }
+
+  async onRestore(bundleVersion: BundleVersion) {
+    hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+  }
+}

+ 130 - 0
entry/src/main/ets/pages/Index.ets

@@ -0,0 +1,130 @@
+
+import { webview } from '@kit.ArkWeb';
+import { BusinessError } from '@kit.BasicServicesKit';
+import { promptAction } from '@kit.ArkUI';
+import { bundleManager } from '@kit.AbilityKit'
+import { LocalFunc } from './LocalFunc'
+import common from '@ohos.app.ability.common';
+import PreferencesUtils from '../pages/MyPreferences'
+import { StrUtil } from './utils/StrUtil';
+
+@Entry
+@Component
+struct WebComponent {
+  controller: webview.WebviewController = new webview.WebviewController();
+  private versionName = '1.0.0'
+  private cookie: string = ''
+  @State LocalFunc: LocalFunc = new LocalFunc(this.controller)
+
+  aboutToAppear(): void {
+
+    bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then((info) => {
+      this.versionName = info.versionName
+    })
+
+    try {
+      webview.WebviewController.setWebDebuggingAccess(true);
+    } catch (error) {
+      console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
+    }
+  }
+
+  onBackPress() {
+    if (this.controller.accessBackward()) {
+      this.controller.backward();
+    }else {
+      const context = getContext(this) as common.UIAbilityContext;
+      context.terminateSelf();
+    }
+    return true;
+  }
+
+  build() {
+    Column() {
+      Web({ src: 'https://app-i3.jianyu360.cn/jyapp/free/index?deviceid=', controller: this.controller })
+        .onControllerAttached(() => {
+          // 推荐在此loadUrl、设置自定义用户代理、注入JS对象等
+          console.log('onControllerAttached execute')
+          let userAgent =  this.controller.getUserAgent()
+          this.controller.setCustomUserAgent(userAgent + ' jianyuapp/' + this.versionName)
+        })
+        .onLoadIntercept((event) => {
+          if (event) {
+            console.log('onLoadIntercept url:' + event.data.getRequestUrl())
+            console.log('url:' + event.data.getRequestUrl())
+            console.log('isMainFrame:' + event.data.isMainFrame())
+            console.log('isRedirect:' + event.data.isRedirect())
+            console.log('isRequestGesture:' + event.data.isRequestGesture())
+          }
+          // 返回true表示阻止此次加载,否则允许此次加载
+          return false
+        })
+        .onOverrideUrlLoading((webResourceRequest: WebResourceRequest) => {
+          if (webResourceRequest && webResourceRequest.getRequestUrl() == "about:blank") {
+            return true;
+          }
+          return false;
+        })
+        .onPageBegin((event) => {
+          if (event) {
+            console.log('onPageBegin url:' + event.url);
+          }
+          if (StrUtil.isEmpty(this.cookie)) {
+            PreferencesUtils.get("cookie").then((info) => {
+              this.cookie = info as string
+            })
+          }
+          if (StrUtil.isNotEmpty(this.cookie)) {
+            webview.WebCookieManager.configCookieSync(this.controller.getUrl(), this.cookie)
+          }
+        })
+        .onFirstContentfulPaint(event => {
+          if (event) {
+            console.log("onFirstContentfulPaint:" + "[navigationStartTick]:" +
+            event.navigationStartTick + ", [firstContentfulPaintMs]:" +
+            event.firstContentfulPaintMs);
+          }
+        })
+        .onProgressChange((event) => {
+          if (event) {
+            // console.log('newProgress:' + event.newProgress);
+          }
+        })
+        .onPageEnd((event) => {
+          // 推荐在此事件中执行JavaScript脚本
+          if (event) {
+            console.log('onPageEnd url:' + event.url);
+          }
+          let cookie = webview.WebCookieManager.fetchCookieSync(this.controller.getUrl())
+          console.log('cookie: ', cookie)
+          if (StrUtil.isEmpty(this.cookie)) {
+            PreferencesUtils.put('cookie', cookie)
+          }
+        })
+        .onPageVisible((event) => {
+          console.log('onPageVisible url:' + event.url);
+        })
+        .onRenderExited((event) => {
+          if (event) {
+            console.log('onRenderExited reason:' + event.renderExitReason);
+          }
+        })
+        .onDisAppear(() => {
+          promptAction.showToast({
+            message: 'The web is hidden',
+            duration: 2000
+          })
+        })
+        .domStorageAccess(true)
+        .javaScriptProxy({
+          object: this.LocalFunc,
+          name: "JyObj",
+          methodList: ['chooseTab', 'hiddenBottom', 'getUserToken', 'clearHistory', 'getVersion', 'getLogin', 'getCipherText', 'sendMsgCount', 'loginByWeixin', 'openExternalLink',
+            'share', 'callPhone', 'getPushRid', 'saveUserToken', 'checkNoticePermission', 'removeUserToken', 'checkLab', 'loginSuccess', 'backUrl', 'getOtherPushId', 'getPhoneBrand',
+            'getIdentity', 'getChannel'],
+          controller: this.controller
+        })
+        .cacheMode(CacheMode.Online)
+    }
+  }
+}

+ 163 - 0
entry/src/main/ets/pages/LocalFunc.ets

@@ -0,0 +1,163 @@
+
+import { webview } from '@kit.ArkWeb';
+import { bundleManager, common } from '@kit.AbilityKit'
+import util from '@ohos.util'
+import { MD5 } from './utils/MD5';
+import { AES } from './utils/AES'
+import { CryptoHelper } from './utils/CryptoHelper'
+import { CryptoUtil } from './utils/CryptoUtil'
+import { StrUtil } from './utils/StrUtil';
+import call from '@ohos.telephony.call';
+import PreferencesUtils from '../pages/MyPreferences'
+
+export class LocalFunc {
+  private controller: webview.WebviewController
+  private versionName: string = '1.0.0'
+  private token: string = ''
+
+  constructor(controller: webview.WebviewController) {
+    this.controller = controller
+  }
+
+  chooseTab() {}
+
+  hiddenBottom() {
+  }
+
+  saveUserToken(token: string) {
+    PreferencesUtils.put("token", token)
+  }
+
+  getUserToken(): string {
+    PreferencesUtils.get("token").then((info) => {
+      this.token = info as string
+    })
+    return this.token
+  }
+
+  removeUserToken() {
+    PreferencesUtils.delete("token")
+  }
+
+  /**
+   * 清空浏览器历史
+   */
+  clearHistory() {
+    this.controller.clearHistory()
+  }
+
+  /**
+   * 获取app版本
+   */
+  getVersion(): string {
+    bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then((info) => {
+      this.versionName = info.versionName
+    })
+    return this.versionName
+  }
+
+  /**
+   * 手机号一键登陆
+   */
+  getLogin() {
+    this.controller.runJavaScript('getLoginCallback("")');
+  }
+
+  /**
+   * 发送验证码
+   * @returns 手机号+日期 加密
+   */
+  getCipherText(phoneNumb: string): string {
+    if (StrUtil.isEmpty(phoneNumb)) {
+      return ""
+    }
+    let currentDate = new Date()
+    let year = currentDate.getFullYear();
+    let month = (currentDate.getMonth() + 1).toString().padStart(2, '0'); // 月份需要补0
+    let day = currentDate.getDate().toString().padStart(2, '0');           // 日期补0
+    let hours = currentDate.getHours().toString().padStart(2, '0');        // 小时补0
+    let minutes = currentDate.getMinutes().toString().padStart(2, '0');    // 分钟补0
+    let seconds = currentDate.getSeconds().toString().padStart(2, '0');
+    let dd = `${year}${month}${day}${hours}${minutes}${seconds}`
+    let sign = MD5.digestSync(phoneNumb + "&" + dd).toString()
+    let symKey = CryptoUtil.getConvertSymKeySync('AES128', 'mGlAgnIBB8bx2nch', 'utf-8')
+    let ivP = CryptoUtil.getIvParamsSpec("1389461544135476", "utf-8")
+    let data = CryptoHelper.strToDataBlob(util.format("%s_%s_%s", phoneNumb, dd, sign), 'utf-8'); //待加密数据
+    let encryptData = AES.encryptCBCSync(data, symKey, ivP, 'AES|CBC|PKCS5')
+    let base64Str = CryptoHelper.dataBlobToStr(encryptData, "base64");
+    return base64Str
+  }
+
+  sendMsgCount() {}
+
+  loginByWeixin() {
+    AlertDialog.show({
+      title: "暂不支持微信登陆!",
+      message: "请通过手机号登陆,暂时无法支持微信登陆",
+      confirm: {
+        value: "确定",
+        action: () => {},
+      }
+    })
+  }
+
+  openExternalLink(url: string, title: string) {
+    this.controller.loadUrl(url)
+  }
+
+  /**
+   * 分享
+   * @param type
+   * @param title
+   * @param content
+   * @param link
+   * @param tips
+   */
+  share(type: string, title: string, content: string, link: string, tips: String) {
+    AlertDialog.show({
+      title: "暂不支持分享功能!",
+      message: "请关注后续版本功能",
+      confirm: {
+        value: "确定",
+        action: () => {},
+      }
+    })
+  }
+
+  /**
+   * 拨打电话
+   */
+  callPhone(tel: string) {
+    call.makeCall(tel, err => {
+      console.log(`callPhone callback: err->${JSON.stringify(err)}`);
+    });
+  }
+
+  checkNoticePermission() {
+  }
+  checkLab() {}
+  loginSuccess() {
+    // PreferencesUtils.get("token").then((info) => {
+    //   this.token = info as string
+    // })
+    // this.controller.loadUrl('https://app-i3.jianyu360.cn/jyapp/free/index' + '?sign=' + this.token)
+  }
+  backUrl() {
+    this.controller.backward()
+  }
+  getPushRid(): string {
+    return ""
+  }
+  getOtherPushId(): string {
+    return ""
+  }
+  getPhoneBrand(): string {
+    return "huawei"
+  }
+  getIdentity(): string {
+    return ""
+  }
+  getChannel(): string {
+    return "topnet"
+  }
+}

+ 66 - 0
entry/src/main/ets/pages/MyPreferences.ets

@@ -0,0 +1,66 @@
+
+import dataPreferences from '@ohos.data.preferences'
+import GlobalContext from './utils/MyContext'
+
+const TAG = "PreferencesUtils"
+// 默认文件名,可以在构造函数进行修改
+const PREFERENCES_NAME = 'yiPreferences'
+const KEY_PREFERENCES = "preferences"
+
+export class PreferencesUtils{
+  // preferences的文件名
+  private preferencesName: string = PREFERENCES_NAME
+  // 用于获取preferences实例的key值,保存到单例中
+  private keyPreferences: string = KEY_PREFERENCES
+
+  constructor(name: string = PREFERENCES_NAME, keyP: string = KEY_PREFERENCES) {
+    this.preferencesName = name
+    this.keyPreferences = keyP
+  }
+
+  createPreferences(context: Context): Promise<dataPreferences.Preferences> {
+    let preferences = dataPreferences.getPreferences(context, this.preferencesName)
+    GlobalContext.getContext().setObject(this.keyPreferences, preferences)
+    return preferences
+  }
+
+  getPreferences(): Promise<dataPreferences.Preferences> {
+    return GlobalContext.getContext().getObject(KEY_PREFERENCES) as Promise<dataPreferences.Preferences>
+  }
+
+  async get(key: string, def?: dataPreferences.ValueType): Promise<dataPreferences.ValueType> {
+   return (await this.getPreferences()).get(key, def)
+  }
+
+  async getAll(): Promise<Object> {
+    let  preferences = await this.getPreferences()
+    return preferences.getAll()
+  }
+
+  async put(key: string, value: dataPreferences.ValueType): Promise<void> {
+    let promise = await this.getPreferences().then(async (p) => {
+      await p.put(key, value)
+      await p.flush();
+    }).catch((err: Error)=>{
+      console.log(TAG, err)
+    })
+    return promise
+  }
+
+
+
+  async delete(key: string): Promise<void> {
+    return (await this.getPreferences()).delete(key).finally(async () => {
+      (await this.getPreferences()).flush()
+    })
+  }
+
+  async clear(): Promise<void> {
+    return (await this.getPreferences()).clear().finally(async () => {
+      (await this.getPreferences()).flush()
+    })
+  }
+
+}
+
+export default new PreferencesUtils()

+ 382 - 0
entry/src/main/ets/pages/utils/AES.ets

@@ -0,0 +1,382 @@
+import cryptoFramework from '@ohos.security.cryptoFramework';
+import { CryptoUtil } from './CryptoUtil';
+
+
+/**
+ * AES加解密
+ */
+export class AES {
+
+
+  /**
+   * 加密(GCM模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @returns
+   */
+  static async encryptGCM(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    let cipher = cryptoFramework.createCipher(transformation);
+    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
+    let encryptUpdate = await cipher.update(data);
+    //GCM模式加密doFinal时传入空,获得tag数据,并更新至gcmParams对象中。
+    gcmParams.authTag = await cipher.doFinal(null);
+    return encryptUpdate;
+  }
+
+  /**
+   * 加密(GCM模式),同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @returns
+   */
+  static encryptGCMSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7'): cryptoFramework.DataBlob {
+    let cipher = cryptoFramework.createCipher(transformation);
+    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
+    let encryptUpdate = cipher.updateSync(data);
+    //GCM模式加密doFinal时传入空,获得tag数据,并更新至gcmParams对象中。
+    gcmParams.authTag = cipher.doFinalSync(null);
+    return encryptUpdate;
+  }
+
+
+  /**
+   * 解密(GCM模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @returns
+   */
+  static async decryptGCM(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    let decoder = cryptoFramework.createCipher(transformation);
+    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
+    let decryptUpdate = await decoder.update(data);
+    //GCM模式解密doFinal时传入空,验证init时传入的tag数据,如果验证失败会抛出异常。
+    await decoder.doFinal(null)
+    return decryptUpdate;
+  }
+
+  /**
+   * 解密(GCM模式),同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @returns
+   */
+  static decryptGCMSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7'): cryptoFramework.DataBlob {
+    let decoder = cryptoFramework.createCipher(transformation);
+    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
+    let decryptUpdate = decoder.updateSync(data);
+    //GCM模式解密doFinal时传入空,验证init时传入的tag数据,如果验证失败会抛出异常。
+    decoder.doFinalSync(null)
+    return decryptUpdate;
+  }
+
+
+  /**
+   * 加密(CBC模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param ivParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|CBC|PKCS7、AES192|CBC|PKCS7、AES128|CBC|PKCS7)。
+   * @returns
+   */
+  static async encryptCBC(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    ivParams: cryptoFramework.IvParamsSpec, transformation: string = 'AES256|CBC|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    return AES.encrypt(data, symKey, ivParams, transformation);
+  }
+
+  /**
+   * 加密(CBC模式),同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param ivParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|CBC|PKCS7、AES192|CBC|PKCS7、AES128|CBC|PKCS7)。
+   * @returns
+   */
+  static encryptCBCSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    ivParams: cryptoFramework.IvParamsSpec, transformation: string = 'AES256|CBC|PKCS7'): cryptoFramework.DataBlob {
+    return AES.encryptSync(data, symKey, ivParams, transformation);
+  }
+
+
+  /**
+   * 解密(CBC模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param ivParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|CBC|PKCS7、AES192|CBC|PKCS7、AES128|CBC|PKCS7)。
+   * @returns
+   */
+  static async decryptCBC(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    ivParams: cryptoFramework.IvParamsSpec, transformation: string = 'AES256|CBC|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    return AES.decrypt(data, symKey, ivParams, transformation);
+  }
+
+  /**
+   * 解密(CBC模式),同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param ivParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|CBC|PKCS7、AES192|CBC|PKCS7、AES128|CBC|PKCS7)。
+   * @returns
+   */
+  static decryptCBCSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    ivParams: cryptoFramework.IvParamsSpec, transformation: string = 'AES256|CBC|PKCS7'): cryptoFramework.DataBlob {
+    return AES.decryptSync(data, symKey, ivParams, transformation);
+  }
+
+
+  /**
+   * 加密(ECB模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|ECB|PKCS7、AES192|ECB|PKCS7、AES128|ECB|PKCS7)。
+   * @returns
+   */
+  static async encryptECB(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    transformation: string = 'AES256|ECB|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    return AES.encrypt(data, symKey, null, transformation);
+  }
+
+  /**
+   * 加密(ECB模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|ECB|PKCS7、AES192|ECB|PKCS7、AES128|ECB|PKCS7)。
+   * @returns
+   */
+  static encryptECBSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    transformation: string = 'AES256|ECB|PKCS7'): cryptoFramework.DataBlob {
+    return AES.encryptSync(data, symKey, null, transformation);
+  }
+
+
+  /**
+   * 解密(ECB模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|ECB|PKCS7、AES192|ECB|PKCS7、AES128|ECB|PKCS7)。
+   * @returns
+   */
+  static async decryptECB(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    transformation: string = 'AES256|ECB|PKCS7'): Promise<cryptoFramework.DataBlob> {
+    return AES.decrypt(data, symKey, null, transformation);
+  }
+
+  /**
+   * 解密(ECB模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|ECB|PKCS7、AES192|ECB|PKCS7、AES128|ECB|PKCS7)。
+   * @returns
+   */
+  static decryptECBSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    transformation: string = 'AES256|ECB|PKCS7'): cryptoFramework.DataBlob {
+    return AES.decryptSync(data, symKey, null, transformation);
+  }
+
+
+  /**
+   * 加密,异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static async encrypt(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): Promise<cryptoFramework.DataBlob> {
+    return CryptoUtil.encrypt(data, symKey, params, transformation);
+  }
+
+  /**
+   * 加密,同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static encryptSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): cryptoFramework.DataBlob {
+    return CryptoUtil.encryptSync(data, symKey, params, transformation);
+  }
+
+
+  /**
+   * 解密,异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static async decrypt(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): Promise<cryptoFramework.DataBlob> {
+    return CryptoUtil.decrypt(data, symKey, params, transformation);
+  }
+
+  /**
+   * 解密,同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static decryptSync(data: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): cryptoFramework.DataBlob {
+    return CryptoUtil.decryptSync(data, symKey, params, transformation);
+  }
+
+
+  /**
+   * 加密(GCM模式)分段,异步
+   * @param dataBlob 加密或者解密的数据。dataBlob不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES128|GCM|PKCS7、AES192|GCM|PKCS7、AES256|GCM|PKCS7、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static async encryptGCMSegment(dataBlob: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7',
+    len: number = 128): Promise<cryptoFramework.DataBlob> {
+    let cipher = cryptoFramework.createCipher(transformation);
+    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, gcmParams);
+    let encryptData = new Uint8Array();
+    for (let i = 0; i < dataBlob.data.length; i += len) {
+      let updateData = dataBlob.data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      let updateOutput = await cipher.update(updateDataBlob); //分段update
+      let mergeTData = new Uint8Array(encryptData.length + updateOutput.data.length);
+      mergeTData.set(encryptData);
+      mergeTData.set(updateOutput.data, encryptData.length);
+      encryptData = mergeTData;
+    }
+    gcmParams.authTag = await cipher.doFinal(null);
+    let encryptBlob: cryptoFramework.DataBlob = { data: encryptData };
+    return encryptBlob;
+  }
+
+  /**
+   * 加密(GCM模式)分段,同步
+   * @param dataBlob 加密或者解密的数据。dataBlob不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES128|GCM|PKCS7、AES192|GCM|PKCS7、AES256|GCM|PKCS7、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static encryptGCMSegmentSync(dataBlob: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7',
+    len: number = 128): cryptoFramework.DataBlob {
+    let cipher = cryptoFramework.createCipher(transformation);
+    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, gcmParams);
+    let encryptData = new Uint8Array();
+    for (let i = 0; i < dataBlob.data.length; i += len) {
+      let updateData = dataBlob.data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      let updateOutput = cipher.updateSync(updateDataBlob); //分段update
+      let mergeTData = new Uint8Array(encryptData.length + updateOutput.data.length);
+      mergeTData.set(encryptData);
+      mergeTData.set(updateOutput.data, encryptData.length);
+      encryptData = mergeTData;
+    }
+    gcmParams.authTag = cipher.doFinalSync(null);
+    let encryptBlob: cryptoFramework.DataBlob = { data: encryptData };
+    return encryptBlob;
+  }
+
+
+  /**
+   * 解密(GCM模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static async decryptGCMSegment(dataBlob: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7',
+    len: number = 128): Promise<cryptoFramework.DataBlob> {
+    let decoder = cryptoFramework.createCipher(transformation);
+    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
+    let decryptData = new Uint8Array();
+    for (let i = 0; i < dataBlob.data.length; i += len) {
+      let updateData = dataBlob.data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      let updateOutput = await decoder.update(updateDataBlob); //分段update
+      //把update的结果拼接起来,得到明文
+      let mergeData = new Uint8Array(decryptData.length + updateOutput.data.length);
+      mergeData.set(decryptData);
+      mergeData.set(updateOutput.data, decryptData.length);
+      decryptData = mergeData;
+    }
+    await decoder.doFinal(null);
+    let decryptBlob: cryptoFramework.DataBlob = { data: decryptData };
+    return decryptBlob;
+  }
+
+  /**
+   * 解密(GCM模式),异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param symKey 指定加密或解密的密钥。
+   * @param gcmParams 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合(AES256|GCM|PKCS7、AES192|GCM|PKCS7、AES128|GCM|PKCS7)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static decryptGCMSegmentSync(dataBlob: cryptoFramework.DataBlob, symKey: cryptoFramework.SymKey,
+    gcmParams: cryptoFramework.GcmParamsSpec, transformation: string = 'AES256|GCM|PKCS7',
+    len: number = 128): cryptoFramework.DataBlob {
+    let decoder = cryptoFramework.createCipher(transformation);
+    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
+    let decryptData = new Uint8Array();
+    for (let i = 0; i < dataBlob.data.length; i += len) {
+      let updateData = dataBlob.data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      let updateOutput = decoder.updateSync(updateDataBlob); //分段update
+      //把update的结果拼接起来,得到明文
+      let mergeTData = new Uint8Array(decryptData.length + updateOutput.data.length);
+      mergeTData.set(decryptData);
+      mergeTData.set(updateOutput.data, decryptData.length);
+      decryptData = mergeTData;
+    }
+    decoder.doFinalSync(null);
+    let decryptBlob: cryptoFramework.DataBlob = { data: decryptData };
+    return decryptBlob;
+  }
+
+
+  /**
+   * 生成对称密钥SymKey,异步
+   * @param symAlgName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256)
+   * @returns
+   */
+  static async generateSymKey(algName: string = 'AES256'): Promise<cryptoFramework.SymKey> {
+    return CryptoUtil.generateSymKey(algName);
+  }
+
+  /**
+   * 生成对称密钥SymKey,同步
+   * @param symAlgName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256)
+   * @returns
+   */
+  static generateSymKeySync(algName: string = 'AES256'): cryptoFramework.SymKey {
+    return CryptoUtil.generateSymKeySync(algName);
+  }
+
+
+}

+ 78 - 0
entry/src/main/ets/pages/utils/Base64Util.ets

@@ -0,0 +1,78 @@
+import util from '@ohos.util';
+
+/**
+ * Base64工具类
+ */
+export class Base64Util{
+
+  private constructor() {}
+
+
+  /**
+   * 编码,通过输入参数编码后输出Uint8Array对象。
+   * @param array
+   * @returns
+   */
+  static encodeSync(array: Uint8Array): Uint8Array {
+    let base64 = new util.Base64Helper();
+    let result = base64.encodeSync(array);
+    return result;
+  }
+
+
+  /**
+   * 编码,通过输入参数编码后输出对应文本。
+   * @param array
+   * @returns
+   */
+  static encodeToStrSync(array: Uint8Array, options?: util.Type): string {
+    let base64 = new util.Base64Helper();
+    let result = base64.encodeToStringSync(array, options);
+    return result;
+  }
+
+  /**
+   * 解码,通过输入参数解码后输出对应Uint8Array对象。
+   * @param array
+   * @returns
+   */
+  static decodeSync(array: Uint8Array | string, options?: util.Type): Uint8Array {
+    let base64 = new util.Base64Helper();
+    let result = base64.decodeSync(array, options);
+    return result;
+  }
+
+
+  /**
+   * 编码,通过输入参数编码后输出Uint8Array对象。
+   * @param array
+   * @returns
+   */
+  static encode(array: Uint8Array): Promise<Uint8Array> {
+    let base64 = new util.Base64Helper();
+    return base64.encode(array);
+  }
+
+
+  /**
+   * 编码,通过输入参数编码后输出对应文本。
+   * @param array
+   * @returns
+   */
+  static encodeToStr(array: Uint8Array, options?: util.Type): Promise<string> {
+    let base64 = new util.Base64Helper();
+    return base64.encodeToString(array, options);
+  }
+
+  /**
+   * 解码,通过输入参数解码后输出对应Uint8Array对象。
+   * @param array
+   * @returns
+   */
+  static decode(array: Uint8Array | string, options?: util.Type): Promise<Uint8Array> {
+    let base64 = new util.Base64Helper();
+    return base64.decode(array, options);
+  }
+
+
+}

+ 122 - 0
entry/src/main/ets/pages/utils/CharUtil.ets

@@ -0,0 +1,122 @@
+import { i18n } from '@kit.LocalizationKit';
+
+/**
+ * 字符工具类
+ */
+export class CharUtil {
+
+  private constructor() {}
+
+
+  /**
+   * 判断字符串char是否是数字
+   * @param char
+   * @returns
+   */
+  static isDigit(char: string): boolean {
+    return i18n.Unicode.isDigit(char);
+  }
+
+  /**
+   * 判断字符串char是否是字母
+   * @param char
+   * @returns
+   */
+  static isLetter(char: string): boolean {
+    return i18n.Unicode.isLetter(char);
+  }
+
+  /**
+   * 判断字符串char是否是小写字母
+   * @param char
+   * @returns
+   */
+  static isLowerCase(char: string): boolean {
+    return i18n.Unicode.isLowerCase(char);
+  }
+
+  /**
+   * 判断字符串char是否是大写字母
+   * @param char
+   * @returns
+   */
+  static isUpperCase(char: string): boolean {
+    return i18n.Unicode.isUpperCase(char);
+  }
+
+  /**
+   * 判断字符串char是否是空格符
+   * @param char
+   * @returns
+   */
+  static isSpaceChar(char: string): boolean {
+    return i18n.Unicode.isSpaceChar(char);
+  }
+
+  /**
+   * 判断字符串char是否是空白符
+   * @param char
+   * @returns
+   */
+  static isWhitespace(char: string): boolean {
+    return i18n.Unicode.isWhitespace(char);
+  }
+
+  /**
+   * 判断字符串char是否是从右到左语言的字符
+   * @param char
+   * @returns
+   */
+  static isRTL(char: string): boolean {
+    return i18n.Unicode.isRTL(char);
+  }
+
+  /**
+   * 判断字符串char是否是表意文字
+   * @param char
+   * @returns
+   */
+  static isIdeograph(char: string): boolean {
+    return i18n.Unicode.isIdeograph(char);
+  }
+
+
+  /**
+   * 是否空白符 空白符包括空格、制表符、全角空格和不间断空格
+   * @param c
+   * @returns
+   */
+  static isBlankChar(c: number): boolean {
+    return CharUtil.isWhitespace(c.toString())
+      || CharUtil.isSpaceChar(c.toString())
+      || c == 0xFEFF || c == 0x202A || c == 0x0000;
+  }
+
+
+  /**
+   * 检查字符是否位于ASCII范围内(0~127)
+   * @param ch 被检查的字符
+   * @returns `true`表示为ASCII字符,否则为`false`
+   */
+  static isAscii(char: string): boolean {
+    if (char.length === 1) { //确保输入的是单个字符
+      return char.charCodeAt(0) < 128;
+    } else {
+      return false;
+    }
+  }
+
+
+  /**
+   * 判断是否为emoji表情符
+   * @param c 字符
+   * @returns 是否为emoji
+   */
+  static isEmoji(c: number): boolean {
+    const isNotEmoji = (c === 0x0) || (c === 0x9) || (c === 0xA) || (c === 0xD) ||
+      (c >= 0x20 && c == 0xD7FF) || (c >= 0xE000 && c == 0xFFFD) || (c >= 0x100000 && c == 0x10FFFF);
+    return !isNotEmoji;
+  }
+
+
+}

+ 244 - 0
entry/src/main/ets/pages/utils/CryptoHelper.ets

@@ -0,0 +1,244 @@
+import { Base64Util } from './Base64Util';
+import { StrUtil } from '../utils/StrUtil';
+import { crypto } from './crypto';
+import { cryptoFramework } from '@kit.CryptoArchitectureKit';
+import { buffer } from '@kit.ArkTS';
+import { LogUtil } from './LogUtil';
+
+
+/**
+ * 加解密数据类型转换
+ */
+export class CryptoHelper {
+
+
+  /**
+   * 字符串转DataBlob
+   * @param str 字符串
+   * @param coding 编码方式(base64/hex/utf8/utf-8)。
+   * @returns
+   */
+  static strToDataBlob(str: string, coding: crypto.BhuCoding): cryptoFramework.DataBlob {
+    let dataBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(str, coding) };
+    return dataBlob;
+  }
+
+  /**
+   * DataBlob转字符串
+   * @param dataBlob DataBlob
+   * @param coding 编码方式(base64/hex/utf8/utf-8)。
+   * @returns
+   */
+  static dataBlobToStr(dataBlob: cryptoFramework.DataBlob, coding: crypto.BhuCoding): string {
+    return CryptoHelper.uint8ArrayToStr(dataBlob.data, coding);
+  }
+
+
+  /**
+   * 字符串转Uint8Array
+   * @param symKey 字符串
+   * @param coding 编码方式(base64/hex/utf8/utf-8)。
+   * @returns
+   */
+  static strToUint8Array(str: string, coding: crypto.BhuCoding, len: number = 0): Uint8Array {
+    if (coding === 'base64') { //base64
+      let uint8Array = Base64Util.decodeSync(str);
+      uint8Array = CryptoHelper.getUint8ArrayPaddingZero(uint8Array, len)
+      return uint8Array;
+    } else if (coding === 'hex') { //hex-16进制类型
+      let uint8Array = StrUtil.strToHex(str);
+      uint8Array = CryptoHelper.getUint8ArrayPaddingZero(uint8Array, len)
+      return uint8Array;
+    } else {
+      let uint8Array = new Uint8Array(buffer.from(str, coding).buffer);
+      uint8Array = CryptoHelper.getUint8ArrayPaddingZero(uint8Array, len)
+      return uint8Array;
+    }
+  }
+
+
+
+
+
+
+  /**
+   * Uint8Array转字符串
+   * @param arr Uint8Array
+   * @param coding 编码方式(base64/hex/utf8/utf-8)。
+   * @returns
+   */
+  static uint8ArrayToStr(arr: Uint8Array, coding: crypto.BhuCoding): string {
+    if (coding === 'base64') { //base64
+      return Base64Util.encodeToStrSync(arr);
+    } else if (coding === 'hex') { //hex-16进制类型
+      return StrUtil.hexToStr(arr);
+    } else {
+      return buffer.from(arr).toString(coding);
+    }
+  }
+
+
+  // 字符串转成字节流
+  static stringToUint8Array(str: string) {
+    return new Uint8Array(buffer.from(str, 'utf-8').buffer);
+  }
+
+  // 字节流转成可理解的字符串
+  static uint8ArrayToString(array: Uint8Array) {
+    // 将UTF-8编码转换成Unicode编码
+    let out: string = '';
+    let index: number = 0;
+    let len: number = array.length;
+    while (index < len) {
+      let character = array[index++];
+      switch (character >> 4) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+          out += String.fromCharCode(character);
+          break;
+        case 12:
+        case 13:
+          out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F));
+          break;
+        case 14:
+          out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) |
+            ((array[index++] & 0x3F) << 0));
+          break;
+        default:
+          break;
+      }
+    }
+    return out;
+  }
+
+
+  /**
+   * 根据传入的大小生成随机Uint8Array
+   * @param size 生成的串长度
+   * @returns
+   */
+  static getRandomUint8Array(size: number): Uint8Array {
+    let randArray = new Array<number>();
+    for (let i = 0; i < size; i++) {
+      randArray.push(Math.floor(Math.random() * 256));
+    }
+    return new Uint8Array(randArray);
+  }
+
+
+  /**
+   * Uint8Array补零操作
+   * @param len 密钥规格长度
+   * @returns
+   */
+  static getUint8ArrayPaddingZero(uint8Array: Uint8Array, len: number = 0): Uint8Array {
+    if (len > 0 && uint8Array.length < len) {
+      LogUtil.error("uint8Array-补零前: " + uint8Array);
+      let diff = len - uint8Array.length;
+      let randArray = new Array<number>();
+      for (let i = 0; i < diff; i++) {
+        randArray.push(0);
+      }
+      let diffUint8Array = new Uint8Array(diff);
+      let mergeData = new Uint8Array(len);
+      mergeData.set(uint8Array);
+      mergeData.set(diffUint8Array, uint8Array.length);
+      LogUtil.error("uint8Array-补零后: " + mergeData);
+      return mergeData;
+    }
+    return uint8Array;
+  }
+
+
+  /**
+   * 补零操作
+   */
+  static toHexWithPaddingZero(val: bigint) {
+    let length = 64;
+    let c1x = val.toString(16);
+    if (c1x.length > length) {
+      return c1x;
+    }
+    let padLength = length - c1x.length;
+    let returnVal = '';
+    for (let i = 0; i < padLength; i++) {
+      returnVal += '0'
+    }
+    return returnVal += c1x;
+  }
+
+
+  static stringToHex(str: string) {
+    let hex = '';
+    for (let i = 0; i < str.length; i++) {
+      let hexCharCode = str.charCodeAt(i).toString(16);
+      // 确保每个字符的十六进制编码占两位,不足补零
+      hex += ('00' + hexCharCode).slice(-2);
+    }
+    return hex;
+  }
+
+
+  // 字节流转成可理解的字符串
+  static  uint8ArrayToString1(array: Uint8Array) {
+    // 将UTF-8编码转换成Unicode编码
+    let out: string = '';
+    let index: number = 0;
+    let len: number = array.length;
+    while (index < len) {
+      let character = array[index++];
+      switch (character >> 4) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+          out += String.fromCharCode(character);
+          break;
+        case 12:
+        case 13:
+          out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F));
+          break;
+        case 14:
+          out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) |
+            ((array[index++] & 0x3F) << 0));
+          break;
+        default:
+          break;
+      }
+    }
+    return out;
+  }
+
+  // 字符串转成字节流
+  static  stringToUint8Array1(str: string) {
+    return new Uint8Array(buffer.from(str, 'utf-8').buffer);
+  }
+
+  //
+  // function StringToUint8Array(str: String) {
+  //   let arr:number[]=new Array();
+  //   for (let i = 0, j = str.length; i < j; ++i) {
+  //     arr.push(str.charCodeAt(i));
+  //   }
+  //   return new Uint8Array(arr);
+  // }
+  // function Uint8ArrayToString(fileData:Uint8Array) {
+  //   let dataString = '';
+  //   for (let i = 0; i < fileData.length; i++) {
+  //     dataString += String.fromCharCode(fileData[i]);
+  //   }
+  //   return dataString;
+  // }
+
+
+}

+ 627 - 0
entry/src/main/ets/pages/utils/CryptoUtil.ets

@@ -0,0 +1,627 @@
+import { cryptoFramework } from '@kit.CryptoArchitectureKit';
+import { crypto } from './crypto';
+import { CryptoHelper } from './CryptoHelper';
+
+/**
+ * 加解密公用工具类
+ */
+export class CryptoUtil {
+
+
+  /**
+   * 加密,异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static async encrypt(data: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): Promise<cryptoFramework.DataBlob> {
+    let cipher = cryptoFramework.createCipher(transformation);
+    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, params);
+    let cipherData = await cipher.doFinal(data);
+    return cipherData;
+  }
+
+  /**
+   * 加密,同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static encryptSync(data: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): cryptoFramework.DataBlob {
+    let cipher = cryptoFramework.createCipher(transformation);
+    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, params);
+    let cipherData = cipher.doFinalSync(data);
+    return cipherData;
+  }
+
+
+  /**
+   * 解密,异步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static async decrypt(data: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): Promise<cryptoFramework.DataBlob> {
+    let decoder = cryptoFramework.createCipher(transformation);
+    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, params);
+    let decryptData = await decoder.doFinal(data);
+    return decryptData;
+  }
+
+  /**
+   * 解密,同步
+   * @param data 加密或者解密的数据。data不能为null。
+   * @param key 指定加密或解密的密钥。
+   * @param params 指定加密或解密的参数,对于ECB等没有参数的算法模式,可以传入null。API 10之前只支持ParamsSpec, API 10之后增加支持null。
+   * @param transformation 待生成Cipher的算法名称(含密钥长度)、加密模式以及填充方法的组合。
+   * @returns
+   */
+  static decryptSync(data: cryptoFramework.DataBlob, key: cryptoFramework.Key,
+    params: cryptoFramework.ParamsSpec | null, transformation: string): cryptoFramework.DataBlob {
+    let decoder = cryptoFramework.createCipher(transformation);
+    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, key, params);
+    let decryptData = decoder.doFinalSync(data);
+    return decryptData;
+  }
+
+
+  /**
+   * 生成对称密钥SymKey,异步
+   * @param algName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256、3DES192、SM4_128、HMAC|SHA1、等)
+   * @returns
+   */
+  static async generateSymKey(algName: string): Promise<cryptoFramework.SymKey> {
+    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(algName); //创建对称密钥生成器
+    let symKey = await symKeyGenerator.generateSymKey(); //获取该对称密钥生成器随机生成的密钥
+    return symKey;
+  }
+
+  /**
+   * 生成对称密钥SymKey,同步
+   * @param algName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256、3DES192、SM4_128、HMAC|SHA1、等)
+   * @returns
+   */
+  static generateSymKeySync(algName: string): cryptoFramework.SymKey {
+    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(algName); //创建对称密钥生成器
+    let symKey = symKeyGenerator.generateSymKeySync(); //获取该对称密钥生成器随机生成的密钥
+    return symKey;
+  }
+
+
+  /**
+   * 获取转换的对称密钥SymKey,异步
+   * @param key 字符串key
+   * @param algName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256、3DES192、SM4_128、HMAC|SHA1、等)
+   * @param keyCoding 秘钥的编码方式(base64/hex/utf8/utf-8)
+   * @returns
+   */
+  static async getConvertSymKey(algName: string, key: string, keyCoding: crypto.BhuCoding): Promise<cryptoFramework.SymKey> {
+    let symKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(key, keyCoding) };
+    let aesGenerator = cryptoFramework.createSymKeyGenerator(algName);
+    let symKey = await aesGenerator.convertKey(symKeyBlob);
+    return symKey;
+  }
+
+  /**
+   * 获取转换的对称密钥SymKey,同步
+   * @param key 字符串key
+   * @param algName 待生成对称密钥生成器的算法名称(AES128、AES192、AES256、3DES192、SM4_128、HMAC|SHA1、等)
+   * @param keyCoding 秘钥的编码方式(base64/hex/utf8/utf-8)
+   * @returns
+   */
+  static getConvertSymKeySync(algName: string, key: string, keyCoding: crypto.BhuCoding): cryptoFramework.SymKey {
+    let symKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(key, keyCoding) };
+    let aesGenerator = cryptoFramework.createSymKeyGenerator(algName);
+    let symKey = aesGenerator.convertKeySync(symKeyBlob);
+    return symKey;
+  }
+
+
+  /**
+   * 生成非对称密钥KeyPair,异步
+   * @param algName 待生成对称密钥生成器的算法名称(RSA1024、RSA2048、SM2_256、ECC256、等)。
+   * @returns
+   */
+  static async generateKeyPair(algName: string): Promise<cryptoFramework.KeyPair> {
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPair = await asyKeyGenerator.generateKeyPair() //获取该非对称密钥生成器随机生成的密钥
+    return keyPair;
+  }
+
+  /**
+   * 生成非对称密钥KeyPair,同步
+   * @param algName 待生成对称密钥生成器的算法名称(RSA1024、RSA2048、SM2_256、ECC256、等)。
+   * @returns
+   */
+  static generateKeyPairSync(algName: string): cryptoFramework.KeyPair {
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPair = asyKeyGenerator.generateKeyPairSync() //获取该非对称密钥生成器随机生成的密钥
+    return keyPair;
+  }
+
+
+  /**
+   * 获取转换的非对称密钥KeyPair,异步
+   * @param algName 待生成对称密钥生成器的算法名称(RSA1024、RSA2048、SM2_256、ECC256、HMAC|SHA1、等)
+   * @param pubKey 公钥字符串
+   * @param priKey 私钥字符串
+   * @param keyCoding 秘钥的编码方式(base64/hex/utf8/utf-8)
+   * @returns
+   */
+  static async genConvertKeyPair(algName: string, pubKey: string, priKey: string, keyCoding: crypto.BhuCoding): Promise<cryptoFramework.KeyPair> {
+    let pubKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(pubKey, keyCoding) };
+    let priKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(priKey, keyCoding) };
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPair = await asyKeyGenerator.convertKey(pubKeyBlob, priKeyBlob); //获取该非对称密钥生成器随机生成的密钥
+    return keyPair;
+  }
+
+  /**
+   * 获取转换的非对称密钥KeyPair,同步
+   * @param algName 待生成对称密钥生成器的算法名称(RSA1024、RSA2048、SM2_256、ECC256、HMAC|SHA1、等)
+   * @param pubKey 公钥字符串
+   * @param priKey 私钥字符串
+   * @param keyCoding 秘钥的编码方式(base64/hex/utf8/utf-8)
+   * @returns
+   */
+  static genConvertKeyPairSync(algName: string, pubKey: string, priKey: string, keyCoding: crypto.BhuCoding): cryptoFramework.KeyPair {
+    let pubKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(pubKey, keyCoding) };
+    let priKeyBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(priKey, keyCoding) };
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPair = asyKeyGenerator.convertKeySync(pubKeyBlob, priKeyBlob); //获取该非对称密钥生成器随机生成的密钥
+    return keyPair;
+  }
+
+
+
+
+
+
+  /**
+   * 生成IvParamsSpec
+   * @returns
+   */
+  static generateIvParamsSpec() {
+    let dataIv = CryptoHelper.getRandomUint8Array(16);
+    let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
+    let ivParamsSpec: cryptoFramework.IvParamsSpec = { algName: "IvParamsSpec", iv: ivBlob };
+    return ivParamsSpec;
+  }
+
+  /**
+   * 获取生成IvParamsSpec
+   * @param ivStr 字符串iv
+   * @param ivCoding 编码方式(base64/hex/utf8/utf-8)
+   * @returns
+   */
+  static getIvParamsSpec(ivStr: string, ivCoding: crypto.BhuCoding): cryptoFramework.IvParamsSpec {
+    let ivBlob: cryptoFramework.DataBlob = { data: CryptoHelper.strToUint8Array(ivStr, ivCoding) };
+    let ivParamsSpec: cryptoFramework.IvParamsSpec = { algName: "IvParamsSpec", iv: ivBlob };
+    return ivParamsSpec;
+  }
+
+
+  /**
+   * 生成GcmParamsSpec
+   */
+  static generateGcmParamsSpec(): cryptoFramework.GcmParamsSpec {
+    let ivBlob: cryptoFramework.DataBlob = { data: CryptoHelper.getRandomUint8Array(12) };
+    let aadBlob: cryptoFramework.DataBlob = { data: CryptoHelper.getRandomUint8Array(8) };
+    let tagBlob: cryptoFramework.DataBlob = { data: CryptoHelper.getRandomUint8Array(16) };
+    //GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
+    let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
+      iv: ivBlob,
+      aad: aadBlob,
+      authTag: tagBlob,
+      algName: "GcmParamsSpec"
+    };
+    return gcmParamsSpec;
+  }
+
+
+  /**
+   * 获取生成GcmParamsSpec
+   */
+  static getGcmParamsSpec(iv: Uint8Array, aad: Uint8Array, authTag: Uint8Array): cryptoFramework.GcmParamsSpec {
+    let ivBlob: cryptoFramework.DataBlob = { data: iv };
+    let aadBlob: cryptoFramework.DataBlob = { data: aad };
+    let tagBlob: cryptoFramework.DataBlob = { data: authTag };
+    //GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
+    let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
+      iv: ivBlob,
+      aad: aadBlob,
+      authTag: tagBlob,
+      algName: "GcmParamsSpec"
+    };
+    return gcmParamsSpec;
+  }
+
+
+  /**
+   * 对数据进行签名,异步
+   * @param dataBlob 待签名数据
+   * @param priKey 私钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @returns
+   */
+  static async sign(dataBlob: cryptoFramework.DataBlob, priKey: cryptoFramework.PriKey, algName: string): Promise<cryptoFramework.DataBlob> {
+    let signer = cryptoFramework.createSign(algName);
+    await signer.init(priKey);
+    let signData = await signer.sign(dataBlob);
+    return signData;
+  }
+
+  /**
+   * 对数据进行签名,同步
+   * @param dataBlob 待签名数据
+   * @param priKey 私钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @returns
+   */
+  static signSync(dataBlob: cryptoFramework.DataBlob, priKey: cryptoFramework.PriKey, algName: string): cryptoFramework.DataBlob {
+    let signer = cryptoFramework.createSign(algName);
+    signer.initSync(priKey);
+    let signData = signer.signSync(dataBlob);
+    return signData;
+  }
+
+
+  /**
+   * 对数据进行验签,异步
+   * @param dataBlob 待验签数据
+   * @param signDataBlob 签名数据
+   * @param pubKey 公钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @returns
+   */
+  static async verify(dataBlob: cryptoFramework.DataBlob, signDataBlob: cryptoFramework.DataBlob,
+    pubKey: cryptoFramework.PubKey, algName: string): Promise<boolean> {
+    let verifier = cryptoFramework.createVerify(algName);
+    await verifier.init(pubKey);
+    let res = await verifier.verify(dataBlob, signDataBlob);
+    return res;
+  }
+
+  /**
+   * 对数据进行验签,同步
+   * @param dataBlob 待验签数据
+   * @param signDataBlob 签名数据
+   * @param pubKey 公钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @returns
+   */
+  static verifySync(dataBlob: cryptoFramework.DataBlob, signDataBlob: cryptoFramework.DataBlob,
+    pubKey: cryptoFramework.PubKey, algName: string): boolean {
+    let verifier = cryptoFramework.createVerify(algName);
+    verifier.initSync(pubKey);
+    let res = verifier.verifySync(dataBlob, signDataBlob);
+    return res;
+  }
+
+
+  /**
+   * 对数据进行分段签名,异步
+   * @param data 待签名数据
+   * @param priKey 私钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static async signSegment(data: Uint8Array, priKey: cryptoFramework.PriKey, algName: string, len: number): Promise<cryptoFramework.DataBlob> {
+    let signer = cryptoFramework.createSign(algName);
+    await signer.init(priKey);
+    for (let i = 0; i < data.length; i += len) {
+      let updateData = data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      await signer.update(updateDataBlob); //分段update
+    }
+    //已通过分段传入所有明文,故此处sign传入null
+    let signData = await signer.sign(null);
+    return signData;
+  }
+
+  /**
+   * 对数据进行分段签名,同步
+   * @param data 待签名数据
+   * @param priKey 私钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static signSegmentSync(data: Uint8Array, priKey: cryptoFramework.PriKey, algName: string, len: number): cryptoFramework.DataBlob {
+    let signer = cryptoFramework.createSign(algName);
+    signer.initSync(priKey);
+    for (let i = 0; i < data.length; i += len) {
+      let updateData = data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      signer.updateSync(updateDataBlob); //分段update
+    }
+    //已通过分段传入所有明文,故此处sign传入null
+    let signData = signer.signSync(null);
+    return signData;
+  }
+
+
+  /**
+   * 对数据进行分段验签,异步
+   * @param data 待验签数据
+   * @param signDataBlob 签名数据
+   * @param pubKey 公钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static async verifySegment(data: Uint8Array, signDataBlob: cryptoFramework.DataBlob,
+    pubKey: cryptoFramework.PubKey, algName: string, len: number): Promise<boolean> {
+    let verifier = cryptoFramework.createVerify(algName);
+    await verifier.init(pubKey);
+    for (let i = 0; i < data.length; i += len) {
+      let updateData = data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      await verifier.update(updateDataBlob); //分段update
+    }
+    //已通过分段传入所有明文,故此处verify第一个参数传入null
+    let res = await verifier.verify(null, signDataBlob);
+    return res;
+  }
+
+  /**
+   * 对数据进行分段验签,同步
+   * @param data 待验签数据
+   * @param signDataBlob 签名数据
+   * @param pubKey 公钥
+   * @param algName 指定签名算法(RSA1024|PKCS1|SHA256、RSA2048|PKCS1|SHA256、ECC256|SHA256、SM2_256|SM3、、等)。
+   * @param len 自定义的数据拆分长度。
+   * @returns
+   */
+  static verifySegmentSync(data: Uint8Array, signDataBlob: cryptoFramework.DataBlob,
+    pubKey: cryptoFramework.PubKey, algName: string, len: number): boolean {
+    let verifier = cryptoFramework.createVerify(algName);
+    verifier.initSync(pubKey);
+    for (let i = 0; i < data.length; i += len) {
+      let updateData = data.subarray(i, i + len);
+      let updateDataBlob: cryptoFramework.DataBlob = { data: updateData };
+      verifier.updateSync(updateDataBlob); //分段update
+    }
+    //已通过分段传入所有明文,故此处verify第一个参数传入null
+    let res = verifier.verifySync(null, signDataBlob);
+    return res;
+  }
+
+
+  /**
+   * 密钥协商,异步
+   * @param algName 密钥协商算法规格(ECC256、X25519、DH_modp1536、等)
+   * @param pubKey 公钥(一般为外部传入)
+   * @param priKey 私钥
+   * @param coding 编码方式(base64/hex/utf8/utf-8)
+   * @returns 共享密钥
+   */
+  static async dynamicKey(algName: string, pubKey: Uint8Array | string, priKey: Uint8Array | string, coding: crypto.BhuCoding): Promise<string> {
+    if (typeof pubKey === 'string') {
+      pubKey = CryptoHelper.strToUint8Array(pubKey, coding);
+    }
+    if (typeof priKey === 'string') {
+      priKey = CryptoHelper.strToUint8Array(priKey, coding);
+    }
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPairA = await asyKeyGenerator.convertKey({ data: pubKey }, null); //转换公私钥
+    let keyPairB = await asyKeyGenerator.convertKey(null, { data: priKey }); //转换私钥
+    let keyAgreement = cryptoFramework.createKeyAgreement(algName); //使用密钥协商方法之前需要创建该实例进行操作
+    let secret = await keyAgreement.generateSecret(keyPairB.priKey, keyPairA.pubKey); //传入的私钥与公钥进行密钥协商
+    if (secret.data) {
+      return CryptoHelper.uint8ArrayToStr(secret.data, coding);
+    }
+    return "";
+  }
+
+  /**
+   * 密钥协商,同步
+   * @param algName 密钥协商算法规格(ECC256、X25519、DH_modp1536、等)
+   * @param pubKey 公钥(一般为外部传入)
+   * @param priKey 私钥
+   * @param coding 编码方式(base64/hex/utf8/utf-8)
+   * @returns 共享密钥
+   */
+  static dynamicKeySync(algName: string, pubKey: Uint8Array | string, priKey: Uint8Array | string, coding: crypto.BhuCoding): string {
+    if (typeof pubKey === 'string') {
+      pubKey = CryptoHelper.strToUint8Array(pubKey, coding);
+    }
+    if (typeof priKey === 'string') {
+      priKey = CryptoHelper.strToUint8Array(priKey, coding);
+    }
+    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(algName); //非对称密钥生成器的对象。
+    let keyPairA = asyKeyGenerator.convertKeySync({ data: pubKey }, null); //转换公私钥
+    let keyPairB = asyKeyGenerator.convertKeySync(null, { data: priKey }); //转换私钥
+    let keyAgreement = cryptoFramework.createKeyAgreement(algName); //使用密钥协商方法之前需要创建该实例进行操作
+    let secret = keyAgreement.generateSecretSync(keyPairB.priKey, keyPairA.pubKey); //传入的私钥与公钥进行密钥协商
+    if (secret.data) {
+      return CryptoHelper.uint8ArrayToStr(secret.data, coding);
+    }
+    return "";
+  }
+
+
+  /**
+   * 摘要,异步
+   * @param data 待摘要的数据
+   * @param algName 摘要算法名(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param resultCoding 摘要的编码方式(base64/hex)
+   * @returns
+   */
+  static async digest(data: string, algName: string, resultCoding: crypto.BhCoding = 'hex'): Promise<string> {
+    let md = cryptoFramework.createMd(algName);
+    //数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
+    await md.update({ data: CryptoHelper.strToUint8Array(data, 'utf-8') });
+    let dataBlob = await md.digest();
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+  /**
+   * 摘要,同步
+   * @param data 待摘要的数据
+   * @param algName 摘要算法名(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @returns
+   */
+  static digestSync(data: string, algName: string, resultCoding: crypto.BhCoding = 'hex'): string {
+    let md = cryptoFramework.createMd(algName);
+    //数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
+    md.updateSync({ data: CryptoHelper.strToUint8Array(data, 'utf-8') });
+    let dataBlob = md.digestSync();
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+
+  /**
+   * 摘要,分段,同步
+   * @param data 待摘要的数据
+   * @param algName 摘要算法名(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   * @returns
+   */
+  static async digestSegment(data: string, algName: string, resultCoding: crypto.BhCoding = 'hex', len: number = 128): Promise<string> {
+    let md = cryptoFramework.createMd(algName);
+    let messageData = CryptoHelper.strToUint8Array(data, 'utf-8');
+    for (let i = 0; i < messageData.length; i += len) {
+      let updateMessage = messageData.subarray(i, i + len);
+      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
+      await md.update(updateMessageBlob);
+    }
+    let dataBlob = await md.digest();
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+  /**
+   * 摘要,分段,同步
+   * @param data 待摘要的数据
+   * @param algName 摘要算法名(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   * @returns
+   */
+  static digestSegmentSync(data: string, algName: string, resultCoding: crypto.BhCoding = 'hex', len: number = 128): string {
+    let md = cryptoFramework.createMd(algName);
+    let messageData = CryptoHelper.strToUint8Array(data, 'utf-8');
+    for (let i = 0; i < messageData.length; i += len) {
+      let updateMessage = messageData.subarray(i, i + len);
+      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
+      md.updateSync(updateMessageBlob);
+    }
+    let dataBlob = md.digestSync();
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+
+  /**
+   * 消息认证码计算,异步
+   * @param data 传入的消息
+   * @param algName 指定摘要算法(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   */
+  static async hmac(data: string, algName: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex'): Promise<string> {
+    if (typeof symKey === 'string') {
+      symKey = await CryptoUtil.generateSymKey(symKey); //生成对称密钥
+    }
+    let mac = cryptoFramework.createMac(algName);
+    await mac.init(symKey); //使用对称密钥初始化Mac计算
+    //数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
+    await mac.update({ data: CryptoHelper.strToUint8Array(data, 'utf-8') }); //传入消息进行Mac更新计算
+    let dataBlob = await mac.doFinal(); //通过注册回调函数返回Mac的计算结果
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+  /**
+   * 消息认证码计算,同步
+   * @param data 传入的消息
+   * @param algName 指定摘要算法(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   */
+  static hmacSync(data: string, algName: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex'): string {
+    if (typeof symKey === 'string') {
+      symKey = CryptoUtil.generateSymKeySync(symKey); //生成对称密钥
+    }
+    let mac = cryptoFramework.createMac(algName);
+    mac.initSync(symKey); //使用对称密钥初始化Mac计算
+    //数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
+    mac.updateSync({ data: CryptoHelper.strToUint8Array(data, 'utf-8') }); //传入消息进行Mac更新计算
+    let dataBlob = mac.doFinalSync(); //通过注册回调函数返回Mac的计算结果
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+
+  /**
+   * 消息认证码计算,分段,异步
+   * @param data 传入的消息
+   * @param algName 指定摘要算法(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   */
+  static async hmacSegment(data: string, algName: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex', len: number = 128): Promise<string> {
+    if (typeof symKey === 'string') {
+      symKey = await CryptoUtil.generateSymKey(symKey); //生成对称密钥
+    }
+    let messageData = CryptoHelper.strToUint8Array(data, 'utf-8');
+    let mac = cryptoFramework.createMac(algName);
+    await mac.init(symKey); //使用对称密钥初始化Mac计算
+    for (let i = 0; i < messageData.length; i += len) {
+      let updateMessage = messageData.subarray(i, i + len);
+      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
+      await mac.update(updateMessageBlob); //传入消息进行Mac更新计算
+    }
+    let dataBlob = await mac.doFinal(); //通过注册回调函数返回Mac的计算结果
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+  /**
+   * 消息认证码计算,分段,同步
+   * @param data 传入的消息
+   * @param algName 指定摘要算法(SHA1、SHA224、SHA256、SHA384、SHA512、MD5、SM3)。
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   */
+  static hmacSegmentSync(data: string, algName: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex', len: number = 128): string {
+    if (typeof symKey === 'string') {
+      symKey = CryptoUtil.generateSymKeySync(symKey); //生成对称密钥
+    }
+    let messageData = CryptoHelper.strToUint8Array(data, 'utf-8');
+    let mac = cryptoFramework.createMac(algName);
+    mac.initSync(symKey); //使用对称密钥初始化Mac计算
+    for (let i = 0; i < messageData.length; i += len) {
+      let updateMessage = messageData.subarray(i, i + len);
+      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
+      mac.updateSync(updateMessageBlob); //传入消息进行Mac更新计算
+    }
+    let dataBlob = mac.doFinalSync(); //通过注册回调函数返回Mac的计算结果
+    let result = CryptoHelper.uint8ArrayToStr(dataBlob.data, resultCoding);
+    return result;
+  }
+
+
+
+}

+ 133 - 0
entry/src/main/ets/pages/utils/LogUtil.ets

@@ -0,0 +1,133 @@
+import hilog from '@ohos.hilog'
+import { BusinessError } from '@kit.BasicServicesKit'
+
+const LOGGER_DOMAIN: number = 0x0000
+const LOGGER_TAG: string = 'HarmonyLogUtil'
+
+/**
+ * 日志工具类
+ */
+export class LogUtil {
+  private static domain: number = LOGGER_DOMAIN
+  private static tag: string = LOGGER_TAG //日志Tag
+  private static format: string = '%{public}s'
+  private static showLog: boolean = true //是否显示打印日志
+
+
+  /**
+   * 初始化日志参数(该方法建议在Ability里调用)
+   * @param domain
+   * @param tag
+   * @param showLog
+   */
+  static init(domain: number = LOGGER_DOMAIN, tag: string = LOGGER_TAG, showLog: boolean = true) {
+    LogUtil.domain = domain
+    LogUtil.tag = tag
+    LogUtil.showLog = showLog
+  }
+
+  /**
+   * 设置日志对应的领域标识,范围是0x0~0xFFFF。(该方法建议在Ability里调用)
+   * @param domain
+   */
+  static setDomain(domain: number = LOGGER_DOMAIN) {
+    LogUtil.domain = domain
+  }
+
+  /**
+   * 设置日志标识(该方法建议在Ability里调用)
+   * @param tag
+   */
+  static setTag(tag: string = LOGGER_TAG) {
+    LogUtil.tag = tag
+  }
+
+  /**
+   * 是否打印日志(该方法建议在Ability里调用)
+   * @param showLog
+   */
+  static setShowLog(showLog: boolean = true) {
+    LogUtil.showLog = showLog
+  }
+
+  /**
+   * 打印DEBUG级别日志
+   * @param args
+   */
+  static debug(...args: string[]): void {
+    if (LogUtil.showLog) {
+      hilog.debug(LogUtil.domain, LogUtil.tag, LogUtil.format.repeat(args.length), args)
+    }
+  }
+
+  /**
+   * 打印INFO级别日志
+   * @param args
+   */
+  static info(...args: string[]): void {
+    if (LogUtil.showLog) {
+      hilog.info(LogUtil.domain, LogUtil.tag, LogUtil.format.repeat(args.length), args)
+    }
+  }
+
+  /**
+   * 打印WARN级别日志
+   * @param args
+   */
+  static warn(...args: string[]): void {
+    if (LogUtil.showLog) {
+      hilog.warn(LogUtil.domain, LogUtil.tag, LogUtil.format.repeat(args.length), args)
+    }
+  }
+
+  /**
+   * 打印ERROR级别日志
+   * @param args
+   */
+  static error(...args: string[]): void {
+    if (LogUtil.showLog) {
+      hilog.error(LogUtil.domain, LogUtil.tag, LogUtil.format.repeat(args.length), args)
+    }
+  }
+
+  /**
+   * 打印FATAL级别日志
+   * @param args
+   */
+  static fatal(...args: string[]): void {
+    if (LogUtil.showLog) {
+      hilog.fatal(LogUtil.domain, LogUtil.tag, LogUtil.format.repeat(args.length), args)
+    }
+  }
+
+
+  /**
+   * 打印JSON对象和JSON字符串
+   * @param obj
+   */
+  static print(obj: object | string) {
+    try {
+      if (typeof obj === 'object') {
+        let str = JSON.stringify(obj, null, 2)
+        let arr: string[] = str.split('\n')
+        for (let index = 0; index < arr.length; index++) {
+          console.debug(arr[index])
+        }
+      } else {
+        obj = JSON.parse(obj)
+        let str = JSON.stringify(obj, null, 2)
+        let arr = str.split('\n')
+        for (let index = 0; index < arr.length; index++) {
+          console.debug(arr[index])
+        }
+      }
+    } catch (err) {
+      let error = err as BusinessError; //异常了,说明不是JSON字符串
+      LogUtil.error(`LogUtil-print-异常 ~ code: ${error.code} -·- message: ${error.message}`);
+    }
+  }
+
+
+}
+
+// export default new LogUtil() //单例(在ES6模块中,当你使用 import 导入一个模块时,实际上是在导入该模块的值的一个引用。这意味着在另一个模块中修改该值会影响原始模块中的值。)

+ 104 - 0
entry/src/main/ets/pages/utils/MD5.ets

@@ -0,0 +1,104 @@
+import { crypto } from './crypto';
+import { CryptoUtil } from './CryptoUtil';
+import { cryptoFramework } from '@kit.CryptoArchitectureKit';
+
+
+/**
+ * MD5工具类
+ */
+export class MD5 {
+
+
+  /**
+   * MD5摘要,同步
+   * @param data 待摘要的数据
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @returns
+   */
+  static async digest(data: string, resultCoding: crypto.BhCoding = 'hex'): Promise<string> {
+    return CryptoUtil.digest(data, 'MD5', resultCoding);
+  }
+
+  /**
+   * MD5摘要,同步
+   * @param data 待摘要的数据
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @returns
+   */
+  static digestSync(data: string, resultCoding: crypto.BhCoding = 'hex'): string {
+    return CryptoUtil.digestSync(data, 'MD5', resultCoding);
+  }
+
+
+  /**
+   * MD5摘要,分段,同步
+   * @param data 待摘要的数据
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   * @returns
+   */
+  static async digestSegment(data: string, resultCoding: crypto.BhCoding = 'hex', len: number = 120): Promise<string> {
+    return CryptoUtil.digestSegment(data, 'MD5', resultCoding, len);
+  }
+
+  /**
+   * MD5摘要,分段,同步
+   * @param data 待摘要的数据
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   * @returns
+   */
+  static digestSegmentSync(data: string, resultCoding: crypto.BhCoding = 'hex', len: number = 120): string {
+    return CryptoUtil.digestSegmentSync(data, 'MD5', resultCoding, len);
+  }
+
+
+  /**
+   * 消息认证码计算,异步
+   * @param data 传入的消息
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   */
+  static async hmac(data: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex'): Promise<string> {
+    return CryptoUtil.hmac(data, 'MD5', symKey, resultCoding);
+  }
+
+  /**
+   * 消息认证码计算,同步
+   * @param data 传入的消息
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   */
+  static hmacSync(data: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex'): string {
+    return CryptoUtil.hmacSync(data, 'MD5', symKey, resultCoding);
+  }
+
+
+  /**
+   * 消息认证码计算,分段,异步
+   * @param data 传入的消息
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   */
+  static async hmacSegment(data: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex', len: number = 120): Promise<string> {
+    return CryptoUtil.hmacSegment(data, 'MD5', symKey, resultCoding, len);
+  }
+
+  /**
+   * 消息认证码计算,分段,同步
+   * @param data 传入的消息
+   * @param symKey 共享对称密钥, 当symKey为string时,生成对称密钥(AES128、AES256)。
+   * @param resultCoding 摘要的编码方式(base64/hex),默认不传为hex。
+   * @param len 自定义的数据拆分长度
+   */
+  static hmacSegmentSync(data: string, symKey: cryptoFramework.SymKey | string = 'AES256',
+    resultCoding: crypto.BhCoding = 'hex', len: number = 120): string {
+    return CryptoUtil.hmacSegmentSync(data, 'MD5', symKey, resultCoding, len);
+  }
+
+
+}

+ 21 - 0
entry/src/main/ets/pages/utils/MyContext.ets

@@ -0,0 +1,21 @@
+
+export default class GlobalContext {
+  private constructor() { }
+  private static instance: GlobalContext;
+  private _objects = new Map<string, Object>();
+
+  public static getContext(): GlobalContext {
+    if (!GlobalContext.instance) {
+      GlobalContext.instance = new GlobalContext();
+    }
+    return GlobalContext.instance;
+  }
+
+  getObject(value: string): Object | undefined {
+    return this._objects.get(value);
+  }
+
+  setObject(key: string, objectClass: Object): void {
+    this._objects.set(key, objectClass);
+  }
+}

+ 389 - 0
entry/src/main/ets/pages/utils/StrUtil.ets

@@ -0,0 +1,389 @@
+import { CharUtil } from './CharUtil';
+import util from '@ohos.util';
+import { buffer } from '@kit.ArkTS';
+import { Base64Util } from './Base64Util';
+import { i18n } from '@kit.LocalizationKit';
+
+
+/**
+ * 字符串工具类
+ */
+export class StrUtil {
+
+  private constructor() {}
+
+
+  /**
+   * 字符串是否为空(undefined、null)
+   * @param str 被检测的字符串
+   * @returns 是否为空
+   */
+  static isNull(str: string | undefined | null): boolean {
+    return str == undefined || str == null;
+  }
+
+  /**
+   * 判断字符串是否为非空。true为非空空,否则false
+   * @param str
+   * @returns
+   */
+  static isNotNull(str: string | undefined | null) {
+    return false == StrUtil.isNull(str);
+  }
+
+
+  /**
+   * 字符串是否为空(undefined、null、字符串长度为0)
+   * @param str 被检测的字符串
+   * @return 是否为空
+   */
+  static isEmpty(str: string | undefined | null): boolean {
+    return str == undefined || str == null || str.length == 0;
+  }
+
+  /**
+   * 判断字符串是否为非空。true为非空空,否则false
+   * @param str
+   * @returns
+   */
+  static isNotEmpty(str: string | undefined | null) {
+    return false == StrUtil.isEmpty(str);
+  }
+
+
+  /**
+   * 判断字符串是否为空和空白符(空白符包括空格、制表符、全角空格和不间断空格)。true为空,否则false
+   * @param str
+   * @returns
+   */
+  static isBlank(str: string | undefined | null): boolean {
+    let length: number;
+    if ((str == undefined) || (str == null) || ((length = str.length) == 0)) {
+      return true;
+    }
+    for (let i = 0; i < length; i++) {
+      if (false == CharUtil.isBlankChar(str.charCodeAt(i))) {
+        return false;  //只要有一个非空字符即为非空字符串
+      }
+    }
+    return true;
+  }
+
+  /**
+   * 判断字符串是否为非空和空白符(空白符包括空格、制表符、全角空格和不间断空格)true为非空,否则false
+   * @param str
+   * @returns
+   */
+  static isNotBlank(str: string | undefined | null): boolean {
+    return false == StrUtil.isBlank(str);
+  }
+
+
+  /**
+   * 格式化字符串
+   * @param source
+   * @param defaultValue
+   * @returns
+   */
+  static toStr(source: string | null | undefined, defaultValue = "") {
+    if (source == null || source == undefined) {
+      return defaultValue;
+    }
+    return String(source);
+  }
+
+
+  /**
+   * 替换字符串中匹配的正则为给定的字符串
+   * @param str   待替换的字符串
+   * @param pattern  要匹配的内容正则或字符串
+   * @param replacement 替换的内容
+   * @returns 返回替换后的字符串
+   */
+  static replace(str: string, pattern: RegExp | string, replacement: string = ''): string {
+    return str.replace(pattern, replacement);
+  }
+
+  /**
+   * 替换字符串中所有匹配的正则为给定的字符串
+   * @param str   待替换的字符串
+   * @param pattern  要匹配的内容正则或字符串
+   * @param replacement 替换的内容
+   * @returns 返回替换后的字符串
+   */
+  static replaceAll(str: string, pattern: RegExp | string, replacement: string = ''): string {
+    return str.replaceAll(pattern, replacement);
+  }
+
+  /**
+   * 检查字符串是否以给定的字符串开头
+   * @param string 要检索的字符串
+   * @param target 要检索字符
+   * @param position 检索的位置
+   * @returns 如果字符串以字符串开头,那么返回 true,否则返回 false
+   */
+  static startsWith(string: string = '', target: string, position: number = 0): boolean {
+    return string.startsWith(target, position);
+  }
+
+
+  /**
+   * 检查字符串是否以给定的字符串结尾
+   * @param str 要检索的字符串
+   * @param target 要检索字符
+   * @param position 检索的位置
+   * @returns 如果字符串以字符串结尾,那么返回 true,否则返回 false
+   */
+  static endsWith(str: string = '', target: string, position: number = str.length): boolean {
+    return str.endsWith(target, position);
+  }
+
+
+  /**
+   * 将字符串重复指定次数
+   * @param str  要重复的字符串
+   * @param n  重复的次数
+   * @returns
+   */
+  static repeat(str: string = '', n: number = 1): string {
+    return str.repeat(n);
+  }
+
+
+  /**
+   * 转换整个字符串的字符为小写
+   * @param str 要转换的字符串
+   * @returns 返回小写的字符串
+   */
+  static toLower(str: string = ''): string {
+    return str.toLowerCase();
+  }
+
+
+  /**
+   * 转换整个字符串的字符为大写
+   * @param str 要转换的字符串
+   * @returns 返回小写的字符串
+   */
+  static toUpper(str: string = ''): string {
+    return str.toUpperCase();
+  }
+
+
+  /**
+   * 转换字符串首字母为大写,剩下为小写
+   * @param str 待转换的字符串
+   * @returns 转换后的
+   */
+  static capitalize(str: string = ''): string {
+    if (!str) {
+      return '';
+    }
+    const firstChar = str.charAt(0).toUpperCase();
+    const restChars = str.slice(1).toLowerCase();
+    return firstChar + restChars;
+  }
+
+
+  /**
+   * 判断两个传入的数值或者是字符串是否相等
+   * @param source
+   * @param target
+   * @returns
+   */
+  static equal(source: string | number, target: string | number): boolean {
+    return source === target;
+  }
+
+  /**
+   * 判断两个传入的数值或者是字符串是否不相等
+   * @param source
+   * @param target
+   * @returns
+   */
+  static notEqual(source: string | number, target: string | number): boolean {
+    return false == StrUtil.equal(source, target);
+  }
+
+
+  /**
+   * 字符串转Uint8Array
+   * @param src 字符串
+   * @returns Uint8Array
+   */
+  public static strToUint8Array(src: string, encoding: buffer.BufferEncoding = 'utf-8'): Uint8Array {
+    let textEncoder = new util.TextEncoder(encoding);
+    let result = textEncoder.encodeInto(src);
+    return result;
+  }
+
+  /**
+   * Uint8Array转字符串
+   * @param src Uint8Array
+   * @returns 字符串
+   */
+  static unit8ArrayToStr(src: Uint8Array, encoding: buffer.BufferEncoding = 'utf-8'): string {
+    let textDecoder = util.TextDecoder.create(encoding, { ignoreBOM: true })
+    let result = textDecoder.decodeWithStream(src, { stream: true });
+    return result;
+  }
+
+
+  /**
+   * 16进制字符串转换unit8Array
+   * @param hexStr
+   * @returns
+   */
+  static strToHex(hexStr: string): Uint8Array {
+    return new Uint8Array(buffer.from(hexStr, 'hex').buffer);
+  }
+
+  /**
+   * 16进制unit8Array转字符串
+   * @param arr
+   * @returns
+   */
+  static hexToStr(arr: Uint8Array): string {
+    return buffer.from(arr).toString('hex');
+  }
+
+
+  /**
+   * 字符串转Base64字符串
+   * @param src 字符串
+   * @returns
+   */
+  static strToBase64(src: string): string {
+    let uint8Array = StrUtil.strToUint8Array(src);
+    let result = Base64Util.encodeToStrSync(uint8Array);
+    return result;
+  }
+
+
+  /**
+   * Base64字符串转字符串
+   * @param base64Str Base64字符串
+   * @returns
+   */
+  static base64ToStr(base64Str: string): string {
+    let uint8Array = Base64Util.decodeSync(base64Str);
+    let result = StrUtil.unit8ArrayToStr(uint8Array);
+    return result;
+  }
+
+
+  /**
+   * 字符串转ArrayBuffer
+   * @param str
+   * @returns
+   */
+  static strToBuffer(src: string, encoding: buffer.BufferEncoding = 'utf-8'): ArrayBuffer {
+    let buf = buffer.from(src, encoding);
+    return buf.buffer;
+  }
+
+  /**
+   * ArrayBuffer转字符串
+   * @param str
+   * @returns
+   */
+  static bufferToStr(src: ArrayBuffer, encoding: buffer.BufferEncoding = 'utf-8'): string {
+    let buf = buffer.from(src);
+    let result = buf.toString(encoding);
+    return result;
+  }
+
+
+  /**
+   * ArrayBuffer转Uint8Array
+   * @param str
+   * @returns
+   */
+  static bufferToUint8Array(src: ArrayBuffer): Uint8Array {
+    return new Uint8Array(src);
+  }
+
+  /**
+   * Uint8Array转ArrayBuffer
+   * @param str
+   * @returns
+   */
+  static unit8ArrayToBuffer(src: Uint8Array): ArrayBuffer {
+    // return buffer.from(src).buffer;
+    return src.buffer as ArrayBuffer;
+  }
+
+
+  /**
+   * 判断传入的电话号码格式是否正确。
+   * @param phone
+   * country string 表示电话号码所属国家或地区代码。
+   * options PhoneNumberFormatOptions 电话号码格式化对象的相关选项。默认值:NATIONAL。
+   * @returns
+   */
+  static isPhone(phone: string, country: string = "CN", option?: i18n.PhoneNumberFormatOptions): boolean {
+    let phoneNumberFormat: i18n.PhoneNumberFormat = new i18n.PhoneNumberFormat(country, option);
+    return phoneNumberFormat.isValidNumber(phone);
+  }
+
+  /**
+   * 对电话号码进行格式化
+   * @param phone
+   * country string 表示电话号码所属国家或地区代码。
+   * options PhoneNumberFormatOptions 电话号码格式化对象的相关选项。默认值:NATIONAL。
+   * @returns
+   */
+  static getPhoneFormat(phone: string, country: string = "CN", option?: i18n.PhoneNumberFormatOptions): string {
+    let phoneNumberFormat: i18n.PhoneNumberFormat = new i18n.PhoneNumberFormat(country, option);
+    return phoneNumberFormat.format(phone);
+  }
+
+  /**
+   * 获取电话号码归属地
+   * @param phone
+   * @param locale string 区域ID
+   * country string 表示电话号码所属国家或地区代码。
+   * options PhoneNumberFormatOptions 电话号码格式化对象的相关选项。默认值:NATIONAL。
+   * @returns
+   */
+  static getPhoneLocationName(phone: string, locale: string = "zh-CN", country: string = "CN", option?: i18n.PhoneNumberFormatOptions): string {
+    let phoneNumberFormat: i18n.PhoneNumberFormat = new i18n.PhoneNumberFormat(country, option);
+    return phoneNumberFormat.getLocationName(phone, locale);
+  }
+
+
+  /**
+   * 给定内容是否匹配正则
+   * @param content 内容
+   * @param regex   正则
+   */
+  static isMatch(content: string, pattern: string): boolean {
+    if (content == undefined || content == null) {
+      return false;
+    } else {
+      return new RegExp(pattern).test(content);
+    }
+  }
+
+  /**
+   * 判断传入的邮箱格式是否正确
+   * @param content
+   * @returns
+   */
+  static isEmail(content: string): boolean {
+    const pattern: string = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])"; //邮件,符合RFC 5322规范,正则来自:http://emailregex.com/
+    return StrUtil.isMatch(content, pattern);
+  }
+
+
+  /**
+   * 获取系统错误码对应的详细信息
+   * @param errno 错误码
+   * @returns
+   */
+  static getErrnoToString(errno: number): string {
+    return util.errnoToString(errno);
+  }
+
+
+}

+ 11 - 0
entry/src/main/ets/pages/utils/crypto.ets

@@ -0,0 +1,11 @@
+/**
+ * 类型约束
+ */
+export declare namespace crypto {
+
+  type BhuCoding = 'base64' | 'hex' | 'utf8' | 'utf-8';
+  type BhCoding = 'base64' | 'hex';
+
+  type SHA = 'SHA1' | 'SHA224' | 'SHA256' | 'SHA384' | 'SHA512';
+
+}

+ 72 - 0
entry/src/main/module.json5

@@ -0,0 +1,72 @@
+{
+  "module": {
+    "name": "entry",
+    "type": "entry",
+    "description": "$string:module_desc",
+    "mainElement": "EntryAbility",
+    "deviceTypes": [
+      "phone",
+      "tablet"
+    ],
+    "deliveryWithInstall": true,
+    "installationFree": false,
+    "pages": "$profile:main_pages",
+    "abilities": [
+      {
+        "name": "EntryAbility",
+        "srcEntry": "./ets/entryability/EntryAbility.ets",
+        "description": "$string:EntryAbility_desc",
+        "icon": "$media:layered_image",
+        "label": "$string:EntryAbility_label",
+        "startWindowIcon": "$media:startIcon",
+        "startWindowBackground": "$color:start_window_background",
+        "exported": true,
+        "skills": [
+          {
+            "entities": [
+              "entity.system.home"
+            ],
+            "actions": [
+              "action.system.home"
+            ]
+          }
+        ],
+        "removeMissionAfterTerminate": true
+      }
+    ],
+    "extensionAbilities": [
+      {
+        "name": "EntryBackupAbility",
+        "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+        "type": "backup",
+        "exported": false,
+        "metadata": [
+          {
+            "name": "ohos.extension.backup",
+            "resource": "$profile:backup_config"
+          }
+        ],
+      }
+    ],
+    "requestPermissions":[
+      {
+        "name" : "ohos.permission.GET_NETWORK_INFO",
+        "usedScene": {
+          "abilities": [
+            "AppAbility"
+          ],
+          "when":"always"
+        }
+      },
+      {
+        "name" : "ohos.permission.INTERNET",
+        "usedScene": {
+          "abilities": [
+            "AppAbility"
+          ],
+          "when":"always"
+        }
+      }
+    ]
+  }
+}

+ 8 - 0
entry/src/main/resources/base/element/color.json

@@ -0,0 +1,8 @@
+{
+  "color": [
+    {
+      "name": "start_window_background",
+      "value": "#FFFFFF"
+    }
+  ]
+}

+ 16 - 0
entry/src/main/resources/base/element/string.json

@@ -0,0 +1,16 @@
+{
+  "string": [
+    {
+      "name": "module_desc",
+      "value": "module description"
+    },
+    {
+      "name": "EntryAbility_desc",
+      "value": "description"
+    },
+    {
+      "name": "EntryAbility_label",
+      "value": "剑鱼标讯"
+    }
+  ]
+}

BIN
entry/src/main/resources/base/media/background.png


BIN
entry/src/main/resources/base/media/foreground.png


+ 7 - 0
entry/src/main/resources/base/media/layered_image.json

@@ -0,0 +1,7 @@
+{
+  "layered-image":
+  {
+    "background" : "$media:background",
+    "foreground" : "$media:foreground"
+  }
+}

BIN
entry/src/main/resources/base/media/startIcon.png


+ 3 - 0
entry/src/main/resources/base/profile/backup_config.json

@@ -0,0 +1,3 @@
+{
+  "allowToBackupRestore": true
+}

+ 5 - 0
entry/src/main/resources/base/profile/main_pages.json

@@ -0,0 +1,5 @@
+{
+  "src": [
+    "pages/Index"
+  ]
+}

+ 16 - 0
entry/src/main/resources/en_US/element/string.json

@@ -0,0 +1,16 @@
+{
+  "string": [
+    {
+      "name": "module_desc",
+      "value": "module description"
+    },
+    {
+      "name": "EntryAbility_desc",
+      "value": "description"
+    },
+    {
+      "name": "EntryAbility_label",
+      "value": "剑鱼标讯"
+    }
+  ]
+}

+ 16 - 0
entry/src/main/resources/zh_CN/element/string.json

@@ -0,0 +1,16 @@
+{
+  "string": [
+    {
+      "name": "module_desc",
+      "value": "模块描述"
+    },
+    {
+      "name": "EntryAbility_desc",
+      "value": "description"
+    },
+    {
+      "name": "EntryAbility_label",
+      "value": "剑鱼标讯"
+    }
+  ]
+}

+ 2 - 0
entry/src/mock/mock-config.json5

@@ -0,0 +1,2 @@
+{
+}

+ 35 - 0
entry/src/ohosTest/ets/test/Ability.test.ets

@@ -0,0 +1,35 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+  describe('ActsAbilityTest', () => {
+    // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+    beforeAll(() => {
+      // Presets an action, which is performed only once before all test cases of the test suite start.
+      // This API supports only one parameter: preset action function.
+    })
+    beforeEach(() => {
+      // Presets an action, which is performed before each unit test case starts.
+      // The number of execution times is the same as the number of test cases defined by **it**.
+      // This API supports only one parameter: preset action function.
+    })
+    afterEach(() => {
+      // Presets a clear action, which is performed after each unit test case ends.
+      // The number of execution times is the same as the number of test cases defined by **it**.
+      // This API supports only one parameter: clear action function.
+    })
+    afterAll(() => {
+      // Presets a clear action, which is performed after all test cases of the test suite end.
+      // This API supports only one parameter: clear action function.
+    })
+    it('assertContain', 0, () => {
+      // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+      hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+      let a = 'abc';
+      let b = 'b';
+      // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+      expect(a).assertContain(b);
+      expect(a).assertEqual(a);
+    })
+  })
+}

+ 5 - 0
entry/src/ohosTest/ets/test/List.test.ets

@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+  abilityTest();
+}

+ 12 - 0
entry/src/ohosTest/module.json5

@@ -0,0 +1,12 @@
+{
+  "module": {
+    "name": "entry_test",
+    "type": "feature",
+    "deviceTypes": [
+      "phone",
+      "tablet"
+    ],
+    "deliveryWithInstall": true,
+    "installationFree": false
+  }
+}

+ 7 - 0
entry/src/test/List.test.ets

@@ -0,0 +1,7 @@
+import LocalFuncTest from './LocalFunc.test'
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+  localUnitTest();
+  LocalFuncTest()
+}

+ 33 - 0
entry/src/test/LocalUnit.test.ets

@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+  describe('localUnitTest', () => {
+    // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+    beforeAll(() => {
+      // Presets an action, which is performed only once before all test cases of the test suite start.
+      // This API supports only one parameter: preset action function.
+    });
+    beforeEach(() => {
+      // Presets an action, which is performed before each unit test case starts.
+      // The number of execution times is the same as the number of test cases defined by **it**.
+      // This API supports only one parameter: preset action function.
+    });
+    afterEach(() => {
+      // Presets a clear action, which is performed after each unit test case ends.
+      // The number of execution times is the same as the number of test cases defined by **it**.
+      // This API supports only one parameter: clear action function.
+    });
+    afterAll(() => {
+      // Presets a clear action, which is performed after all test cases of the test suite end.
+      // This API supports only one parameter: clear action function.
+    });
+    it('assertContain', 0, () => {
+      // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+      let a = 'abc';
+      let b = 'b';
+      // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+      expect(a).assertContain(b);
+      expect(a).assertEqual(a);
+    });
+  });
+}

+ 22 - 0
hvigor/hvigor-config.json5

@@ -0,0 +1,22 @@
+{
+  "modelVersion": "5.0.0",
+  "dependencies": {
+  },
+  "execution": {
+    // "analyze": "normal",                     /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+    // "daemon": true,                          /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+    // "incremental": true,                     /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+    // "parallel": true,                        /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+    // "typeCheck": false,                      /* Enable typeCheck. Value: [ true | false ]. Default: false */
+  },
+  "logging": {
+    // "level": "info"                          /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+  },
+  "debugging": {
+    // "stacktrace": false                      /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+  },
+  "nodeOptions": {
+    // "maxOldSpaceSize": 8192                  /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+    // "exposeGC": true                         /* Enable to trigger garbage collection explicitly. Default: true*/
+  }
+}

+ 6 - 0
hvigorfile.ts

@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+    system: appTasks,  /* Built-in plugin of Hvigor. It cannot be modified. */
+    plugins:[]         /* Custom plugin to extend the functionality of Hvigor. */
+}

+ 27 - 0
oh-package-lock.json5

@@ -0,0 +1,27 @@
+{
+  "meta": {
+    "stableOrder": true
+  },
+  "lockfileVersion": 3,
+  "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+  "specifiers": {
+    "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+    "@ohos/hypium@1.0.19": "@ohos/hypium@1.0.19"
+  },
+  "packages": {
+    "@ohos/hamock@1.0.0": {
+      "name": "@ohos/hamock",
+      "version": "1.0.0",
+      "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+      "registryType": "ohpm"
+    },
+    "@ohos/hypium@1.0.19": {
+      "name": "@ohos/hypium",
+      "version": "1.0.19",
+      "integrity": "sha512-cEjDgLFCm3cWZDeRXk7agBUkPqjWxUo6AQeiu0gEkb3J8ESqlduQLSIXeo3cCsm8U/asL7iKjF85ZyOuufAGSQ==",
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.19.har",
+      "registryType": "ohpm"
+    }
+  }
+}

+ 10 - 0
oh-package.json5

@@ -0,0 +1,10 @@
+{
+  "modelVersion": "5.0.0",
+  "description": "Please describe the basic information.",
+  "dependencies": {
+  },
+  "devDependencies": {
+    "@ohos/hypium": "1.0.19",
+    "@ohos/hamock": "1.0.0"
+  }
+}