feat: implement end-to-end encryption (E2EE) support for agents with configuration and documentation updates

This commit is contained in:
2026-03-05 00:06:32 +00:00
parent 1e5103eb70
commit 54fe479792
11 changed files with 227 additions and 21 deletions
+17 -7
View File
@@ -4,6 +4,7 @@ package matrix
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
@@ -44,10 +45,12 @@ func New(cfg config.MatrixCfg) (*Client, error) {
}
// InitCrypto sets up end-to-end encryption using the mautrix cryptohelper.
// storePath is the SQLite file path for crypto material (e.g. "./data/crypto/crypto.db").
// agentID is used to namespace the crypto state so multiple agents can share a database.
// storePath is the SQLite file path for crypto material (e.g. "./agents/<id>/data/crypto/crypto.db").
// pickleKeyHex is a hex-encoded key for encrypting crypto material at rest. If empty,
// falls back to sha256(access_token) for backward compatibility.
// agentID namespaces the crypto state within the database.
// Returns an io.Closer that must be called on agent shutdown to flush the crypto store.
func (c *Client) InitCrypto(ctx context.Context, storePath, agentID string) (io.Closer, error) {
func (c *Client) InitCrypto(ctx context.Context, storePath, pickleKeyHex, agentID string) (io.Closer, error) {
// Resolve the actual device ID from the server — the value in config may differ
// from what the registration process assigned.
whoami, err := c.raw.Whoami(ctx)
@@ -56,10 +59,17 @@ func (c *Client) InitCrypto(ctx context.Context, storePath, agentID string) (io.
}
c.raw.DeviceID = whoami.DeviceID
// Derive a stable pickle key from the access token.
// If the token changes (bot re-registered), delete the crypto store to reset.
sum := sha256.Sum256([]byte(c.raw.AccessToken))
pickleKey := sum[:]
// Use explicit pickle key if provided, otherwise derive from access token.
var pickleKey []byte
if pickleKeyHex != "" {
pickleKey, err = hex.DecodeString(pickleKeyHex)
if err != nil {
return nil, fmt.Errorf("decode pickle_key_env: %w", err)
}
} else {
sum := sha256.Sum256([]byte(c.raw.AccessToken))
pickleKey = sum[:]
}
if err := os.MkdirAll(filepath.Dir(storePath), 0700); err != nil {
return nil, fmt.Errorf("create crypto store dir: %w", err)