feat: v0.2.0-dev, encrypt supports x25519

This commit is contained in:
2023-10-08 00:49:17 +08:00
parent 9637ef9e01
commit 0bdb89ad25
6 changed files with 113 additions and 4 deletions

View File

@@ -10,7 +10,7 @@ use rsa::Pkcs1v15Encrypt;
use rust_util::{debugging, failure, information, opt_result, simple_error, success, util_msg, warning, XResult};
use zeroize::Zeroize;
use crate::{util, util_ecdh};
use crate::{util, util_ecdh, util_x25519};
use crate::compress::GzStreamEncoder;
use crate::config::{TinyEncryptConfig, TinyEncryptConfigEnvelop};
use crate::crypto_aes::aes_gcm_encrypt;
@@ -233,6 +233,9 @@ fn encrypt_envelops(key: &[u8], envelops: &[&TinyEncryptConfigEnvelop]) -> XResu
TinyEncryptEnvelopType::Pgp => {
encrypted_envelops.push(encrypt_envelop_pgp(key, envelop)?);
}
TinyEncryptEnvelopType::PgpX25519 => {
encrypted_envelops.push(encrypt_envelop_ecdh_x25519(key, envelop)?);
}
TinyEncryptEnvelopType::Ecdh => {
encrypted_envelops.push(encrypt_envelop_ecdh(key, envelop)?);
}
@@ -245,7 +248,22 @@ fn encrypt_envelops(key: &[u8], envelops: &[&TinyEncryptConfigEnvelop]) -> XResu
fn encrypt_envelop_ecdh(key: &[u8], envelop: &TinyEncryptConfigEnvelop) -> XResult<TinyEncryptEnvelop> {
let public_key_point_hex = &envelop.public_part;
let (shared_secret, ephemeral_spki) = util_ecdh::compute_shared_secret(public_key_point_hex)?;
let shared_key = util::simple_kdf(shared_secret.as_slice());
encrypt_envelop_shared_secret(key, &shared_secret, &ephemeral_spki, envelop)
}
fn encrypt_envelop_ecdh_x25519(key: &[u8], envelop: &TinyEncryptConfigEnvelop) -> XResult<TinyEncryptEnvelop> {
let public_key_point_hex = &envelop.public_part;
let (shared_secret, ephemeral_spki) = util_x25519::compute_x25519_shared_secret(public_key_point_hex)?;
encrypt_envelop_shared_secret(key, &shared_secret, &ephemeral_spki, envelop)
}
fn encrypt_envelop_shared_secret(key: &[u8],
shared_secret: &[u8],
ephemeral_spki: &[u8],
envelop: &TinyEncryptConfigEnvelop) -> XResult<TinyEncryptEnvelop> {
let shared_key = util::simple_kdf(shared_secret);
let (_, nonce) = util::make_key256_and_nonce();
let encrypted_key = aes_gcm_encrypt(&shared_key, &nonce, key)?;

View File

@@ -9,6 +9,7 @@ use crate::cmd_info::CmdInfo;
mod util;
mod util_ecdh;
mod util_x25519;
mod compress;
mod config;
mod spec;

View File

@@ -50,6 +50,8 @@ pub struct TinyEncryptEnvelop {
pub enum TinyEncryptEnvelopType {
#[serde(rename = "pgp")]
Pgp,
#[serde(rename = "pgp-x25519")]
PgpX25519,
#[serde(rename = "age")]
Age,
#[serde(rename = "ecdh")]
@@ -65,6 +67,7 @@ impl TinyEncryptEnvelopType {
pub fn get_name(&self) -> &'static str {
match self {
TinyEncryptEnvelopType::Pgp => "pgp",
TinyEncryptEnvelopType::PgpX25519 => "pgp-x25519",
TinyEncryptEnvelopType::Age => "age",
TinyEncryptEnvelopType::Ecdh => "ecdh",
TinyEncryptEnvelopType::Kms => "kms",

19
src/util_x25519.rs Normal file
View File

@@ -0,0 +1,19 @@
use rand::rngs::OsRng;
use rust_util::{opt_result, simple_error, XResult};
use x25519_dalek::{EphemeralSecret, PublicKey};
pub fn compute_x25519_shared_secret(public_key_point_hex: &str) -> XResult<(Vec<u8>, Vec<u8>)> {
let public_key_bytes = opt_result!(hex::decode(public_key_point_hex), "Parse X25519 public key hex failed: {}");
if public_key_bytes.len() != 32 {
return simple_error!("Parse X25519 key failed: not 32 bytes");
}
let public_key_bytes: [u8; 32] = public_key_bytes.try_into().unwrap();
let public_key_card = PublicKey::from(public_key_bytes);
let ephemeral_secret = EphemeralSecret::random_from_rng(OsRng);
let ephemeral_public = PublicKey::from(&ephemeral_secret);
let shared_secret = ephemeral_secret.diffie_hellman(&public_key_card);
Ok((shared_secret.as_bytes().to_vec(), ephemeral_public.as_bytes().to_vec()))
}