Files
sonr/x/dwn/keeper/vault_secure.go
T

168 lines
4.6 KiB
Go
Raw Normal View History

2025-10-03 14:45:52 -04:00
package keeper
import (
"context"
"fmt"
2025-10-10 11:47:18 -04:00
"github.com/sonr-io/crypto/argon2"
"github.com/sonr-io/crypto/mpc"
"github.com/sonr-io/crypto/password"
2025-10-03 14:45:52 -04:00
didtypes "github.com/sonr-io/sonr/x/did/types"
)
// CreateVaultForDIDSecure creates a vault with user-provided password
func (k Keeper) CreateVaultForDIDSecure(
ctx context.Context,
did string,
owner string,
vaultID string,
keyID string,
userPassword []byte,
enclaveData *mpc.EnclaveData,
) (*didtypes.CreateVaultResponse, error) {
// Validate password strength
validator := password.NewValidator(password.DefaultPasswordConfig())
if err := validator.Validate(userPassword); err != nil {
return nil, fmt.Errorf("password validation failed: %w", err)
}
// Create Argon2id KDF with default secure parameters
kdf := argon2.New(argon2.DefaultConfig())
// Generate secure salt
salt, err := kdf.GenerateSalt()
if err != nil {
return nil, fmt.Errorf("failed to generate salt: %w", err)
}
// Derive encryption key using Argon2id
derivedKey := kdf.DeriveKey(userPassword, salt)
// Clear password from memory
defer password.ZeroBytes(userPassword)
// Encrypt enclave data with derived key
encryptedData, err := k.encryptEnclaveData(enclaveData, derivedKey)
if err != nil {
return nil, fmt.Errorf("failed to encrypt vault data: %w", err)
}
// Store vault with encrypted data and salt
vaultState, err := k.storeSecureVault(ctx, vaultID, owner, encryptedData, salt)
if err != nil {
return nil, fmt.Errorf("failed to store secure vault: %w", err)
}
return &didtypes.CreateVaultResponse{
VaultID: vaultState.VaultId,
}, nil
}
// UnlockVault unlocks a vault using the user's password
func (k Keeper) UnlockVault(
ctx context.Context,
vaultID string,
userPassword []byte,
) (*mpc.EnclaveData, error) {
// Retrieve vault state with salt
vaultState, err := k.getVaultState(ctx, vaultID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve vault: %w", err)
}
if len(vaultState.Salt) == 0 {
return nil, fmt.Errorf("vault salt not found")
}
// Create KDF with same config as creation
kdf := argon2.New(argon2.DefaultConfig())
// Derive key using stored salt
derivedKey := kdf.DeriveKey(userPassword, vaultState.Salt)
// Clear password from memory
defer password.ZeroBytes(userPassword)
// Decrypt enclave data
enclaveData, err := k.decryptEnclaveData(vaultState.EncryptedData, derivedKey)
if err != nil {
return nil, fmt.Errorf("failed to decrypt vault: invalid password")
}
return enclaveData, nil
}
// encryptEnclaveData encrypts enclave data with AES-GCM
func (k Keeper) encryptEnclaveData(data *mpc.EnclaveData, key []byte) ([]byte, error) {
// Implementation would use AES-GCM for authenticated encryption
// This is a placeholder - actual implementation needs crypto/cipher
// For now, return a placeholder
// In production, this would:
// 1. Serialize enclave data to JSON
// 2. Create AES-GCM cipher with key
// 3. Generate nonce
// 4. Encrypt and authenticate data
// 5. Return nonce + ciphertext
return []byte("encrypted_placeholder"), nil
}
// decryptEnclaveData decrypts enclave data
func (k Keeper) decryptEnclaveData(encryptedData []byte, key []byte) (*mpc.EnclaveData, error) {
// Implementation would use AES-GCM for authenticated decryption
// This is a placeholder - actual implementation needs crypto/cipher
// For now, return a placeholder
// In production, this would:
// 1. Extract nonce from encrypted data
// 2. Create AES-GCM cipher with key
// 3. Decrypt and verify authentication
// 4. Deserialize JSON to enclave data
// 5. Return decrypted enclave data
return &mpc.EnclaveData{}, nil
}
// storeSecureVault stores encrypted vault data with salt
func (k Keeper) storeSecureVault(
ctx context.Context,
vaultID string,
owner string,
encryptedData []byte,
salt []byte,
) (*VaultStateWithSalt, error) {
// This would store the vault state with salt in the database
// For now, return a placeholder
vaultState := &VaultStateWithSalt{
VaultId: vaultID,
Owner: owner,
EncryptedData: encryptedData,
Salt: salt,
}
// In production: k.OrmDB.VaultStateTable().Insert(ctx, vaultState)
return vaultState, nil
}
// getVaultState retrieves vault state with salt
func (k Keeper) getVaultState(ctx context.Context, vaultID string) (*VaultStateWithSalt, error) {
// This would retrieve the vault state from the database
// For now, return a placeholder
return &VaultStateWithSalt{
VaultId: vaultID,
Salt: []byte("placeholder_salt"),
}, nil
}
// VaultStateWithSalt extends vault state with salt storage
type VaultStateWithSalt struct {
VaultId string
Owner string
EncryptedData []byte
Salt []byte
}