feat: support all cipher types (Login/SecureNote/Card/Identity)
- decryptCipher: full decrypt for Card (number/cvv/exp/brand) and Identity (all fields) - extractSecret: type-aware output (notes for SecureNote, JSON fields for Card/Identity) - tested: TEST_NOTE (SecureNote) and login secrets resolve by name
This commit is contained in:
1 parent
4408999bb9
commit
7934e58c37
2 files changed
+107
-1
No files matched your search
@@ -81,6 +81,7 @@ type SyncCipher struct {
|
||||
Notes *string `json:"notes"`
|
||||
Login *SyncLogin `json:"login"`
|
||||
Card *SyncCard `json:"card"`
|
||||
Identity *SyncIdentity `json:"identity"`
|
||||
Fields []SyncField `json:"fields"`
|
||||
}
|
||||
|
||||
@@ -99,6 +100,31 @@ type SyncCard struct {
|
||||
CardholderName *string `json:"cardholderName"`
|
||||
Number *string `json:"number"`
|
||||
Code *string `json:"code"`
|
||||
Brand *string `json:"brand"`
|
||||
ExpMonth *string `json:"expMonth"`
|
||||
ExpYear *string `json:"expYear"`
|
||||
}
|
||||
|
||||
// SyncIdentity contains encrypted identity data.
|
||||
type SyncIdentity struct {
|
||||
Title *string `json:"title"`
|
||||
FirstName *string `json:"firstName"`
|
||||
MiddleName *string `json:"middleName"`
|
||||
LastName *string `json:"lastName"`
|
||||
Address1 *string `json:"address1"`
|
||||
Address2 *string `json:"address2"`
|
||||
Address3 *string `json:"address3"`
|
||||
City *string `json:"city"`
|
||||
State *string `json:"state"`
|
||||
PostalCode *string `json:"postalCode"`
|
||||
Country *string `json:"country"`
|
||||
Company *string `json:"company"`
|
||||
Email *string `json:"email"`
|
||||
Phone *string `json:"phone"`
|
||||
SSN *string `json:"ssn"`
|
||||
Username *string `json:"username"`
|
||||
PassportNumber *string `json:"passportNumber"`
|
||||
LicenseNumber *string `json:"licenseNumber"`
|
||||
}
|
||||
|
||||
// SyncField contains encrypted custom field data.
|
||||
@@ -562,6 +588,69 @@ func decryptCipher(c SyncCipher, key SymmetricKey) (DecryptedItem, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if c.Card != nil {
|
||||
if c.Card.CardholderName != nil {
|
||||
if v, err := DecryptStr(*c.Card.CardholderName, key); err == nil && v != "" {
|
||||
item.Fields["cardholder_name"] = v
|
||||
}
|
||||
}
|
||||
if c.Card.Number != nil {
|
||||
if v, err := DecryptStr(*c.Card.Number, key); err == nil && v != "" {
|
||||
item.Fields["number"] = v
|
||||
}
|
||||
}
|
||||
if c.Card.Code != nil {
|
||||
if v, err := DecryptStr(*c.Card.Code, key); err == nil && v != "" {
|
||||
item.Fields["code"] = v
|
||||
}
|
||||
}
|
||||
if c.Card.Brand != nil {
|
||||
if v, err := DecryptStr(*c.Card.Brand, key); err == nil && v != "" {
|
||||
item.Fields["brand"] = v
|
||||
}
|
||||
}
|
||||
if c.Card.ExpMonth != nil {
|
||||
if v, err := DecryptStr(*c.Card.ExpMonth, key); err == nil && v != "" {
|
||||
item.Fields["exp_month"] = v
|
||||
}
|
||||
}
|
||||
if c.Card.ExpYear != nil {
|
||||
if v, err := DecryptStr(*c.Card.ExpYear, key); err == nil && v != "" {
|
||||
item.Fields["exp_year"] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.Identity != nil {
|
||||
idFields := map[string]*string{
|
||||
"title": c.Identity.Title,
|
||||
"first_name": c.Identity.FirstName,
|
||||
"middle_name": c.Identity.MiddleName,
|
||||
"last_name": c.Identity.LastName,
|
||||
"address1": c.Identity.Address1,
|
||||
"address2": c.Identity.Address2,
|
||||
"address3": c.Identity.Address3,
|
||||
"city": c.Identity.City,
|
||||
"state": c.Identity.State,
|
||||
"postal_code": c.Identity.PostalCode,
|
||||
"country": c.Identity.Country,
|
||||
"company": c.Identity.Company,
|
||||
"email": c.Identity.Email,
|
||||
"phone": c.Identity.Phone,
|
||||
"ssn": c.Identity.SSN,
|
||||
"username": c.Identity.Username,
|
||||
"passport_number": c.Identity.PassportNumber,
|
||||
"license_number": c.Identity.LicenseNumber,
|
||||
}
|
||||
for name, ptr := range idFields {
|
||||
if ptr != nil {
|
||||
if v, err := DecryptStr(*ptr, key); err == nil && v != "" {
|
||||
item.Fields[name] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range c.Fields {
|
||||
var name, value string
|
||||
if f.Name != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package vaultwarden
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"strings"
|
||||
@@ -229,8 +230,24 @@ func (c *Client) backgroundSync() {
|
||||
}
|
||||
|
||||
// extractSecret extracts the most relevant secret value from a decrypted item.
|
||||
// Priority: password > field named "value"/"secret"/"api_key" > notes > first field.
|
||||
// For Login: password > field named "value"/"secret"/"api_key" > notes > first field.
|
||||
// For SecureNote: notes (the whole note body).
|
||||
// For Card / Identity: a compact JSON of all decrypted fields.
|
||||
func extractSecret(item DecryptedItem) string {
|
||||
switch item.Type {
|
||||
case CipherTypeSecureNote:
|
||||
if item.Notes != "" {
|
||||
return item.Notes
|
||||
}
|
||||
case CipherTypeCard, CipherTypeIdentity:
|
||||
if len(item.Fields) > 0 {
|
||||
b, err := json.Marshal(item.Fields)
|
||||
if err == nil {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if item.Password != "" {
|
||||
return item.Password
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user