feat: add file
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
use aes_gcm::{Aes256Gcm, AesGcm, Key, KeyInit, Nonce};
|
||||
use aes_gcm::aead::{Aead, AeadMut, OsRng};
|
||||
use aes_gcm::aead::generic_array::GenericArray;
|
||||
use aes_gcm::aes::{Aes256, Aes256Enc};
|
||||
use aes_gcm::aes::cipher::{Block, BlockEncrypt, BlockEncryptMut, Iv};
|
||||
use aes_gcm::aes::cipher::inout::{InOut, InOutBuf};
|
||||
|
||||
#[test]
|
||||
fn test_aes_gcm_01() {
|
||||
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
|
||||
use aes_gcm::aead::{Aead};
|
||||
|
||||
let data_key = hex::decode("0001020304050607080910111213141516171819202122232425262728293031").unwrap();
|
||||
let nonce = hex::decode("000102030405060708091011").unwrap();
|
||||
|
||||
@@ -32,6 +28,9 @@ fn test_aes_gcm_01() {
|
||||
|
||||
#[test]
|
||||
fn test_aes_gcm_02() {
|
||||
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
|
||||
use aes_gcm::aead::{Aead};
|
||||
|
||||
let data_key = hex::decode("aa01020304050607080910111213141516171819202122232425262728293031").unwrap();
|
||||
let nonce = hex::decode("aa0102030405060708091011").unwrap();
|
||||
|
||||
|
||||
39
src/file.rs
Normal file
39
src/file.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use rust_util::{opt_result, simple_error, XResult};
|
||||
|
||||
use crate::spec::TinyEncryptMeta;
|
||||
|
||||
fn write_tiny_encrypt_meta<W: Write>(w: &mut W, meta: &TinyEncryptMeta) -> XResult<usize> {
|
||||
let meta_json = opt_result!( serde_json::to_string(meta), "Meta to JSON failed: {}");
|
||||
let meta_json_bytes = meta_json.as_bytes();
|
||||
let meta_json_bytes_len = meta_json_bytes.len();
|
||||
|
||||
opt_result!(w.write_all(&((0x01) as u16).to_be_bytes()), "Write tag failed: {}");
|
||||
opt_result!(w.write_all(&(meta_json_bytes_len as u32).to_be_bytes()), "Write length failed: {}");
|
||||
opt_result!(w.write_all(&meta_json_bytes), "Write meta failed: {}");
|
||||
|
||||
Ok(meta_json_bytes_len + 2 + 4)
|
||||
}
|
||||
|
||||
fn read_tiny_encrypt_meta<R: Read>(r: &mut R) -> XResult<TinyEncryptMeta> {
|
||||
let mut tag_buff = [0_u8; 2];
|
||||
opt_result!(r.read_exact(&mut tag_buff), "Read tag failed: {}");
|
||||
let tag = u16::from_be_bytes(tag_buff);
|
||||
if tag != 0x01 {
|
||||
return simple_error!("Tag is not 0x01, but is: 0x{:x}", tag);
|
||||
}
|
||||
|
||||
let mut length_buff = [0_u8; 4];
|
||||
opt_result!(r.read_exact(&mut length_buff), "Read length failed: {}");
|
||||
let length = u32::from_be_bytes(length_buff);
|
||||
if length > 1024 * 1024 {
|
||||
return simple_error!("Meta too large: {}", length);
|
||||
}
|
||||
|
||||
let mut meta_buff = Vec::with_capacity(length as usize);
|
||||
opt_result!( r.read_exact(meta_buff.as_mut_slice()), "Read meta failed: {}");
|
||||
|
||||
Ok(opt_result!(serde_json::from_slice(&meta_buff), "Parse meta failed: {}"))
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
extern crate core;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
@@ -5,6 +7,7 @@ use rust_util::information;
|
||||
|
||||
mod spec;
|
||||
mod crypto;
|
||||
mod file;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "tiny-encrypt-rs")]
|
||||
|
||||
69
src/spec.rs
69
src/spec.rs
@@ -1,37 +1,46 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// File format
|
||||
// [MAGIC; 4 bytes][VERSION; 1 byte]
|
||||
// [META_LENGTH; 4 bytes]
|
||||
// [META; META_LENGTH bytes]
|
||||
// [ENCRYPTED DATA; n bytes]
|
||||
|
||||
pub const EXT: &'static str = "ers";
|
||||
pub const MAGIC: u16 = 0xECF0;
|
||||
|
||||
pub const VERSION_1: u8 = 0x01;
|
||||
pub const TINY_ENCRYPT_VERSION: &'static str = "1.0";
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct MetaBock {
|
||||
pub meta_random_hex: String,
|
||||
pub desc: Option<DescBlock>,
|
||||
pub encrypted_desc: String,
|
||||
pub keys: Vec<KeyBlock>,
|
||||
pub iv_nonce_hex: String,
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TinyEncryptMeta {
|
||||
pub version: String,
|
||||
pub created: u64,
|
||||
pub user_agent: String,
|
||||
pub comment: Option<String>,
|
||||
pub encrypted_comment: Option<String>,
|
||||
pub pgp_envelop: Option<String>,
|
||||
pub pgp_fingerprint: Option<String>,
|
||||
pub envelop: Option<String>,
|
||||
pub nonce: String,
|
||||
pub file_length: u64,
|
||||
pub file_last_modified: u64,
|
||||
pub compress: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct DescBlock {
|
||||
pub file_id: Option<String>,
|
||||
pub author: Option<String>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct KeyBlock {
|
||||
pub key_type: String,
|
||||
pub key_id: Option<String>,
|
||||
pub encrypted_key_hex: String,
|
||||
pub key_verification_code_hex: String,
|
||||
pub extended_information: Option<String>,
|
||||
pub fn get_user_agent() -> String {
|
||||
format!("TinyEncrypt-rs v{}@{}", env!("CARGO_PKG_VERSION"),
|
||||
if cfg!(target_os = "macos") {
|
||||
"MacOS"
|
||||
} else if cfg!(target_os = "ios") {
|
||||
"iOS"
|
||||
} else if cfg!(target_os = "android") {
|
||||
"Android"
|
||||
} else if cfg!(target_os = "windows") {
|
||||
"Windows"
|
||||
} else if cfg!(target_os = "linux") {
|
||||
"Linux"
|
||||
} else if cfg!(target_os = "freebsd") {
|
||||
"FreeBSD"
|
||||
} else if cfg!(target_os = "dragonfly") {
|
||||
"Dragonfly"
|
||||
} else if cfg!(target_os = "openbsd") {
|
||||
"OpenBSD"
|
||||
} else if cfg!(target_os = "netbsd") {
|
||||
"NetBSD"
|
||||
} else {
|
||||
panic!("Unsupported OS!");
|
||||
}
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user