Skip to content

Commit

Permalink
Fix: 1917 key caps (gopasspw#2047)
Browse files Browse the repository at this point in the history
* add Caps type to gpg-keys and dummy parse-func
* add deactivated keycap flag fixes gopasspw#1917
* make key.IsUsable depend on KeyCaps gopasspw#1917
* gopasspwgh-1917: add key-capabilities in key-tests
* gopasspwgh-1917: SubKey Capabilities are also in PrimaryKey Caps (uppercase)
* gopasspwgh-1917: provide some meaningful pointers in key error msg

RELEASE_NOTES=[FEATURE] only accept keys with "encryption" key capability

Signed-off-by: Thomas Mantl <thomas.mantl@redgears.net>
  • Loading branch information
TM2500 authored Nov 26, 2021
1 parent d289fe6 commit a385d8b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
2 changes: 1 addition & 1 deletion internal/backend/crypto/gpg/cli/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (g *GPG) Encrypt(ctx context.Context, plaintext []byte, recipients []string
if err != nil {
debug.Log("Failed to check key %s. Adding anyway. %s", err)
} else if len(kl.UseableKeys(gpg.IsAlwaysTrust(ctx))) < 1 {
out.Printf(ctx, "Not using expired key %s for encryption", r)
out.Printf(ctx, "Not using invalid key %s for encryption. (Check its expiration date or its encryption capabilities.)", r)
continue
}
args = append(args, "--recipient", r)
Expand Down
23 changes: 23 additions & 0 deletions internal/backend/crypto/gpg/colons/parse_colons.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func Parse(reader io.Reader) gpg.KeyList {
Ownertrust: fields[8],
Identities: make(map[string]gpg.Identity, 1),
SubKeys: make(map[string]struct{}, 1),
Caps: parseKeyCaps(fields[11]),
}
case "sub":
fallthrough
Expand All @@ -111,6 +112,28 @@ func Parse(reader io.Reader) gpg.KeyList {
return kl
}

func parseKeyCaps(field string) gpg.Capabilities {
keycaps := gpg.Capabilities{}

if strings.Contains(field, "S") {
keycaps.Sign = true
}
if strings.Contains(field, "E") {
keycaps.Encrypt = true
}
if strings.Contains(field, "C") {
keycaps.Certify = true
}
if strings.Contains(field, "A") {
keycaps.Authentication = true
}
if strings.Contains(field, "D") {
keycaps.Deactivated = true
}

return keycaps
}

func parseColonIdentity(fields []string) gpg.Identity {
for i, f := range fields {
fields[i] = strings.Replace(f, "\\x3a", ":", -1)
Expand Down
16 changes: 16 additions & 0 deletions internal/backend/crypto/gpg/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,26 @@ type Key struct {
Fingerprint string
Identities map[string]Identity
SubKeys map[string]struct{}
Caps Capabilities
}

// Capabilities of a Key
type Capabilities struct {
Encrypt bool
Sign bool
Certify bool
Authentication bool
Deactivated bool
}

// IsUseable returns true if GPG would assume this key is useable for encryption
func (k Key) IsUseable(alwaysTrust bool) bool {
if k.Caps.Deactivated {
return false
}
if !k.Caps.Encrypt {
return false
}
if !k.ExpirationDate.IsZero() && k.ExpirationDate.Before(time.Now()) {
return false
}
Expand Down
20 changes: 20 additions & 0 deletions internal/backend/crypto/gpg/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ func genTestKey(args ...string) Key {
ExpirationDate: expiration,
},
},
Caps: Capabilities{
Encrypt: true,
Sign: false,
Certify: false,
Authentication: false,
Deactivated: false,
},
}
}

Expand Down Expand Up @@ -94,11 +101,21 @@ func TestUseability(t *testing.T) {
{},
{
ExpirationDate: time.Now().Add(-time.Second),
Caps: Capabilities{Encrypt: true},
},
{
ExpirationDate: time.Now().Add(time.Hour),
Caps: Capabilities{Encrypt: true},
Validity: "z",
},
{
ExpirationDate: time.Now().Add(time.Hour),
Caps: Capabilities{Deactivated: true},
},
{
ExpirationDate: time.Now().Add(time.Hour),
Caps: Capabilities{Encrypt: false},
},
} {
assert.False(t, k.IsUseable(false))
}
Expand All @@ -107,14 +124,17 @@ func TestUseability(t *testing.T) {
{
ExpirationDate: time.Now().Add(time.Hour),
Validity: "m",
Caps: Capabilities{Encrypt: true},
},
{
ExpirationDate: time.Now().Add(time.Hour),
Validity: "f",
Caps: Capabilities{Encrypt: true},
},
{
ExpirationDate: time.Now().Add(time.Hour),
Validity: "u",
Caps: Capabilities{Encrypt: true},
},
} {
assert.True(t, k.IsUseable(false))
Expand Down

0 comments on commit a385d8b

Please sign in to comment.