现代密码学的一个基本原则是“一切秘密寓于密钥之中”。
密钥分为两种:对称密钥与非对称密钥
- 对称密码算法使用相同的密钥;
- 公钥密码使用不同的密钥来对消息进行加密解密;
- MAC消息认证码使用相同的密钥;
- 数字签名使用不同的密钥来对消息进行签名和验证。
密钥的管理
- 如何生成公私钥对?
- 如何根据编码后的公私钥对得到 PrivateKey, PublicKey ?
- 如何保护私钥的安全?
- 如何传输交换密钥?
- 密钥共享
如何生成公私钥对?
RSA生成公私钥对
use rand_core::CryptoRngCore;
use rsa::pkcs8::{self, DecodePublicKey, EncodePrivateKey, EncodePublicKey, LineEnding};
use rsa::{Pkcs1v15Encrypt, PublicKey, RsaPrivateKey, RsaPublicKey};
let mut rng = random::thread_rng();
let bits = 2048;
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
ECC生成公私钥对
#[test]
fn ecc() {
use base64ct::LineEnding;
use elliptic_curve::SecretKey;
use p256::NistP256;
use rand_core::OsRng; // requires 'getrandom' feature
// 1. 生成私钥
let key: SecretKey<NistP256> = SecretKey::random(&mut OsRng);
let pem_str = key.to_sec1_pem(LineEnding::LF);
println!("{:?}", pem_str);
// 根据私钥生成公钥
println!("{:?}", key.public_key());
//2. 根据PEM格式字符串恢复私钥
let private_key : Result<SecretKey<NistP256>, elliptic_curve::Error> = elliptic_curve::SecretKey::from_sec1_pem("-----BEGIN EC PRIVATE KEY-----\nMGsCAQEEIKUhSRir8XkO1BcqcgdgFxtapjz0UFyzwQQpcCJ6IZhcoUQDQgAEWsVX\ns/5B/A4rWT4hRk6EBP/tzRzQjJKZIoh9WQbV4eots1mPwiio6XYhcYD+zauInLNq\nK1i6dCgXjJ0GB1FEhA==\n-----END EC PRIVATE KEY-----");
//3. 根据私钥生成公钥
let public_key = private_key.unwrap().public_key();
println!("{:?}", public_key);
}
SM2生成公私钥对
use libsm::sm2::signature::{SigCtx, Signature};
let ctx = SigCtx::new();
let (pk, sk) = ctx.new_keypair().unwrap();
(1)获得openssl支持椭圆曲线算法列表
命令:openssl ecparam -list_curves
(2)生成SM2私钥文件
命令:openssl ecparam -outform pem -out sm2PrivateKey.pem -name SM2 -genkey
(3)查看私钥文件
命令:openssl ec -in sm2PrivateKey.pem -text
(4)生成SM2 公钥文件
命令:openssl ec -in sm2PrivateKey.pem -pubout -out sm2PublicKey.pem
如何根据编码后的公私钥对得到 PrivateKey, PublicKey ?
let private_key_pem = std::fs::read_to_string("private_key.pem").unwrap();
let public_key_pem = std::fs::read_to_string("public_key.pem").unwrap();
let priv_key = RsaPrivateKey::from_pkcs8_pem(&private_key_pem).unwrap();
let pub_key = RsaPublicKey::from_public_key_pem(&public_key_pem).unwrap();
密钥交换
use k256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret};
use rand_core::OsRng; // requires 'getrandom' feature
// Alice
let alice_secret = EphemeralSecret::random(&mut OsRng);
let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key());
// Bob
let bob_secret = EphemeralSecret::random(&mut OsRng);
let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key());
// Alice decodes Bob's serialized public key and computes a shared secret from it
let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref())
.expect("bob's public key is invalid!"); // In real usage, don't panic, handle this!
let alice_shared = alice_secret.diffie_hellman(&bob_public);
// Bob decodes Alice's serialized public key and computes the same shared secret
let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref())
.expect("alice's public key is invalid!"); // In real usage, don't panic, handle this!
let bob_shared = bob_secret.diffie_hellman(&alice_public);
// Both participants arrive on the same shared secret
assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes());
Elliptic Curve Diffie-Hellman (ECDH) function
x25519-dalek X25519 elliptic curve Diffie-Hellman key exchange in pure-Rust, using curve25519-dalek.
密钥管理系统(Key Management Service,KMS)
HashiCorp Vault
async fn vault() {
use vaultrs::client::{Client, VaultClient, VaultClientSettingsBuilder};
use rand_core::CryptoRngCore;
use rand_core::OsRng;
use rsa::pkcs8::{
self, DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey, LineEnding,
};
use rsa::{Pkcs1v15Encrypt, PublicKey, RsaPrivateKey, RsaPublicKey};
use serde::{Deserialize, Serialize};
use vaultrs::kv2;
// let mut rng = random::thread_rng();
// Create and read secrets
#[derive(Debug, Deserialize, Serialize)]
struct MySecret {
key: String,
password: String,
}
#[derive(Debug, Deserialize, Serialize)]
struct RSAKey {
public_key: String,
private_key: String,
}
// Create a client
let mut client = VaultClient::new(
VaultClientSettingsBuilder::default()
.address("http://127.0.0.1:8200")
.token("hvs.80mEiiPnonTChoSTH5pkAeLg")
.build()
.unwrap(),
)
.unwrap();
let secret = MySecret {
key: "super".to_string(),
password: "secret".to_string(),
};
kv2::set(&client, "secret", "mysecret", &secret).await;
// let secret: MySecret = ;
let result: Result<MySecret, vaultrs::error::ClientError> =
kv2::read(&client, "secret", "mysecret").await;
if (result.is_ok()) {
println!("{}", result.unwrap().password) // "secret"
} else {
println!("{:?}", result.err()) // "secret"
}
let mut public_key = String::new();
let mut private_key = String::new();
let bits = 2048;
let mut rng = rand::thread_rng();
//1. 生成RSA公私钥
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
//2. 序列化公私钥
if let Ok(priv_pem) = RsaPrivateKey::to_pkcs8_pem(&priv_key, pkcs8::LineEnding::default()) {
private_key = priv_pem.to_string();
}
if let Ok(pub_pem) = RsaPublicKey::to_public_key_pem(&pub_key, pkcs8::LineEnding::default()) {
public_key = pub_pem.to_string();
}
let secret1 = RSAKey {
public_key,
private_key,
};
// let mut rng = rand_core::OsRng;
let key = String::from("RSA:666666666666");
kv2::set(&client, "secret", &key, &secret1).await;
let result: Result<RSAKey, vaultrs::error::ClientError> =
kv2::read(&client, "secret", &key).await;
if (result.is_ok()) {
println!("{}", result.unwrap().public_key)
} else {
println!("{:?}", result.err())
}
}