v0.2-x25519 #1
69
Cargo.lock
generated
69
Cargo.lock
generated
@@ -390,6 +390,33 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"fiat-crypto",
|
||||
"platforms",
|
||||
"rustc_version",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.4.0"
|
||||
@@ -574,6 +601,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d"
|
||||
|
||||
[[package]]
|
||||
name = "flagset"
|
||||
version = "0.4.4"
|
||||
@@ -1339,6 +1372,12 @@ version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "platforms"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8"
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.1"
|
||||
@@ -1579,6 +1618,15 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusticata-macros"
|
||||
version = "4.1.0"
|
||||
@@ -1709,6 +1757,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
@@ -2009,7 +2063,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tiny-encrypt"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0-dev"
|
||||
dependencies = [
|
||||
"aes-gcm-stream",
|
||||
"base64",
|
||||
@@ -2029,6 +2083,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"simpledateformat",
|
||||
"x25519-dalek",
|
||||
"x509-parser",
|
||||
"yubikey",
|
||||
"zeroize",
|
||||
@@ -2428,6 +2483,18 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"rand_core",
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x509-cert"
|
||||
version = "0.2.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiny-encrypt"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0-dev"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "A simple and tiny file encrypt tool"
|
||||
@@ -26,6 +26,7 @@ serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.93"
|
||||
sha256 = "1.4.0"
|
||||
simpledateformat = "0.1.4"
|
||||
x25519-dalek = "2.0.0"
|
||||
x509-parser = "0.15.1"
|
||||
yubikey = { version = "0.8.0", features = ["untested"] }
|
||||
zeroize = "1.6.0"
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::cmd_info::CmdInfo;
|
||||
|
||||
mod util;
|
||||
mod util_ecdh;
|
||||
mod util_x25519;
|
||||
mod compress;
|
||||
mod config;
|
||||
mod spec;
|
||||
|
||||
@@ -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
19
src/util_x25519.rs
Normal 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()))
|
||||
}
|
||||
Reference in New Issue
Block a user