欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rust_cargo

本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。

完整的过程可以参考一下:

【OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南】


一、ring 库完整介绍

1. 是什么

ring 是 Rust 工业级安全密码学库,底层基于 BoringSSL,API 设计防误用,强制使用现代安全算法,屏蔽不安全老旧加密模式(如 CBC、MD5),rustls TLS 库底层就是 ring,多用于后端加密、接口签名、用户密码存储、数据加解密。

2. 核心能力

  1. 哈希摘要:SHA256/SHA384/SHA512(替代MD5,用于文件校验、数据指纹)
  2. HMAC 消息签名:接口验签、防篡改(对应前端 crypto-js HMAC)
  3. AEAD 对称加密:AES-GCM、ChaCha20-Poly1305(自带完整性校验,最安全对称加密)
  4. 密码加盐哈希 PBKDF2:用户密码存储,不存明文
  5. 数字签名:Ed25519、RSA、ECDSA(公私钥签名验签,替代 jsencrypt)
  6. 安全随机数生成:生成密钥、IV、盐值
  7. 密钥交换 ECDH/X25519:前后端密钥协商

3. 优势

  • 强制安全参数,不会写出弱加密;
  • 带硬件AES-NI/ARM NEON加速;
  • 恒定时间运算,抵抗计时侧信道攻击;
  • 跨平台:Linux/macOS/Windows/嵌入式/Wasm。

4. 典型业务场景

  • 用户登录密码加盐存储
  • HTTP接口HMAC签名防篡改
  • 敏感数据AES-GCM加密(手机号、身份证)
  • JWT/自定义Token签名校验
  • 文件完整性SHA校验
  • 客户端-服务端非对称签名通信

二、安装依赖

Cargo.toml

[package]
name = "ring_demo"
version = "0.1.0"
edition = "2021"

[dependencies]
ring = "0.17"
hex = "0.4" # 用于把二进制密文/哈希转十六进制打印

安装命令

cargo add ring hex

请添加图片描述

三、完整无报错 main.rs(覆盖5大高频场景)

use ring::rand::SecureRandom;
use ring::signature::KeyPair;
use ring::{
    aead, digest, hmac, pbkdf2, rand::SystemRandom, signature,
};
use hex::encode;
use std::num::NonZeroU32;

fn main() {
    println!("===== 1. SHA256 哈希摘要(数据指纹) =====");
    demo_sha256();

    println!("\n===== 2. HMAC-SHA256 接口签名验签 =====");
    demo_hmac();

    println!("\n===== 3. AES-GCM 对称加解密(敏感数据) =====");
    demo_aes_gcm();

    println!("\n===== 4. PBKDF2 密码加盐哈希(存储用户密码) =====");
    demo_pbkdf2();

    println!("\n===== 5. Ed25519 公私钥签名验签(替代RSA/jsencrypt) =====");
    demo_ed25519();
}

/// 1. SHA256 哈希
fn demo_sha256() {
    let text = "用户原始明文数据 13800138000";
    let data = text.as_bytes();
    let hash_result = digest::digest(&digest::SHA256, data);
    println!("原文:{}", text);
    println!("SHA256(hex): {}", encode(hash_result.as_ref()));
}

/// 2. HMAC-SHA256 签名校验
fn demo_hmac() {
    let rng = SystemRandom::new();
    let mut key_buf = [0u8; 32];
    rng.fill(&mut key_buf).unwrap();
    let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &key_buf);

    let msg_text = "order_id=10086&amount=99.9";
    let msg = msg_text.as_bytes();
    let sign = hmac::sign(&hmac_key, msg);
    let sign_hex = encode(sign.as_ref());
    println!("待签名报文:{}", msg_text);
    println!("HMAC签名hex:{}", sign_hex);

    hmac::verify(&hmac_key, msg, sign.as_ref()).expect("签名校验失败");
    println!("✅ 签名校验通过");
}

/// 3. AES-GCM 加解密(修复nonce move所有权错误)
fn demo_aes_gcm() {
    let rng = SystemRandom::new();
    let mut key_raw = [0u8; 32];
    rng.fill(&mut key_raw).unwrap();
    let key = aead::LessSafeKey::new(aead::UnboundKey::new(&aead::AES_256_GCM, &key_raw).unwrap());

    let mut nonce_raw = [0u8; 12];
    rng.fill(&mut nonce_raw).unwrap();
    // 每次使用从原始字节重新构造Nonce,避免所有权转移
    let build_nonce = || aead::Nonce::try_assume_unique_for_key(&nonce_raw).unwrap();

    let plain_text = "身份证 440101199901011234";
    let plaintext = plain_text.as_bytes();
    let mut buffer = plaintext.to_vec();
    // 加密
    key.seal_in_place_append_tag(build_nonce(), aead::Aad::empty(), &mut buffer).unwrap();

    println!("AES-GCM密文+tag hex:{}", encode(&buffer));
    println!("随机Nonce hex:{}", encode(&nonce_raw));

    // 解密,重新构造新Nonce实例,不占用原有所有权
    let mut cipher_copy = buffer.clone();
    let plain_slice = key.open_in_place(build_nonce(), aead::Aad::empty(), &mut cipher_copy).unwrap();
    println!("解密原文:{}", String::from_utf8_lossy(plain_slice));
}

/// 4. PBKDF2 密码哈希
fn demo_pbkdf2() {
    let rng = SystemRandom::new();
    let mut salt = [0u8; 16];
    rng.fill(&mut salt).unwrap();
    let password = b"user123456";

    let mut hash_out = [0u8; 32];
    pbkdf2::derive(
        pbkdf2::PBKDF2_HMAC_SHA256,
        NonZeroU32::new(100_000).unwrap(),
        &salt,
        password,
        &mut hash_out,
    );

    println!("密码盐值hex:{}", encode(&salt));
    println!("PBKDF2密码哈希hex:{}", encode(&hash_out));

    let user_input_pwd = b"user123456";
    pbkdf2::verify(
        pbkdf2::PBKDF2_HMAC_SHA256,
        NonZeroU32::new(100_000).unwrap(),
        &salt,
        user_input_pwd,
        &hash_out,
    ).unwrap();
    println!("✅ 密码校验正确");
}

/// 5. Ed25519 签名验签
fn demo_ed25519() {
    let rng = SystemRandom::new();
    let pkcs8_doc = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
    let key_pair = signature::Ed25519KeyPair::from_pkcs8(pkcs8_doc.as_ref()).unwrap();

    let pub_key_bytes = key_pair.public_key();
    let data_text = "admin login request";
    let data = data_text.as_bytes();

    let sig = key_pair.sign(data);
    let sig_hex = encode(sig.as_ref());
    println!("Ed25519签名hex:{}", sig_hex);

    let verifier = signature::UnparsedPublicKey::new(&signature::ED25519, pub_key_bytes.as_ref());
    verifier.verify(data, sig.as_ref()).unwrap();
    println!("✅ Ed25519签名验证通过");
}

请添加图片描述

1. 库简介

ring 是 Rust 底层工业级密码学库,基于 BoringSSL,强制使用安全加密算法,屏蔽 MD5、CBC 等弱加密;常用于接口签名、用户密码存储、敏感数据加密、公私钥鉴权。

2. 依赖 Cargo.toml

[dependencies]
ring = "0.17.14"
hex = "0.4"
  • ring:加密核心库
  • hex:二进制字节转十六进制字符串,方便控制台打印密文、哈希值

3. 头部导入说明

use ring::rand::SecureRandom; // 随机数trait,提供fill填充字节方法
use ring::signature::KeyPair; // 密钥对trait,获取公钥public_key()
use ring::{
    aead,       // AES-GCM 对称加密模块
    digest,     // SHA256等哈希摘要
    hmac,       // HMAC接口签名验签
    pbkdf2,     // 密码加盐哈希(存储用户密码)
    rand::SystemRandom, // 系统安全随机数生成器
    signature,  // Ed25519非对称签名验签
};
use hex::encode; // 二进制转十六进制字符串
use std::num::NonZeroU32; // 无零整数,PBKDF2迭代次数要求非0

4. 入口 main 函数

依次执行5个加密场景示例,覆盖开发最常用5类加密需求:

  1. SHA256 哈希(文件/数据指纹)
  2. HMAC-SHA256(接口请求防篡改签名)
  3. AES-GCM(手机号/身份证等敏感数据对称加密)
  4. PBKDF2(用户登录密码加盐哈希存储,不存明文)
  5. Ed25519 椭圆曲线公私钥签名(轻量替代RSA/jsencrypt)

二、分函数逐行解析

1. demo_sha256 SHA256不可逆哈希

fn demo_sha256() {
    let text = "用户原始明文数据 13800138000";
    let data = text.as_bytes();
    let hash_result = digest::digest(&digest::SHA256, data);
    println!("原文:{}", text);
    println!("SHA256(hex): {}", encode(hash_result.as_ref()));
}

逻辑说明

  1. 不用 b"中文" 字节字面量(Rust 禁止非ASCII字节串),先定义字符串再 .as_bytes() 转二进制;
  2. digest::digest(算法, 数据):输入任意二进制,输出固定32字节哈希;
  3. 特性:不可逆,只能用于校验完整性,不能加密解密;
  4. 业务场景:文件校验、请求参数指纹、唯一标识生成。

2. demo_hmac HMAC-SHA256 对称签名

fn demo_hmac() {
    let rng = SystemRandom::new();
    let mut key_buf = [0u8; 32];
    rng.fill(&mut key_buf).unwrap();
    let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &key_buf);

    let msg_text = "order_id=10086&amount=99.9";
    let msg = msg_text.as_bytes();
    let sign = hmac::sign(&hmac_key, msg);
    let sign_hex = encode(sign.as_ref());
    println!("待签名报文:{}", msg_text);
    println!("HMAC签名hex:{}", sign_hex);

    hmac::verify(&hmac_key, msg, sign.as_ref()).expect("签名校验失败");
    println!("✅ 签名校验通过");
}

流程拆解

  1. SystemRandom::new() 系统安全随机源,fill 填充32字节随机密钥;
  2. hmac::Key::new(算法, 密钥字节) 构造签名密钥;
  3. hmac::sign(密钥, 报文) 生成签名;
  4. hmac::verify(密钥, 原始报文, 签名) 校验签名,篡改报文直接报错;

业务场景

前后端约定同一个密钥,请求携带签名,后端校验防篡改、防伪造请求。

3. demo_aes_gcm AES-GCM 现代安全对称加密

fn demo_aes_gcm() {
    let rng = SystemRandom::new();
    let mut key_raw = [0u8; 32];
    rng.fill(&mut key_raw).unwrap();
    let key = aead::LessSafeKey::new(aead::UnboundKey::new(&aead::AES_256_GCM, &key_raw).unwrap());

    let mut nonce_raw = [0u8; 12];
    rng.fill(&mut nonce_raw).unwrap();
    // 闭包重复构造Nonce,解决所有权move报错
    let build_nonce = || aead::Nonce::try_assume_unique_for_key(&nonce_raw).unwrap();

    let plain_text = "身份证 440101199901011234";
    let plaintext = plain_text.as_bytes();
    let mut buffer = plaintext.to_vec();
    // 加密:自动追加16位校验tag到buffer末尾
    key.seal_in_place_append_tag(build_nonce(), aead::Aad::empty(), &mut buffer).unwrap();

    println!("AES-GCM密文+tag hex:{}", encode(&buffer));
    println!("随机Nonce hex:{}", encode(&nonce_raw));

    // 解密
    let mut cipher_copy = buffer.clone();
    let plain_slice = key.open_in_place(build_nonce(), aead::Aad::empty(), &mut cipher_copy).unwrap();
    println!("解密原文:{}", String::from_utf8_lossy(plain_slice));
}

核心知识点

  1. AES256-GCM:AEAD 认证加密,自带防篡改校验tag,比CBC安全;
  2. 密钥固定32字节,nonce固定12字节(标准规范,不可复用同一个nonce加密两次);
  3. Nonce 无Copy特征,一次使用所有权转移,所以封装闭包每次从原始字节新建实例,解决 moved value 编译报错;
  4. seal_in_place_append_tag:原地加密,密文尾部自动拼接16字节校验标签;
  5. open_in_place:自动分离末尾tag校验,数据被篡改直接panic;
  6. Aad::empty():附加校验数据(业务可传入请求ID、时间戳增强校验);

业务场景

加密身份证、银行卡、手机号等敏感隐私数据存储/传输。

4. demo_pbkdf2 PBKDF2 用户密码加盐哈希

fn demo_pbkdf2() {
    let rng = SystemRandom::new();
    let mut salt = [0u8; 16];
    rng.fill(&mut salt).unwrap();
    let password = b"user123456";

    let mut hash_out = [0u8; 32];
    pbkdf2::derive(
        pbkdf2::PBKDF2_HMAC_SHA256,
        NonZeroU32::new(100_000).unwrap(),
        &salt,
        password,
        &mut hash_out,
    );

    println!("密码盐值hex:{}", encode(&salt));
    println!("PBKDF2密码哈希hex:{}", encode(&hash_out));

    let user_input_pwd = b"user123456";
    pbkdf2::verify(
        pbkdf2::PBKDF2_HMAC_SHA256,
        NonZeroU32::new(100_000).unwrap(),
        &salt,
        user_input_pwd,
        &hash_out,
    ).unwrap();
    println!("✅ 密码校验正确");
}

关键逻辑(用户登录核心)

  1. salt:每个用户独立随机盐值,16字节,和哈希结果一起存入数据库;
  2. PBKDF2_HMAC_SHA256:密码慢哈希算法,迭代10万次增加暴力破解成本;
  3. pbkdf2::derive:注册时,原始密码+盐值生成哈希存入数据库,不存明文密码
  4. pbkdf2::verify:登录时,用户输入密码 + 数据库存储的盐值,重新计算哈希比对;

安全要点

禁止直接SHA256存储密码,无盐哈希极易彩虹表爆破,PBKDF2是web标准密码存储方案。

5. demo_ed25519 Ed25519 椭圆曲线非对称签名

fn demo_ed25519() {
    let rng = SystemRandom::new();
    // 生成PKCS8格式私钥文档
    let pkcs8_doc = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
    let key_pair = signature::Ed25519KeyPair::from_pkcs8(pkcs8_doc.as_ref()).unwrap();

    let pub_key_bytes = key_pair.public_key();
    let data_text = "admin login request";
    let data = data_text.as_bytes();

    // 私钥签名
    let sig = key_pair.sign(data);
    let sig_hex = encode(sig.as_ref());
    println!("Ed25519签名hex:{}", sig_hex);

    // 公钥验签
    let verifier = signature::UnparsedPublicKey::new(&signature::ED25519, pub_key_bytes.as_ref());
    verifier.verify(data, sig.as_ref()).unwrap();
    println!("✅ Ed25519签名验证通过");
}

公私钥流程

  1. generate_pkcs8:生成Ed25519私钥,返回文档对象;
  2. from_pkcs8:从私钥文档还原密钥对;
  3. key_pair.public_key():提取公钥(可公开分发);
  4. key_pair.sign()私钥签名,仅持有私钥的一方能生成签名;
  5. UnparsedPublicKey::new(算法, 公钥) 构造验证器,用公钥校验签名;

优势&场景

对比RSA:密钥更短、签名速度更快;用于API开放平台鉴权、登录Token签名、分布式服务通信验签。

三、通用公共知识点

  1. 随机数统一使用 SystemRandom,硬件安全随机源,不用rand普通伪随机;
  2. ring 内部错误类型 Unspecified 不实现标准 Error trait,不能用 ?,统一 .unwrap()
  3. 所有二进制输出用 hex::encode 转十六进制,控制台可读;
  4. 凡是无Copy的结构体(Nonce、密钥等),不能重复使用所有权,要么重新构造,要么传引用;
  5. 区分三类加密场景:
    • 哈希:不可逆,校验完整性
    • AES-GCM:对称加解密,同一密钥加密解密
    • Ed25519/HMAC:签名验签,防伪造、防篡改

四、逐模块详细解释

1. SHA256 哈希 digest

digest::digest(&digest::SHA256, data)

输入任意二进制,输出固定32字节哈希;用于文件校验、数据唯一指纹,不可逆,无法解密。

2. HMAC-SHA256 hmac(接口签名)

流程:

  1. 生成32字节随机密钥(前后端约定)
  2. 对请求报文签名
  3. 后端用相同密钥重新计算HMAC比对
    优势:防篡改,中间人修改报文后端校验直接失败。

3. AES-GCM aead(推荐对称加密)

ring 只提供现代 AEAD 加密,不支持不安全的 CBC

  • nonce:12字节随机数,每次加密必须唯一,不可复用;
  • 加密后密文尾部自动附加16字节Tag,解密时校验数据是否被篡改;
  • 适合加密手机号、身份证、银行卡等敏感业务字段。

4. PBKDF2 pbkdf2(用户密码存储核心)

永远不要明文存用户密码:

  1. 每个用户生成独立随机盐salt;
  2. 多次迭代哈希(10万次),暴力破解成本极高;
  3. 登录时用输入密码+同盐重新计算比对。

5. Ed25519 signature(非对称签名,替代RSA/jsencrypt)

  • 私钥签名(服务端/客户端持有)
  • 公钥验签(公开分发)
  • 比RSA密钥短、速度更快,适合接口Token、登录鉴权

五、关键安全注意点

  1. AES-GCM 的 nonce 绝对不能重复使用,否则密钥直接泄露;
  2. 密钥、盐、私钥禁止硬编码写代码,从环境变量/配置文件读取;
  3. 不要用MD5/SHA1,ring直接不提供,强制SHA2系列;
  4. 对称加密优先 AES-GCM,不要自己实现填充模式;
  5. 用户密码必须 PBKDF2/Argon2,不能直接SHA哈希(无盐易彩虹表破解)。

六、极简常用片段(单独复制使用)

生成随机32字节密钥

use ring::rand::{SystemRandom, SecureRandom};
use hex::encode;

fn gen_32_key() -> String {
    let rng = SystemRandom::new();
    let mut buf = [0u8;32];
    rng.fill(&mut buf).unwrap();
    encode(buf)
}

快速HMAC签名输出hex

use ring::hmac;
use hex::encode;

fn hmac_sign_hex(key: &[u8], msg: &[u8]) -> String {
    let k = hmac::Key::new(hmac::HMAC_SHA256, key);
    let s = hmac::sign(&k, msg);
    encode(s.as_ref())
}
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐