This commit is contained in:
JMARyA 2025-04-29 20:43:42 +02:00
commit 79a13d3941
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 2009 additions and 0 deletions

74
README.md Normal file
View file

@ -0,0 +1,74 @@
# 🔮 Sage
**Sage** is a lightweight cryptographic library built with Rust that layers [age](https://github.com/FiloSottile/age) encryption and [minisign](https://jedisct1.github.io/minisign/) signatures to enable **signed encryption** — ensuring both confidentiality **and** authenticity.
Sage signs a message before encryption and again after encryption, verifying both layers on decryption. This offers **end-to-end message integrity, trust, and non-repudiation**.
## 🚀 Features
- 🔐 Encryption with age
- ✍️ Dual minisign signatures (before and after encryption)
- ✅ Signature verification on both layers during decryption
- 📦 Easy key serialization and identity management
## 🌱 Getting Started
### Generate a New Identity
```rust
let id = sage::Identity::new();
let persona = id.public();
```
- `Identity`: holds your private encryption and signing keys.
- `Persona`: a tuple of `(age_public_key, minisign_public_key)` for sharing public keys.
### Encrypt and Sign
```rust
let message = b"Hello, secure world!";
let recipient = persona.enc_key().unwrap(); // Recipient's age public key
let ciphertext = id.encrypt(message, &recipient);
```
### Verify and Decrypt
```rust
let sender_pk = persona.sign_key().unwrap(); // Sender's minisign public key
match id.decrypt(&ciphertext, &sender_pk) {
Ok(msg) => {
println!("Decrypted: {}", String::from_utf8_lossy(&msg.payload));
println!("Signed at timestamp: {}", msg.timestamp);
}
Err(err) => eprintln!("Failed to decrypt: {:?}", err),
}
```
## 📁 Saving & Loading Identities
```rust
id.save("my_keys/");
let loaded = sage::Identity::try_load("my_keys/").unwrap();
```
- Saves two files: `age.key` and `sign.key`
## 🔍 How It Works
### Encryption Flow
1. **Sign the plaintext** with minisign and add meta information (timestamp)
2. **Encrypt** the signed payload using age
3. **Sign the encrypted blob** with minisign again
### Decryption Flow
1. **Verify the outer signature** (authenticity of ciphertext)
2. **Decrypt** using the age identity
3. **Verify the inner signature** (authenticity of plaintext)
4. **Extract** message and timestamp
## 🙏 Credits
- [age](https://github.com/FiloSottile/age) by Filippo Valsorda
- [minisign](https://jedisct1.github.io/minisign/) by Frank Denis (jedisct1)