Rust中有不少加解密库,例如 ring, rust-openssl,Rust Crypto。本文选用Rust Crypto系列中的库实现aes加解密,rsa加解密 签名验签。
- Rust Crypto纯Rust实现,方便交叉编译
- Rust Crypto各个算法独立实现,例如aes、cbc、pkcs7独立实现,cbc pkcs7也可以和国密算法sm4结合使用
1. AES 加解密
本文aes加密选择cbc工作模式、Pkcs7填充模式, 如需其他工作模式可参考block-modes,如需其他padding模式参考block-padding。
加密结果如需使用base64,可使用base64对加密数据进行操作。
use aes::cipher::block_padding::Pkcs7;
use anyhow::anyhow;
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
const AES_KEY: [u8; 32] = *b"1d64dce239c4437d1d64dce239c4437d";
const AES_IV: [u8; 16] = *b"45154c1fc4541161";
/// aes cbc pkcs7 enc
pub fn enc(input: &[u8]) -> anyhow::Result<Vec<u8>> {
let res =
Aes256CbcEnc::new(&AES_KEY.into(), &AES_IV.into()).encrypt_padded_vec_mut::<Pkcs7>(input);
Ok(res)
}
/// aes cbc pkcs7 dec
pub fn dec(cipher: &[u8]) -> anyhow::Result<Vec<u8>> {
let res = Aes256CbcDec::new(&AES_KEY.into(), &AES_IV.into())
.decrypt_padded_vec_mut::<Pkcs7>(&cipher)
.map_err(|e| anyhow!(format!("dec err {:?}", e.to_string())))?;
Ok(res)
}
2. Rsa 加解密及签名验签
Rsa一般用作公钥加密,私钥解密,私钥签名,公钥验签。密钥格式有两种,Pkcs1 Pkcs8。
Pkcs1 pem格式如下开头
-----BEGIN RSA PRIVATE KEY-----
Pkcs8 pem格式如下开头
-----BEGIN PRIVATE KEY-----
加解密、签名验签功能如下
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha8Rng;
use rsa::pkcs1v15::{Signature, SigningKey, VerifyingKey};
use rsa::signature::{Keypair, RandomizedSigner, SignatureEncoding, Verifier};
use rsa::{pkcs1, pkcs8, Pkcs1v15Encrypt, Pkcs1v15Sign, RsaPrivateKey, RsaPublicKey};
use sha2::Sha256;
pub enum RsaKey {
Pkcs1 { key: String },
Pkcs8 { key: String },
}
/// PKCS#1 v1.5 encryption
pub fn rsa_enc(data: &[u8], pub_key_type: RsaKey) -> anyhow::Result<Vec<u8>> {
let public_key: RsaPublicKey;
match pub_key_type {
RsaKey::Pkcs1 { key } => {
public_key = pkcs1::DecodeRsaPublicKey::from_pkcs1_pem(key.as_str())?;
}
RsaKey::Pkcs8 { key } => {
public_key = pkcs8::DecodePublicKey::from_public_key_pem(key.as_str())?;
}
}
let mut rng = ChaCha8Rng::from_seed([42; 32]);
let enc_data = public_key.encrypt(&mut rng, Pkcs1v15Encrypt, data)?;
Ok(enc_data)
}
/// PKCS#1 v1.5 decryption
pub fn rsa_dec(cipher_text: &[u8], private_key_str: RsaKey) -> anyhow::Result<Vec<u8>> {
let private_key: RsaPrivateKey;
match private_key_str {
RsaKey::Pkcs1 { key } => {
private_key = pkcs1::DecodeRsaPrivateKey::from_pkcs1_pem(key.as_str())?;
}
RsaKey::Pkcs8 { key } => {
private_key = pkcs8::DecodePrivateKey::from_pkcs8_pem(key.as_str())?;
}
}
let dec_data = private_key.decrypt(Pkcs1v15Encrypt, cipher_text)?;
Ok(dec_data)
}
/// PKCS#1 v1.5 signatures
pub fn rsa_sign(data: &[u8], private_key_str: RsaKey) -> anyhow::Result<Vec<u8>> {
let private_key: RsaPrivateKey;
match private_key_str {
RsaKey::Pkcs1 { key } => {
private_key = pkcs1::DecodeRsaPrivateKey::from_pkcs1_pem(key.as_str())?;
}
RsaKey::Pkcs8 { key } => {
private_key = pkcs8::DecodePrivateKey::from_pkcs8_pem(key.as_str())?;
}
};
let signing_key = SigningKey::<Sha256>::new_unprefixed(private_key);
let mut rng = ChaCha8Rng::from_seed([42; 32]);
let signature = signing_key.sign_with_rng(&mut rng, data);
Ok(signature.to_bytes().to_vec())
}
pub fn rsa_verify(data: &[u8], sign: &[u8], pub_key: RsaKey) -> anyhow::Result<()> {
let public_key: RsaPublicKey;
match pub_key {
RsaKey::Pkcs1 { key } => {
public_key = pkcs1::DecodeRsaPublicKey::from_pkcs1_pem(key.as_str())?;
}
RsaKey::Pkcs8 { key } => {
public_key = pkcs8::DecodePublicKey::from_public_key_pem(key.as_str())?;
}
}
let verifying_key: VerifyingKey<Sha256> = VerifyingKey::<Sha256>::new_unprefixed(public_key);
let signature = Signature::try_from(sign)?;
verifying_key.verify(data, &signature)?;
Ok(())
}
以上代码详见rust_crypto_demo
Openssl 产生RSA公私钥对
openssl 产生Pkcs8公私钥对命令如下
产生Pkcs8私钥
openssl genpkey -algorithm RSA -out private_pkcs8.pem
产生Pkcs8公钥openssl rsa -pubout -in private_pkcs8.pem -out public_pkcs8.pem
Pkcs8公私钥对转换为Pkcs1命令如下
私钥转化openssl rsa -in private_pkcs8.pem -out private_pkcs1.pem -traditional
公钥转化openssl rsa -pubin -in public_pkcs8.pem -RSAPublicKey_out -out public_pkcs1.pem