欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開(kāi)發(fā)案例:【字符串加解密】

jf_46214456 ? 來(lái)源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-21 21:36 ? 次閱讀

介紹

本Codelab針對(duì)用戶隱私安全,使用加密算法API對(duì)密碼進(jìn)行加密存儲(chǔ),模擬開(kāi)發(fā)一個(gè)用戶注冊(cè)登錄應(yīng)用。實(shí)現(xiàn)如下功能:

  1. 實(shí)現(xiàn)登錄、注冊(cè)、登錄成功頁(yè)面。
  2. 注冊(cè)的用戶數(shù)據(jù)保存到關(guān)系型數(shù)據(jù)庫(kù)。
  3. 登錄時(shí)通過(guò)查詢數(shù)據(jù)庫(kù)校驗(yàn)用戶是否存在、密碼是否正確。
  4. 密碼通過(guò)加密算法保存和使用。

相關(guān)概念

  • [加解密算法庫(kù)框架]:為屏蔽底層硬件和算法庫(kù),向上提供統(tǒng)一的密碼算法庫(kù)加解密相關(guān)接口。
  • [關(guān)系型數(shù)據(jù)庫(kù)]:關(guān)系型數(shù)據(jù)庫(kù)(Relational Database,RDB)是一種基于關(guān)系模型來(lái)管理數(shù)據(jù)的數(shù)據(jù)庫(kù)。

環(huán)境搭建

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開(kāi)發(fā)板類(lèi)型:[潤(rùn)和RK3568開(kāi)發(fā)板]。
  • OpenHarmony系統(tǒng):3.2 Release。

環(huán)境搭建

完成本篇Codelab我們首先要完成開(kāi)發(fā)環(huán)境的搭建,本示例以RK3568開(kāi)發(fā)板為例,參照以下步驟進(jìn)行:

  1. [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開(kāi)發(fā)板的燒錄](méi)
  3. 搭建開(kāi)發(fā)環(huán)境。
    1. 開(kāi)始前請(qǐng)參考[工具準(zhǔn)備],完成DevEco Studio的安裝和開(kāi)發(fā)環(huán)境配置。
    2. 開(kāi)發(fā)環(huán)境配置完成后,請(qǐng)參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”)。
    3. 工程創(chuàng)建完成后,選擇使用[真機(jī)進(jìn)行調(diào)測(cè)]。
    4. 鴻蒙開(kāi)發(fā)指導(dǎo)文檔:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md點(diǎn)擊或者復(fù)制轉(zhuǎn)到。

代碼結(jié)構(gòu)解讀

HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151547.png

本篇Codelab只對(duì)核心代碼進(jìn)行講解,對(duì)于完整代碼,我們會(huì)在gitee中提供。

├──entry/src/main/ets                   // 代碼區(qū)
│  ├──common
│  │  ├──constants
│  │  │  └──CommonConstants.ets         // 公共常量類(lèi)
│  │  └──utils
│  │     ├──AesUtil.ets                 // 加解密工具類(lèi)
│  │     ├──DataTransformUtil.ets       // 數(shù)據(jù)轉(zhuǎn)換工具類(lèi)
│  │     ├──Logger.ets                  // 日志打印工具類(lèi)
│  │     └──PromptUtil.ts               // 彈窗工具類(lèi)
│  ├──entryability
│  │  └──EntryAbility.ts                // 程序入口類(lèi)
│  ├──model
│  │  ├──RdbModel.ets                   // 數(shù)據(jù)庫(kù)業(yè)務(wù)處理文件
│  │  └──UserTableApi.ets               // 用戶表具體業(yè)務(wù)文件
│  ├──pages
│  │  ├──Login.ets                      // 登錄頁(yè)
│  │  ├──Register.ets                   // 注冊(cè)頁(yè)
│  │  └──Welcome.ets                    // 歡迎頁(yè)
│  └──viewmodel
│     └──User.ets                       // 用戶實(shí)體類(lèi)
└──entry/src/main/resources             // 資源文件目錄

關(guān)系型數(shù)據(jù)庫(kù)

首先編寫(xiě)創(chuàng)建表的SQL語(yǔ)句,其中user為表名、id為主鍵并自動(dòng)遞增、username為用戶名、password為加密后的密碼、authTag為加解密認(rèn)證信息

// CommonConstants.ets
  /**
   * 創(chuàng)建表的SQL語(yǔ)句
   */
  static readonly CREATE_TABLE_SQL: string = 'CREATE TABLE IF NOT EXISTS user(' +
    'id INTEGER PRIMARY KEY AUTOINCREMENT, ' +
    'username TEXT NOT NULL, ' +
    'password TEXT NOT NULL, ' +
    'authTag TEXT NOT NULL)';

在RdbModel的構(gòu)造方法中,調(diào)用getRdbStore方法創(chuàng)建數(shù)據(jù)庫(kù)。其中STORE_CONFIG為數(shù)據(jù)庫(kù)相關(guān)配置,sqlCreateTable為創(chuàng)建user用戶表所需的SQL語(yǔ)句。

// RdbModel.ets
import dataRdb from '@ohos.data.relationalStore';
...
export class RdbModel {
  private rdbStore: dataRdb.RdbStore | null = null;
  private tableName: string = '';
  private sqlCreateTable: string = '';
  ...
  constructor(tableName: string, sqlCreateTable: string, columns: Array< string >) {
    this.tableName = tableName;
    this.sqlCreateTable = sqlCreateTable;
    this.columns = columns;
    this.getRdbStore();
  }

  /**
   * 獲取數(shù)據(jù)庫(kù)操作對(duì)象rdbStore.
   */
  getRdbStore() {
    let getPromiseRdb = dataRdb.getRdbStore(getContext(), { name: CommonConstants.DATABASE_NAME, securityLevel: dataRdb.SecurityLevel.S1 });
    getPromiseRdb.then(rdbStore = > {
      this.rdbStore = rdbStore;
      this.rdbStore.executeSql(this.sqlCreateTable);
    }).catch((err: Error) = > {
      Logger.error(`getRdbStore err ${JSON.stringify(err)}`);
    });
  }

創(chuàng)建UserTableApi.ets文件,實(shí)例化RdbModel創(chuàng)建userTable對(duì)象。并對(duì)外提供可操作用戶數(shù)據(jù)表的API接口,包括插入數(shù)據(jù)、根據(jù)用戶名查詢用戶信息等方法。

// UserTableApi.ets
export class UserTableApi {
  private userTable = new RdbModel(TABLE_NAME, CREATE_USER_TABLE, COLUMNS);

  /**
   * 將數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中
   *
   * @param user 需要保存的User類(lèi)型的數(shù)據(jù)對(duì)象
   */
  insertUserData(user: User) {
    this.userTable.insertData(user);
  }

  /**
   * 根據(jù)用戶名查詢用戶信息
   *
   * @param username 查詢的用戶名
   * @returns 查詢結(jié)果集
   */
  async queryUserByUsername(username: string): Promise< User[] > {
    let resultList: Array< User >;
    // 過(guò)濾條件
    let predicates = new dataRdb.RdbPredicates(TABLE_NAME);
    predicates.equalTo('username', username);
    // 將查詢到的結(jié)果封裝成User對(duì)應(yīng)的用戶信息
    let ret = await this.userTable.query(predicates);
    resultList = this.getListFromResultSet(ret);
    return resultList;
  }
  ...
}

密碼加解密

創(chuàng)建AesUtil工具類(lèi),封裝加解密相關(guān)邏輯。首先引入@ohos.security.cryptoFramework包,在構(gòu)造方法中初始化加解密算法框架所需的環(huán)境,包括密鑰規(guī)格的選擇、加解密規(guī)格的選擇等。本示例采用對(duì)稱(chēng)AES加解密算法,密鑰長(zhǎng)度為256位,分組模式為GCM。具體有以下步驟:

  1. 創(chuàng)建對(duì)稱(chēng)密鑰生成器。
  2. 通過(guò)密鑰生成器生成對(duì)稱(chēng)密鑰。
  3. 創(chuàng)建加解密生成器。
  4. 通過(guò)加解密生成器加密或解密數(shù)據(jù)。

說(shuō)明: 對(duì)于對(duì)稱(chēng)密鑰、非對(duì)稱(chēng)密鑰、加解密算法模式。

// AesUtil.ets
import cryptoFramework from '@ohos.security.cryptoFramework';
...
class AesUtil {
  private globalCipher: cryptoFramework.Cipher = cryptoFramework.createCipher(CommonConstants.GENERATOR_NAME;
  private globalKey: cryptoFramework.SymKey = null;

  /**
   * 構(gòu)造函數(shù)初始化加解密環(huán)境、生成密鑰
   */
  constructor() {
    let symAlgName = CommonConstants.ENCRYPTION_MODE;
    // 創(chuàng)建對(duì)稱(chēng)密鑰生成器
    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
    // 通過(guò)密鑰生成器和keyMaterialBlob生成256位長(zhǎng)度的對(duì)稱(chēng)密鑰
    let keyMaterialBlob = this.genKeyMaterialBlob(CommonConstants.KEY_DATA);
    symKeyGenerator.convertKey(keyMaterialBlob, (err, symKey) = > {
      if (err) {
        Logger.error(`Convert symKey failed, ${err.code}, ${err.message}`);
        return;
      }
      this.globalKey = symKey;
      let cipherAlgName = CommonConstants.GENERATOR_NAME;
      try {
        // 生成加解密生成器
        this.globalCipher = cryptoFramework.createCipher(cipherAlgName);
      } catch (error) {
        Logger.error(`createCipher failed, error is ${JSON.stringify(err)}`);
      }
    });
  }

  // 加密
  async encrypt(content: string, authTag: string): Promise< string > {
    ...
  }

  // 解密 
  async decrypt(content: string, authTag: string): Promise< string > {
    ...
  }
}

密碼加密

由于加密算法采用GCM分組模式,在加密前需要獲取GCM模式加解密所需的參數(shù)GcmParamsSpec。依次生成長(zhǎng)度為12字節(jié)、8字節(jié)、16字節(jié)的DataBlob類(lèi)型的數(shù)據(jù),并封裝成GcmParamsSpec對(duì)象。

// AesUtil.ets
class AesUtil {
  ...
  /**
   * 獲取GCM分組加解密所需的參數(shù)
   *
   * @returns 返回加密所需參數(shù)的promise實(shí)例
   */
  async genGcmParamsSpec(): Promise< cryptoFramework.GcmParamsSpec > {
    let ivBlob: cryptoFramework.DataBlob = this.genKeyMaterialBlob(CommonConstants.GCM_IV_DATA);
    let aadBlob: cryptoFramework.DataBlob = this.genKeyMaterialBlob(CommonConstants.GCM_AAD_DATA);
    let tagBlob: cryptoFramework.DataBlob = this.genKeyMaterialBlob(CommonConstants.GCM_TAG_DATA);
    let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
      iv: ivBlob,
      aad: aadBlob,
      authTag: tagBlob,
      algName: `GcmParamsSpec`
    };
    return gcmParamsSpec;
  }

  /**
   * 根據(jù)數(shù)據(jù)組生成DataBlob類(lèi)型的數(shù)據(jù)
   *
   * @param data 需要封裝的數(shù)據(jù)
   * @returns Blob DataBlob類(lèi)型的數(shù)據(jù)
   */
  genKeyMaterialBlob(data: Array< number >): cryptoFramework.DataBlob {
    let keyMaterial = new Uint8Array(data);
    return { data: keyMaterial };
  }
}

在AesUtil.ets的encrypt方法中實(shí)現(xiàn)密碼加密邏輯。由于本示例加密數(shù)據(jù)量較小,所以這里直接使用update一步完成加密操作。若數(shù)據(jù)量較大,可通過(guò)update方法分段加密。主要實(shí)現(xiàn)以下步驟:

  1. 調(diào)用Cipher的init方法初始化加密環(huán)境。設(shè)置mode為ENCRYPT_MODE,傳入密鑰和生成的gcmParams。
  2. 將用戶輸入的密碼轉(zhuǎn)換為Uint8Array數(shù)組,進(jìn)而封裝成DataBlob對(duì)象。
  3. 將封裝好的plainTextBlob傳入update方法中完成加密。
  4. 調(diào)用doFinal方法,傳入null,取出加密后的認(rèn)證信息authTag。
  5. 取出Uint8Array類(lèi)型的加密數(shù)據(jù)和authTag,轉(zhuǎn)換成Base64類(lèi)型的字符串,封裝成User類(lèi)型返回。
// AesUtil.ets
class AesUtil {
  ...
  /**
   * 加密
   *
   * @param content 加密內(nèi)容
   * @returns 返回?cái)y帶密文User對(duì)象的promise實(shí)例
   */
  async encrypt(content: string): Promise< User > {
    // 初始化加密環(huán)境
    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
    let gcmParams = await this.genGcmParamsSpec();
    await this.globalCipher.init(mode, this.globalKey, gcmParams);
    let plainTextBlob = {
      // 字符串轉(zhuǎn)Uint8Array
      data: DataTransformUtil.stringToUint8Array(content)
    };
    // 加密
    let updateOutput: cryptoFramework.DataBlob = await this.globalCipher.update(plainTextBlob);
    if (!updateOutput) {
      return Promise.reject('encrypt updateOutput is null');
    }
    let authTag: cryptoFramework.DataBlob = await this.globalCipher.doFinal(null);
    // Uint8Array轉(zhuǎn)base64
    let encryptContent: string = DataTransformUtil.uint8ArrayToBase64(updateOutput.data);
    let authTagContent: string = DataTransformUtil.uint8ArrayToBase64(authTag.data);
    let user = new User(null, ``, encryptContent, authTagContent);
    return user;
  }
}

密碼解密

解密操作與加密類(lèi)似,主要實(shí)現(xiàn)以下步驟:

  1. 調(diào)用Cipher的init方法初始化解密環(huán)境,設(shè)置mode為DECRYPT_MODE,傳入攜帶authTag認(rèn)證信息的gcmParams。
  2. 將Base64類(lèi)型密文轉(zhuǎn)換為Uint8Array數(shù)組,進(jìn)而封裝成DataBlob對(duì)象。
  3. 將封裝好的plainTextBlob傳入doFinal方法中完成解密。
  4. 取出Uint8Array類(lèi)型的解密數(shù)據(jù),轉(zhuǎn)換成字符串并返回。
// AesUtil.ets
class AesUtil {
  ...

  /**
   * 解密
   *
   * @param content 解密內(nèi)容
   * @param authTag GCM 解密所需認(rèn)證信息內(nèi)容
   * @returns 返回解密內(nèi)容的promise實(shí)例
   */
  async decrypt(content: string, authTag: string): Promise< string > {
    // 初始化解密環(huán)境
    let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
    let gcmParams = await this.genGcmParamsSpec();
    let authTagBlob: cryptoFramework.DataBlob = {
      data: DataTransformUtil.base64ToUint8Array(authTag)
    };
    gcmParams.authTag = authTagBlob;
    await this.globalCipher.init(mode, this.globalKey, gcmParams);
    let plainTextBlob: cryptoFramework.DataBlob = {
      // base64轉(zhuǎn)Uint8Array
      data: DataTransformUtil.base64ToUint8Array(content)
    };
    // 解密
    let finalOutput: cryptoFramework.DataBlob = await this.globalCipher.doFinal(plainTextBlob);
    if (!finalOutput) {
      return Promise.reject('decrypt finalOutput is null');
    }
    // Uint8Array轉(zhuǎn)字符串
    let decryptContent = DataTransformUtil.uint8ArrayToString(finalOutput.data);
    return decryptContent;
  }
}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    585

    瀏覽量

    20613
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2397

    瀏覽量

    43098
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1983

    瀏覽量

    30640
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3753

    瀏覽量

    16669
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    十六進(jìn)制字符串AES是如何分組的?

    文章目錄產(chǎn)生的疑問(wèn)十六進(jìn)制字符串AES是如何分組的?AES是目前最流行的分組對(duì)稱(chēng)加密算法,在開(kāi)發(fā)的過(guò)程中,無(wú)處不在。Intel甚至在他們的芯片中定制了底層指令來(lái)讓AES更快地執(zhí)行,所以AES加解密
    發(fā)表于 07-22 08:25

    字符串的表示

    字符串的表示  隨著計(jì)算機(jī)在文字處理與信息管理中的廣泛應(yīng)用, 字符串已成為最常用的數(shù)據(jù)類(lèi)型之一, 許多計(jì)算機(jī)中都提供字符串操作功能, 一些計(jì)算機(jī)還給出讀寫(xiě)字
    發(fā)表于 10-13 17:11 ?3095次閱讀
    <b class='flag-5'>字符串</b>的表示

    C語(yǔ)言教程之字符串加密和解密

    C語(yǔ)言教程之字符串加密和解密,很好的C語(yǔ)言資料,快來(lái)學(xué)習(xí)吧。
    發(fā)表于 04-25 15:49 ?0次下載

    python字符串拼接方式了解

    python字符串拼接的方式 在Python的實(shí)際開(kāi)發(fā)中,很多都需要用到字符串拼接,python中字符串拼接有很多,今天總結(jié)一下: 用+符號(hào)拼接 用%符號(hào)拼接 用join()方法拼接
    發(fā)表于 12-06 10:09 ?1052次閱讀

    什么是復(fù)制字符串?Python如何復(fù)制字符串

    連續(xù)幾篇文章都在寫(xiě) Python 字符串,這出乎我的意料了。但是,有的問(wèn)題,不寫(xiě)不行,特別是那種靈機(jī)一動(dòng)想到的問(wèn)題,最后你發(fā)現(xiàn),很多人根本不懂卻又誤以為自己懂了。那就繼續(xù)刨根問(wèn)底,探究個(gè)明白吧
    發(fā)表于 11-25 10:32 ?3063次閱讀

    strtok拆分字符串

    大家好,我是驚覺(jué),今天聊聊字符串。字符串的使用場(chǎng)景非常之多,人機(jī)交互和雙機(jī)通信都會(huì)用到。比如:通過(guò)串口向單片機(jī)發(fā)送指令,以執(zhí)行操作或配置參數(shù)。單片機(jī)讀取傳感器數(shù)據(jù),數(shù)據(jù)格式是字符串。一般GPS數(shù)據(jù)
    發(fā)表于 01-13 15:46 ?8次下載
    strtok拆分<b class='flag-5'>字符串</b>

    字符串函數(shù)重寫(xiě)練習(xí)

    字符串函數(shù)重寫(xiě)練習(xí):字符串比較、字符串拼接、字符串查找、字符串拷貝、內(nèi)存比較、內(nèi)存拷貝、內(nèi)存初始化、內(nèi)存比較、二維數(shù)組定義及基本使用、位運(yùn)算
    的頭像 發(fā)表于 05-05 15:02 ?2040次閱讀

    字符串操作

    labview字符串操作
    發(fā)表于 06-28 15:09 ?2次下載

    C語(yǔ)言總結(jié)_字符串全方位練習(xí)

    C語(yǔ)言字符串全方位練習(xí),涉及知識(shí)點(diǎn):字符串解析、大小寫(xiě)判斷、字符串插入、字符串刪除、字符串排序、字符串
    的頭像 發(fā)表于 08-14 09:41 ?1574次閱讀

    一文詳解JavaScript字符串

    JavaScript字符串是原始值。此外,字符串是不可變的。這意味著如果你修改一個(gè)字符串,你總是會(huì)得到一個(gè)新的字符串。原始字符串不會(huì)被改變。
    的頭像 發(fā)表于 12-08 16:36 ?1265次閱讀

    python字符串有哪些特定方法

    python字符串序列操作也適用于列表和元組。 python字符串還有獨(dú)有方法,即字符串對(duì)象的函數(shù),其他對(duì)象不可調(diào)用,只有字符串對(duì)象可調(diào)用。
    的頭像 發(fā)表于 02-23 15:02 ?768次閱讀

    C語(yǔ)言字符串的引用方式

    在C語(yǔ)言程序中,字符串是存放在字符數(shù)組中的。 2. 用字符數(shù)組存放一個(gè)字符串,可以通過(guò)數(shù)組名和下標(biāo)引用字符串中的一個(gè)
    的頭像 發(fā)表于 03-10 14:57 ?2013次閱讀

    字符串的相關(guān)知識(shí)

    TCL 中的數(shù)據(jù)類(lèi)型只有一種:字符串。這些字符串可以是字母、數(shù)字、布爾值、標(biāo)點(diǎn)符號(hào)等特殊字符的組合。在某些特殊命令的作用下,字符串可以向其他數(shù)據(jù)類(lèi)型轉(zhuǎn)換。下面將系統(tǒng)的講解或回顧下
    的頭像 發(fā)表于 03-29 11:41 ?1197次閱讀

    labview掃描字符串怎么用

    LabVIEW 是一種流程化編程語(yǔ)言和開(kāi)發(fā)環(huán)境,主要用于控制、測(cè)量和監(jiān)測(cè)系統(tǒng)。在 LabVIEW 中,掃描字符串是一項(xiàng)常見(jiàn)的任務(wù),它允許用戶按照一定的模式從輸入字符串中提取所需的信息。下面我將詳細(xì)
    的頭像 發(fā)表于 12-29 10:12 ?2200次閱讀

    labview字符串如何轉(zhuǎn)換為16進(jìn)制字符串

    在LabVIEW中,將字符串轉(zhuǎn)換為16進(jìn)制字符串是一個(gè)常見(jiàn)的需求,尤其是在處理數(shù)據(jù)通信和硬件接口時(shí)。LabVIEW提供了多種方法來(lái)實(shí)現(xiàn)這一轉(zhuǎn)換,包括使用內(nèi)置函數(shù)、編寫(xiě)VI(Virtual
    的頭像 發(fā)表于 09-04 15:54 ?3103次閱讀