mirror of
https://github.com/FiloSottile/age.git
synced 2025-12-23 05:25:14 +00:00
age: use native identities first in Decrypt
This commit is contained in:
committed by
Filippo Valsorda
parent
c6fcb5300c
commit
78947d862d
19
age.go
19
age.go
@@ -214,6 +214,7 @@ func (*NoIdentityMatchError) Error() string {
|
||||
//
|
||||
// It returns a Reader reading the decrypted plaintext of the age file read
|
||||
// from src. All identities will be tried until one successfully decrypts the file.
|
||||
// Native, non-interactive identities are tried before any other identities.
|
||||
//
|
||||
// If no identity matches the encrypted file, the returned error will be of type
|
||||
// [NoIdentityMatchError].
|
||||
@@ -240,6 +241,24 @@ func decryptHdr(hdr *format.Header, identities ...Identity) ([]byte, error) {
|
||||
if len(identities) == 0 {
|
||||
return nil, errors.New("no identities specified")
|
||||
}
|
||||
slices.SortStableFunc(identities, func(a, b Identity) int {
|
||||
var aIsNative, bIsNative bool
|
||||
switch a.(type) {
|
||||
case *X25519Identity, *HybridIdentity, *ScryptIdentity:
|
||||
aIsNative = true
|
||||
}
|
||||
switch b.(type) {
|
||||
case *X25519Identity, *HybridIdentity, *ScryptIdentity:
|
||||
bIsNative = true
|
||||
}
|
||||
if aIsNative && !bIsNative {
|
||||
return -1
|
||||
}
|
||||
if !aIsNative && bIsNative {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
stanzas := make([]*Stanza, 0, len(hdr.Recipients))
|
||||
for _, s := range hdr.Recipients {
|
||||
|
||||
44
age_test.go
44
age_test.go
@@ -285,6 +285,50 @@ func TestLabels(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// testIdentity is a non-native identity that records if Unwrap is called.
|
||||
type testIdentity struct {
|
||||
called bool
|
||||
}
|
||||
|
||||
func (ti *testIdentity) Unwrap(stanzas []*age.Stanza) ([]byte, error) {
|
||||
ti.called = true
|
||||
return nil, age.ErrIncorrectIdentity
|
||||
}
|
||||
|
||||
func TestDecryptNativeIdentitiesFirst(t *testing.T) {
|
||||
correct, err := age.GenerateX25519Identity()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
unrelated, err := age.GenerateX25519Identity()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
w, err := age.Encrypt(buf, correct.Recipient())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nonNative := &testIdentity{}
|
||||
|
||||
// Pass identities: unrelated native, non-native, correct native.
|
||||
// Native identities should be tried first, so correct should match
|
||||
// before nonNative is ever called.
|
||||
_, err = age.Decrypt(bytes.NewReader(buf.Bytes()), unrelated, nonNative, correct)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if nonNative.called {
|
||||
t.Error("non-native identity was called, but native identities should be tried first")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetachedHeader(t *testing.T) {
|
||||
i, err := age.GenerateX25519Identity()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user