如何在鸿蒙PC使用ohos-sdk适配rust三方库ring,用于后端加密、接口签名、用户密码存储、数据加解密
欢迎加入开源鸿蒙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. 核心能力
- 哈希摘要:SHA256/SHA384/SHA512(替代MD5,用于文件校验、数据指纹)
- HMAC 消息签名:接口验签、防篡改(对应前端 crypto-js HMAC)
- AEAD 对称加密:AES-GCM、ChaCha20-Poly1305(自带完整性校验,最安全对称加密)
- 密码加盐哈希 PBKDF2:用户密码存储,不存明文
- 数字签名:Ed25519、RSA、ECDSA(公私钥签名验签,替代 jsencrypt)
- 安全随机数生成:生成密钥、IV、盐值
- 密钥交换 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类加密需求:
- SHA256 哈希(文件/数据指纹)
- HMAC-SHA256(接口请求防篡改签名)
- AES-GCM(手机号/身份证等敏感数据对称加密)
- PBKDF2(用户登录密码加盐哈希存储,不存明文)
- 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()));
}
逻辑说明
- 不用
b"中文"字节字面量(Rust 禁止非ASCII字节串),先定义字符串再.as_bytes()转二进制; digest::digest(算法, 数据):输入任意二进制,输出固定32字节哈希;- 特性:不可逆,只能用于校验完整性,不能加密解密;
- 业务场景:文件校验、请求参数指纹、唯一标识生成。
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!("✅ 签名校验通过");
}
流程拆解
SystemRandom::new()系统安全随机源,fill填充32字节随机密钥;hmac::Key::new(算法, 密钥字节)构造签名密钥;hmac::sign(密钥, 报文)生成签名;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));
}
核心知识点
- AES256-GCM:AEAD 认证加密,自带防篡改校验tag,比CBC安全;
- 密钥固定32字节,nonce固定12字节(标准规范,不可复用同一个nonce加密两次);
Nonce无Copy特征,一次使用所有权转移,所以封装闭包每次从原始字节新建实例,解决moved value编译报错;seal_in_place_append_tag:原地加密,密文尾部自动拼接16字节校验标签;open_in_place:自动分离末尾tag校验,数据被篡改直接panic;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!("✅ 密码校验正确");
}
关键逻辑(用户登录核心)
salt:每个用户独立随机盐值,16字节,和哈希结果一起存入数据库;PBKDF2_HMAC_SHA256:密码慢哈希算法,迭代10万次增加暴力破解成本;pbkdf2::derive:注册时,原始密码+盐值生成哈希存入数据库,不存明文密码;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签名验证通过");
}
公私钥流程
generate_pkcs8:生成Ed25519私钥,返回文档对象;from_pkcs8:从私钥文档还原密钥对;key_pair.public_key():提取公钥(可公开分发);key_pair.sign():私钥签名,仅持有私钥的一方能生成签名;UnparsedPublicKey::new(算法, 公钥)构造验证器,用公钥校验签名;
优势&场景
对比RSA:密钥更短、签名速度更快;用于API开放平台鉴权、登录Token签名、分布式服务通信验签。
三、通用公共知识点
- 随机数统一使用
SystemRandom,硬件安全随机源,不用rand普通伪随机; - ring 内部错误类型
Unspecified不实现标准Errortrait,不能用?,统一.unwrap(); - 所有二进制输出用
hex::encode转十六进制,控制台可读; - 凡是无Copy的结构体(Nonce、密钥等),不能重复使用所有权,要么重新构造,要么传引用;
- 区分三类加密场景:
- 哈希:不可逆,校验完整性
- AES-GCM:对称加解密,同一密钥加密解密
- Ed25519/HMAC:签名验签,防伪造、防篡改
四、逐模块详细解释
1. SHA256 哈希 digest
digest::digest(&digest::SHA256, data)
输入任意二进制,输出固定32字节哈希;用于文件校验、数据唯一指纹,不可逆,无法解密。
2. HMAC-SHA256 hmac(接口签名)
流程:
- 生成32字节随机密钥(前后端约定)
- 对请求报文签名
- 后端用相同密钥重新计算HMAC比对
优势:防篡改,中间人修改报文后端校验直接失败。
3. AES-GCM aead(推荐对称加密)
ring 只提供现代 AEAD 加密,不支持不安全的 CBC:
nonce:12字节随机数,每次加密必须唯一,不可复用;- 加密后密文尾部自动附加16字节Tag,解密时校验数据是否被篡改;
- 适合加密手机号、身份证、银行卡等敏感业务字段。
4. PBKDF2 pbkdf2(用户密码存储核心)
永远不要明文存用户密码:
- 每个用户生成独立随机盐salt;
- 多次迭代哈希(10万次),暴力破解成本极高;
- 登录时用输入密码+同盐重新计算比对。
5. Ed25519 signature(非对称签名,替代RSA/jsencrypt)
- 私钥签名(服务端/客户端持有)
- 公钥验签(公开分发)
- 比RSA密钥短、速度更快,适合接口Token、登录鉴权
五、关键安全注意点
- AES-GCM 的 nonce 绝对不能重复使用,否则密钥直接泄露;
- 密钥、盐、私钥禁止硬编码写代码,从环境变量/配置文件读取;
- 不要用MD5/SHA1,ring直接不提供,强制SHA2系列;
- 对称加密优先 AES-GCM,不要自己实现填充模式;
- 用户密码必须 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())
}
更多推荐




所有评论(0)