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
|
// 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.
|
// 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
|
// If no identity matches the encrypted file, the returned error will be of type
|
||||||
// [NoIdentityMatchError].
|
// [NoIdentityMatchError].
|
||||||
@@ -240,6 +241,24 @@ func decryptHdr(hdr *format.Header, identities ...Identity) ([]byte, error) {
|
|||||||
if len(identities) == 0 {
|
if len(identities) == 0 {
|
||||||
return nil, errors.New("no identities specified")
|
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))
|
stanzas := make([]*Stanza, 0, len(hdr.Recipients))
|
||||||
for _, s := range 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) {
|
func TestDetachedHeader(t *testing.T) {
|
||||||
i, err := age.GenerateX25519Identity()
|
i, err := age.GenerateX25519Identity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user