package keeper import ( "context" "fmt" "github.com/sonr-io/crypto/argon2" "github.com/sonr-io/crypto/mpc" "github.com/sonr-io/crypto/password" 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 }