-
Notifications
You must be signed in to change notification settings - Fork 2k
#967: feature/encrypt message at rest #971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devel
Are you sure you want to change the base?
Conversation
I will post the test results + load test. |
Do you want me to review this now or later, after the tests? |
@or-else please do after my testing. |
@or-else thinking about it, I would appreciate early feedbacks, we can discuss more technical details afterwards. |
|
||
**Encryption Key Generation:** | ||
|
||
* `encryption`: Generate encryption key instead of API key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise, 'encryption' is too generic. I would use something like above: encypt_at_rest
or store_encrypt
or some such.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any change
server/store/store.go
Outdated
|
||
// Encrypt message content if encryption is enabled | ||
if encryptionService != nil && encryptionService.IsEnabled() { | ||
encryptedContent, err := encryptionService.EncryptContent(msg.Content) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if encryptedContent, err := encryptionService.EncryptContent(msg.Content); err != nil { ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not really.
return adp.MessageGetAll(topic, forUser, opt) | ||
messages, err := adp.MessageGetAll(topic, forUser, opt) | ||
if err != nil { | ||
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return messages, err
rather than nil, err
. No need to change the logic here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the change.
server/tools/encrypt_messages.go
Outdated
} | ||
|
||
// Get messages for the specified topic | ||
messages, err := store.Store.GetAdapter().MessageGetAll(*topicName, types.ZeroUid, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not going to work. You need a new method in the adapter interface for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not say done
. This is still completely not going to work. If you need help, please ask.
Any update on this? |
Closing as abandoned |
@or-else let me open another mr on this one, been a though week. thanks for your input. |
If you want to continue, please use this PR. I reopened it. Thanks. |
Appreciate it thanks! |
Key Features - Optional: Encryption can be disabled if not needed - Transparent: No changes to client API required - Secure: Uses AES-256-GCM with random nonces - Configurable: Via config file or command line - Migration Support: Tools to convert existing installations - Performance Optimized: Only encrypts message content field - Error Handling: Graceful fallback if encryption fails Security Considerations: - Message content only: Metadata remains unencrypted for search/indexing - Database admins: Can still see message metadata but not content - Key management: Critical - keys must be stored securely - Performance: Minimal overhead (~1-5ms per message) - Recovery: Lost keys mean lost message content [tinode#967]
5d3ce78
to
157476a
Compare
Could you please respond to each of my comments with |
@or-else sure, currently testing the changes. thanks! |
… validation - Rename generic 'encryption' config to 'encrypt_at_rest' for clarity - Remove redundant 'enabled' field - key presence determines encryption - Support all AES key sizes (16, 24, 32 bytes) instead of just 32-byte keys - Simplify EncryptionService to MessageEncryptionService with cleaner API - Use []byte fields in EncryptedContent for automatic base64 conversion - Fix store initialization order: command line flags override config file - Update keygen tool with proper AES key size validation - Remove output file option from keygen (use shell redirection instead) - Fix encrypt_messages tool to use proper store interface methods - Add nil content handling in EncryptContent method - Update all tests to work with new MessageEncryptionService API - Improve error handling and method visibility throughout [tinode#967]
157476a
to
4ae0494
Compare
Testing Results: Steps:
![]()
![]() ![]() Result: Encrypted = true
![]() Result: Encrypted = true
![]() ![]() Result: Encrypted = false Some observation:
CC: @or-else |
|
||
**Encryption Key Generation:** | ||
|
||
* `encryption`: Generate encryption key instead of API key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any change
|
||
```sh | ||
# Generate 32-byte encryption key (AES-256) | ||
./keygen -encryption |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename for consistency to be less generic.
./keygen -encryption | ||
|
||
# Generate 16-byte encryption key (AES-128) | ||
./keygen -encryption -keysize 16 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename encryption
for consistency to be less generic.
./keygen -encryption -keysize 16 | ||
|
||
# Generate 24-byte encryption key (AES-192) | ||
./keygen -encryption -keysize 24 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is probably unnecessary. Any reasonable person can guess that specifying -keysize 24
would mean a 24-byte key.
hmacSalt := flag.String("salt", "", "HMAC salt, 32 random bytes base64-encoded") | ||
|
||
// Encryption key generation flags | ||
encryptionKey := flag.Bool("encryption", false, "Generate encryption key instead of API key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename encryption
for consistency to be less generic.
msg.SetUid(Store.GetUid()) | ||
|
||
// Encrypt message content if encryption is enabled | ||
if messageEncryptionService != nil && messageEncryptionService.IsEnabled() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The messageEncryptionService != nil
is redundant. You already check for it in messageEncryptionService.IsEnabled()
. This is Go, the nil pointer is not going to be dereferenced for calling IsEnabled()
.
return adp.MessageGetAll(topic, forUser, opt) | ||
messages, err := adp.MessageGetAll(topic, forUser, opt) | ||
if err != nil { | ||
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the change.
} | ||
|
||
// Decrypt message content if encryption is enabled | ||
if messageEncryptionService != nil && messageEncryptionService.IsEnabled() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The messageEncryptionService != nil
is redundant.
@@ -0,0 +1,131 @@ | |||
# Encryption Tools |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reduce duplication. Copy-pasting saves time short-term but creates problems in the long run. It requires multiple documents to be updated for every change.
} | ||
|
||
// Get messages for the specified topic using the store interface | ||
messages, err := store.Messages.GetAll(*topicName, types.ZeroUid, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said before, this is totally not going to work. Messages.GetAll
is not suitable for the task.
For one, Messages.GetAll
will return just 1024 messages from the topic.
This part of code in present form is not useful at all. If you don't know how to fix it, please talk to me or just remove it. This is just going to confuse users and won't do anything useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to create a new DB method to paginate over all messages in the DB. Get a page (10K messages?), encrypt/decrypt them, write back, then do the next page and so on.
keyFile = flag.String("key", "", "Path to file containing base64-encoded 32-byte encryption key") | ||
key = flag.String("key_string", "", "Base64-encoded 32-byte encryption key as string") | ||
dryRun = flag.Bool("dry_run", false, "Show what would be done without making changes") | ||
reverse = flag.Bool("reverse", false, "Decrypt encrypted messages (use with caution)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not call this flag decrypt
?
key = flag.String("key_string", "", "Base64-encoded 32-byte encryption key as string") | ||
dryRun = flag.Bool("dry_run", false, "Show what would be done without making changes") | ||
reverse = flag.Bool("reverse", false, "Decrypt encrypted messages (use with caution)") | ||
topicName = flag.String("topic", "", "Topic name to process (leave empty to process all accessible topics)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing it topic-by-topic is not useful.
} | ||
|
||
// Get encryption key | ||
var encryptionKey []byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said before, the key from the config file will override the command line key. That should be exacly inverse: the command line should override the configFile.
|
||
if !*dryRun { | ||
// Save the modified message using the store interface | ||
err, _ := store.Messages.Save(&msg, nil, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will insert a new message into the DB.
Please move |
@or-else i will continue on this, will push a change tomorrow oct 10. please keep it open. Thanks! |
Key Features
Security Considerations:
[#967]