This repository was archived by the owner on Jun 21, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecording_sharing.go
More file actions
148 lines (125 loc) · 4.04 KB
/
Copy pathrecording_sharing.go
File metadata and controls
148 lines (125 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"time"
"term/database"
)
// GenerateKeyPair generates a new RSA key pair for the user
func GenerateKeyPair(name string) (*database.UserKey, error) {
// Generate 2048-bit RSA key pair
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("failed to generate key pair: %w", err)
}
// Encode private key to PEM
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
// Encode public key to PEM
publicKeyBytes, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
if err != nil {
return nil, fmt.Errorf("failed to marshal public key: %w", err)
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: publicKeyBytes,
})
return &database.UserKey{
Name: name,
PublicKey: string(publicKeyPEM),
PrivateKey: string(privateKeyPEM),
CreatedAt: time.Now(),
IsLocal: true,
}, nil
}
// unwrapFileKey unwraps the AES file key using the master key (derived from passphrase)
func unwrapFileKey(encKey, nonce, masterKey []byte) ([]byte, error) {
block, err := aes.NewCipher(masterKey)
if err != nil {
return nil, err
}
aead, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
fileKey, err := aead.Open(nil, nonce, encKey, nil)
if err != nil {
return nil, err
}
return fileKey, nil
}
// WrapKeyForRecipient wraps the file encryption key with the recipient's public key
func WrapKeyForRecipient(fileKey []byte, recipientPublicKeyPEM string) (string, error) {
// Parse the PEM-encoded public key
block, _ := pem.Decode([]byte(recipientPublicKeyPEM))
if block == nil {
return "", fmt.Errorf("failed to parse PEM block")
}
// Parse the public key
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse public key: %w", err)
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return "", fmt.Errorf("not an RSA public key")
}
// Wrap the file key using RSA-OAEP
wrappedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsaPub, fileKey, nil)
if err != nil {
return "", fmt.Errorf("failed to wrap key: %w", err)
}
// Return base64-encoded wrapped key
return base64.StdEncoding.EncodeToString(wrappedKey), nil
}
// UnwrapKeyWithPrivateKey unwraps the file encryption key using the user's private key
func UnwrapKeyWithPrivateKey(wrappedKeyB64, privateKeyPEM string) ([]byte, error) {
// Decode base64
wrappedKey, err := base64.StdEncoding.DecodeString(wrappedKeyB64)
if err != nil {
return nil, fmt.Errorf("failed to decode wrapped key: %w", err)
}
// Parse the PEM-encoded private key
block, _ := pem.Decode([]byte(privateKeyPEM))
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
// Parse the private key
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
// Unwrap the file key using RSA-OAEP
fileKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, wrappedKey, nil)
if err != nil {
return nil, fmt.Errorf("failed to unwrap key: %w", err)
}
return fileKey, nil
}
// ShareRecording creates a wrapped key for a recipient to access a recording
func (rs *RecordingService) ShareRecording(recordingID int, recipientName, recipientPublicKeyPEM string) error {
rs.mu.Lock()
defer rs.mu.Unlock()
// Get the recording
rec, err := rs.db.GetRecording(recordingID)
if err != nil {
return fmt.Errorf("failed to get recording: %w", err)
}
// Check if recording is encrypted
if !rec.Encrypted {
return fmt.Errorf("recording is not encrypted, sharing not needed")
}
// NOTE: This function is a placeholder and not currently used.
// The actual sharing implementation is in keymanagementservice.go
// which handles the complete flow including passphrase prompt.
return fmt.Errorf("use keymanagementservice for sharing - this is a placeholder")
}