Move app packages under internal
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/tobischo/gokeepasslib/v3"
|
||||
)
|
||||
|
||||
type SecuritySettings struct {
|
||||
Cipher string
|
||||
KDF string
|
||||
}
|
||||
|
||||
const (
|
||||
CipherAES256 = "aes256"
|
||||
CipherChaCha20 = "chacha20"
|
||||
KDFAES = "aes-kdf"
|
||||
KDFArgon2 = "argon2"
|
||||
)
|
||||
|
||||
func SupportedSecuritySettings() (ciphers []string, kdfs []string) {
|
||||
return []string{CipherAES256, CipherChaCha20}, []string{KDFAES, KDFArgon2}
|
||||
}
|
||||
|
||||
func DetectSecuritySettings(config *KDBXConfig) SecuritySettings {
|
||||
settings := SecuritySettings{
|
||||
Cipher: CipherChaCha20,
|
||||
KDF: KDFArgon2,
|
||||
}
|
||||
if config == nil || config.Header == nil || config.Header.FileHeaders == nil {
|
||||
return settings
|
||||
}
|
||||
if slices.Equal(config.Header.FileHeaders.CipherID, gokeepasslib.CipherAES) {
|
||||
settings.Cipher = CipherAES256
|
||||
}
|
||||
if config.Header.FileHeaders.KdfParameters != nil && slices.Equal(config.Header.FileHeaders.KdfParameters.UUID, gokeepasslib.KdfAES4) {
|
||||
settings.KDF = KDFAES
|
||||
}
|
||||
return settings
|
||||
}
|
||||
|
||||
func NewSecurityConfig(settings SecuritySettings) (*KDBXConfig, error) {
|
||||
db := gokeepasslib.NewDatabase(gokeepasslib.WithDatabaseKDBXVersion4())
|
||||
config := &KDBXConfig{
|
||||
Header: cloneHeader(db.Header),
|
||||
InnerHeader: cloneInnerHeader(db.Content.InnerHeader),
|
||||
}
|
||||
return ApplySecuritySettings(config, settings)
|
||||
}
|
||||
|
||||
func ApplySecuritySettings(config *KDBXConfig, settings SecuritySettings) (*KDBXConfig, error) {
|
||||
if config == nil || config.Header == nil || config.Header.FileHeaders == nil {
|
||||
return NewSecurityConfig(settings)
|
||||
}
|
||||
out := &KDBXConfig{
|
||||
Header: cloneHeader(config.Header),
|
||||
InnerHeader: cloneInnerHeader(config.InnerHeader),
|
||||
}
|
||||
if out.Header.FileHeaders.KdfParameters == nil {
|
||||
defaults := gokeepasslib.NewDatabase(gokeepasslib.WithDatabaseKDBXVersion4())
|
||||
out.Header.FileHeaders.KdfParameters = cloneHeader(defaults.Header).FileHeaders.KdfParameters
|
||||
}
|
||||
switch settings.Cipher {
|
||||
case "", CipherChaCha20:
|
||||
out.Header.FileHeaders.CipherID = slices.Clone(gokeepasslib.CipherChaCha20)
|
||||
out.Header.FileHeaders.EncryptionIV = randomBytes(12)
|
||||
case CipherAES256:
|
||||
out.Header.FileHeaders.CipherID = slices.Clone(gokeepasslib.CipherAES)
|
||||
out.Header.FileHeaders.EncryptionIV = randomBytes(16)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported cipher %q", settings.Cipher)
|
||||
}
|
||||
|
||||
var salt [32]byte
|
||||
copy(salt[:], randomBytes(32))
|
||||
switch settings.KDF {
|
||||
case "", KDFArgon2:
|
||||
defaults := gokeepasslib.NewDatabase(gokeepasslib.WithDatabaseKDBXVersion4())
|
||||
kdf := defaults.Header.FileHeaders.KdfParameters
|
||||
out.Header.FileHeaders.KdfParameters = &gokeepasslib.KdfParameters{
|
||||
UUID: slices.Clone(gokeepasslib.KdfArgon2),
|
||||
Rounds: kdf.Rounds,
|
||||
Salt: salt,
|
||||
Parallelism: kdf.Parallelism,
|
||||
Memory: kdf.Memory,
|
||||
Iterations: kdf.Iterations,
|
||||
Version: kdf.Version,
|
||||
}
|
||||
case KDFAES:
|
||||
out.Header.FileHeaders.KdfParameters = &gokeepasslib.KdfParameters{
|
||||
UUID: slices.Clone(gokeepasslib.KdfAES4),
|
||||
Rounds: 6000,
|
||||
Salt: salt,
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported KDF %q", settings.KDF)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in New Issue
Block a user