encryption.go RawHistoryFolder
1package disk
2
3import (
4 "errors"
5
6 "github.com/bnema/archup/internal/domain/user"
7)
8
9// EncryptionType represents the disk encryption method
10type EncryptionType int
11
12const (
13 // EncryptionTypeNone means no encryption
14 EncryptionTypeNone EncryptionType = iota
15
16 // EncryptionTypeLUKS means LUKS encryption (basic)
17 EncryptionTypeLUKS
18
19 // EncryptionTypeLUKSLVM means LUKS with LVM
20 EncryptionTypeLUKSLVM
21)
22
23// String returns human-readable encryption type name
24func (e EncryptionType) String() string {
25 switch e {
26 case EncryptionTypeLUKS:
27 return "LUKS"
28 case EncryptionTypeLUKSLVM:
29 return "LUKS+LVM"
30 default:
31 return "None"
32 }
33}
34
35// IsEncrypted returns true if encryption is enabled
36func (e EncryptionType) IsEncrypted() bool {
37 return e != EncryptionTypeNone
38}
39
40// EncryptionConfig is an immutable value object representing encryption configuration
41type EncryptionConfig struct {
42 encType EncryptionType
43 password string
44}
45
46// NewEncryptionConfig creates a new encryption configuration with validation
47func NewEncryptionConfig(encType EncryptionType, password string) (*EncryptionConfig, error) {
48 // If encryption is enabled, password is required
49 if encType.IsEncrypted() && password == "" {
50 return nil, errors.New("encryption password required when encryption is enabled")
51 }
52
53 // If encryption is disabled, password should be empty
54 if !encType.IsEncrypted() && password != "" {
55 return nil, errors.New("password cannot be set when encryption is disabled")
56 }
57
58 // Validate password strength if encryption is enabled
59 if encType.IsEncrypted() {
60 if err := validateEncryptionPassword(password); err != nil {
61 return nil, err
62 }
63 }
64
65 return &EncryptionConfig{
66 encType: encType,
67 password: password,
68 }, nil
69}
70
71// EncryptionType returns the encryption type
72func (e *EncryptionConfig) EncryptionType() EncryptionType {
73 return e.encType
74}
75
76// IsEncrypted returns true if encryption is enabled
77func (e *EncryptionConfig) IsEncrypted() bool {
78 return e.encType.IsEncrypted()
79}
80
81// HasPassword returns true if a password is set
82// (always true if encrypted, always false if not)
83func (e *EncryptionConfig) HasPassword() bool {
84 return e.password != ""
85}
86
87// String returns human-readable representation
88func (e *EncryptionConfig) String() string {
89 return "EncryptionConfig(type=" + e.encType.String() + ", encrypted=" + boolToString(e.IsEncrypted()) + ")"
90}
91
92// Equals checks if two EncryptionConfig objects are equal
93// Note: Password comparison is constant-time safe
94func (e *EncryptionConfig) Equals(other *EncryptionConfig) bool {
95 if other == nil {
96 return false
97 }
98 return e.encType == other.encType && constantTimeEqual(e.password, other.password)
99}
100
101// Private helper functions
102
103func validateEncryptionPassword(password string) error {
104 // Delegate to user password validation (single source of truth)
105 return user.ValidatePassword(password)
106}
107
108// constantTimeEqual compares two strings in constant time to prevent timing attacks
109func constantTimeEqual(a, b string) bool {
110 if len(a) != len(b) {
111 return false
112 }
113
114 result := 0
115 for i := 0; i < len(a); i++ {
116 result |= int(a[i]) ^ int(b[i])
117 }
118
119 return result == 0
120}
121
122func boolToString(b bool) string {
123 if b {
124 return "true"
125 }
126 return "false"
127}