This commit is contained in:
2025-09-17 07:22:27 +02:00
parent 5d4974e38a
commit 304cdb5918
7 changed files with 440 additions and 1 deletions

View File

@@ -0,0 +1,102 @@
module herocrypt
import freeflowuniverse.herolib.core.redisclient
// HeroCrypt provides a client for HeroDB's AGE cryptography features.
pub struct HeroCrypt {
pub mut:
redis_client &redisclient.Redis
}
// new returns a new HeroCrypt client
// url e.g. localhost:6381 (default)
// It pings the server to ensure a valid connection.
pub fn new(url_ string) !&HeroCrypt {
mut url := url_
if url == '' {
url = 'localhost:6381'
}
mut redis := redisclient.new(url)!
redis.ping()!
return &HeroCrypt{
redis_client: redis
}
}
// new_default returns a new HeroCrypt client with the default URL.
pub fn new_default() !&HeroCrypt {
return new('')
}
// -- Stateless (Ephemeral) Methods --
// gen_enc_keypair generates an ephemeral encryption keypair.
// Returns: [recipient_public_key, identity_secret_key]
pub fn (mut self HeroCrypt) gen_enc_keypair() ![]string {
return self.redis_client.cmd_list_str('AGE', ['GENENC'])
}
// encrypt encrypts a message with a recipient public key.
pub fn (mut self HeroCrypt) encrypt(recipient_public_key string, message string) !string {
return self.redis_client.cmd_str('AGE', ['ENCRYPT', recipient_public_key, message])
}
// decrypt decrypts a ciphertext with an identity secret key.
pub fn (mut self HeroCrypt) decrypt(identity_secret_key string, ciphertext_b64 string) !string {
return self.redis_client.cmd_str('AGE', ['DECRYPT', identity_secret_key, ciphertext_b64])
}
// gen_sign_keypair generates an ephemeral signing keypair.
// Returns: [verify_public_key_b64, sign_secret_key_b64]
pub fn (mut self HeroCrypt) gen_sign_keypair() ![]string {
return self.redis_client.cmd_list_str('AGE', ['GENSIGN'])
}
// sign signs a message with a signing secret key.
pub fn (mut self HeroCrypt) sign(sign_secret_key_b64 string, message string) !string {
return self.redis_client.cmd_str('AGE', ['SIGN', sign_secret_key_b64, message])
}
// verify verifies a signature with a public verification key.
pub fn (mut self HeroCrypt) verify(verify_public_key_b64 string, message string, signature_b64 string) !bool {
res := self.redis_client.cmd_str('AGE', ['VERIFY', verify_public_key_b64, message, signature_b64])!
return res == '1'
}
// -- Key-Managed (Persistent, Named) Methods --
// keygen generates and persists a named encryption keypair.
pub fn (mut self HeroCrypt) keygen(name string) ![]string {
return self.redis_client.cmd_list_str('AGE', ['KEYGEN', name])
}
// encrypt_by_name encrypts a message using a named key.
pub fn (mut self HeroCrypt) encrypt_by_name(name string, message string) !string {
return self.redis_client.cmd_str('AGE', ['ENCRYPTNAME', name, message])
}
// decrypt_by_name decrypts a ciphertext using a named key.
pub fn (mut self HeroCrypt) decrypt_by_name(name string, ciphertext_b64 string) !string {
return self.redis_client.cmd_str('AGE', ['DECRYPTNAME', name, ciphertext_b64])
}
// sign_keygen generates and persists a named signing keypair.
pub fn (mut self HeroCrypt) sign_keygen(name string) ![]string {
return self.redis_client.cmd_list_str('AGE', ['SIGNKEYGEN', name])
}
// sign_by_name signs a message using a named signing key.
pub fn (mut self HeroCrypt) sign_by_name(name string, message string) !string {
return self.redis_client.cmd_str('AGE', ['SIGNNAME', name, message])
}
// verify_by_name verifies a signature with a named verification key.
pub fn (mut self HeroCrypt) verify_by_name(name string, message string, signature_b64 string) !bool {
res := self.redis_client.cmd_str('AGE', ['VERIFYNAME', name, message, signature_b64])!
return res == '1'
}
// // list_keys lists all stored AGE keys.
// pub fn (mut self HeroCrypt) list_keys() ![]string {
// return self.redis_client.cmd_list_str('AGE', ['LIST'])
// }

View File

@@ -0,0 +1,116 @@
# HeroCrypt: Effortless Cryptography with HeroDB
HeroCrypt is a library that provides a simple and secure way to handle encryption and digital signatures by leveraging the power of [HeroDB](https://git.ourworld.tf/herocode/herodb). It abstracts the underlying complexity of cryptographic operations, allowing you to secure your application's data with minimal effort.
## What is HeroDB?
HeroDB is a high-performance, Redis-compatible database that offers built-in support for advanced cryptographic operations using the [AGE encryption format](https://age-encryption.org/). This integration makes it an ideal backend for applications requiring robust, end-to-end security.
## Core Features of HeroCrypt
- **Encryption & Decryption**: Securely encrypt and decrypt data.
- **Digital Signatures**: Sign and verify messages to ensure their integrity and authenticity.
- **Flexible Key Management**: Choose between two modes for managing your cryptographic keys:
1. **Key-Managed (Server-Side)**: Let HeroDB manage your keys. Keys are stored securely within the database and are referenced by a name. This is the recommended approach for simplicity and centralized key management.
2. **Stateless (Client-Side)**: Manage your own keys on the client side. You pass the key material with every cryptographic operation. This mode is for advanced users who require full control over their keys.
## To start a db see
https://git.ourworld.tf/herocode/herodb
to do:
```bash
hero git pull https://git.ourworld.tf/herocode/herodb
~/code/git.ourworld.tf/herocode/herodb/run.sh
```
## Key-Managed Mode (Recommended)
In this mode, HeroDB generates and stores the keypairs for you. You only need to provide a name for your key.
### Encryption
```v
import freeflowuniverse.herolib.crypt.herocrypt
mut client := herocrypt.new_default()!
// Generate and persist a named encryption keypair
client.keygen('my_app_key')!
// Encrypt a message
message := 'This is a secret message.'
ciphertext := client.encrypt_by_name('my_app_key', message)!
// Decrypt the message
decrypted_message := client.decrypt_by_name('my_app_key', ciphertext)!
assert decrypted_message == message
```
### Signing
```v
import freeflowuniverse.herolib.crypt.herocrypt
mut client := herocrypt.new_default()!
// Generate and persist a named signing keypair
client.sign_keygen('my_signer_key')!
// Sign a message
message := 'This message needs to be signed.'
signature := client.sign_by_name('my_signer_key', message)!
// Verify the signature
is_valid := client.verify_by_name('my_signer_key', message, signature)!
assert is_valid
```
## Stateless Mode (Advanced)
In this mode, you are responsible for generating and managing your own keys.
### Encryption
```v
import freeflowuniverse.herolib.crypt.herocrypt
mut client := herocrypt.new_default()!
// Generate an ephemeral encryption keypair
keypair := client.gen_enc_keypair()!
recipient_pub := keypair[0]
identity_sec := keypair[1]
// Encrypt a message
message := 'This is a secret message.'
ciphertext := client.encrypt(recipient_pub, message)!
// Decrypt the message
decrypted_message := client.decrypt(identity_sec, ciphertext)!
assert decrypted_message == message
```
### Signing
```v
import freeflowuniverse.herolib.crypt.herocrypt
mut client := herocrypt.new_default()!
// Generate an ephemeral signing keypair
keypair := client.gen_sign_keypair()!
verify_pub_b64 := keypair[0]
sign_sec_b64 := keypair[1]
// Sign a message
message := 'This message needs to be signed.'
signature := client.sign(sign_sec_b64, message)!
// Verify the signature
is_valid := client.verify(verify_pub_b64, message, signature)!
assert is_valid
```

View File

@@ -0,0 +1,84 @@
# HeroCrypt Technical Specifications
This document provides the low-level technical details for the HeroCrypt library, including the underlying Redis commands used to interact with HeroDB's AGE cryptography features.
## Communication Protocol
HeroCrypt communicates with HeroDB using the standard Redis protocol. All commands are sent as RESP (Redis Serialization Protocol) arrays.
## Stateless (Ephemeral) AGE Operations
These commands are used when the client manages its own keys.
### Encryption
- **`AGE GENENC`**: Generates an ephemeral encryption keypair.
- **Returns**: An array containing the recipient (public key) and the identity (secret key).
- **`AGE ENCRYPT <recipient> <message>`**: Encrypts a message using the recipient's public key.
- **`<recipient>`**: The public key (`age1...`).
- **`<message>`**: The plaintext message to encrypt.
- **Returns**: A base64-encoded ciphertext.
- **`AGE DECRYPT <identity> <ciphertext>`**: Decrypts a ciphertext using the identity (secret key).
- **`<identity>`**: The secret key (`AGE-SECRET-KEY-1...`).
- **`<ciphertext>`**: The base64-encoded ciphertext.
- **Returns**: The decrypted plaintext message.
### Signing
- **`AGE GENSIGN`**: Generates an ephemeral signing keypair.
- **Returns**: An array containing the public verification key (base64) and the secret signing key (base64).
- **`AGE SIGN <sign_secret_b64> <message>`**: Signs a message with the secret key.
- **`<sign_secret_b64>`**: The base64-encoded secret signing key.
- **`<message>`**: The message to sign.
- **Returns**: A base64-encoded signature.
- **`AGE VERIFY <verify_pub_b64> <message> <signature_b64>`**: Verifies a signature.
- **`<verify_pub_b64>`**: The base64-encoded public verification key.
- **`<message>`**: The original message.
- **`<signature_b64>`**: The base64-encoded signature.
- **Returns**: `1` if the signature is valid, `0` otherwise.
## Key-Managed (Persistent, Named) AGE Operations
These commands are used when HeroDB manages the keys.
### Encryption
- **`AGE KEYGEN <name>`**: Generates and persists a named encryption keypair.
- **`<name>`**: A unique name for the key.
- **Returns**: An array containing the recipient and identity (for initial export, if needed).
- **`AGE ENCRYPTNAME <name> <message>`**: Encrypts a message using a named key.
- **`<name>`**: The name of the stored key.
- **`<message>`**: The plaintext message.
- **Returns**: A base64-encoded ciphertext.
- **`AGE DECRYPTNAME <name> <ciphertext>`**: Decrypts a ciphertext using a named key.
- **`<name>`**: The name of the stored key.
- **`<ciphertext>`**: The base64-encoded ciphertext.
- **Returns**: The decrypted plaintext message.
### Signing
- **`AGE SIGNKEYGEN <name>`**: Generates and persists a named signing keypair.
- **`<name>`**: A unique name for the key.
- **Returns**: An array containing the public and secret keys (for initial export).
- **`AGE SIGNNAME <name> <message>`**: Signs a message using a named key.
- **`<name>`**: The name of the stored key.
- **`<message>`**: The message to sign.
- **Returns**: A base64-encoded signature.
- **`AGE VERIFYNAME <name> <message> <signature_b64>`**: Verifies a signature using a named key.
- **`<name>`**: The name of the stored key.
- **`<message>`**: The original message.
- **`<signature_b64>`**: The base64-encoded signature.
- **Returns**: `1` if the signature is valid, `0` otherwise.
### Key Listing
- **`AGE LIST`**: Lists all stored AGE keys.
- **Returns**: An array of key names.