...
This commit is contained in:
102
lib/crypt/herocrypt/herocrypt.v
Normal file
102
lib/crypt/herocrypt/herocrypt.v
Normal 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'])
|
||||
// }
|
||||
116
lib/crypt/herocrypt/readme.md
Normal file
116
lib/crypt/herocrypt/readme.md
Normal 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
|
||||
|
||||
```
|
||||
84
lib/crypt/herocrypt/specs.md
Normal file
84
lib/crypt/herocrypt/specs.md
Normal 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.
|
||||
Reference in New Issue
Block a user