mirror of
https://github.com/FiloSottile/age.git
synced 2025-12-23 05:25:14 +00:00
age: move the scrypt lone recipient check out of Decrypt
The important one is the decryption side one, because when a user types a password they expect it to both decrypt and authenticate the file. Moved that one out of Decrypt and into ScryptIdentity, now that Identities get all the stanzas. special_cases-- This also opens the door to other Identity implementations that do allow multiple scrypt recipients, if someone really wants that. The CLI will never allow it, but an explicit choice by an API consumer feels like something we shouldn't interfere with. Moreover, this also allows alternative Identity implementations that use different recipient types to replicate the behavior if they have the same authentication semantics. The encryption side one is only a courtesy, to stop API users from making files that won't decrypt. Unfortunately, that one needs to stay as a special case in Encrypt, as the Recipient can't see around itself. However, changed it to a type assertion, so custom recipients can generate multiple scrypt recipient stanzas, if they really want.
This commit is contained in:
21
age.go
21
age.go
@@ -103,6 +103,16 @@ func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error) {
|
||||
return nil, errors.New("no recipients specified")
|
||||
}
|
||||
|
||||
// As a best effort, prevent an API user from generating a file that the
|
||||
// ScryptIdentity will refuse to decrypt. This check can't unfortunately be
|
||||
// implemented as part of the Recipient interface, so it lives as a special
|
||||
// case in Encrypt.
|
||||
for _, r := range recipients {
|
||||
if _, ok := r.(*ScryptRecipient); ok && len(recipients) != 1 {
|
||||
return nil, errors.New("an ScryptRecipient must be the only one for the file")
|
||||
}
|
||||
}
|
||||
|
||||
fileKey := make([]byte, fileKeySize)
|
||||
if _, err := rand.Read(fileKey); err != nil {
|
||||
return nil, err
|
||||
@@ -118,11 +128,6 @@ func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error) {
|
||||
hdr.Recipients = append(hdr.Recipients, (*format.Stanza)(s))
|
||||
}
|
||||
}
|
||||
for _, s := range hdr.Recipients {
|
||||
if s.Type == "scrypt" && len(hdr.Recipients) != 1 {
|
||||
return nil, errors.New("an scrypt recipient must be the only one")
|
||||
}
|
||||
}
|
||||
if mac, err := headerMAC(fileKey, hdr); err != nil {
|
||||
return nil, fmt.Errorf("failed to compute header MAC: %v", err)
|
||||
} else {
|
||||
@@ -169,12 +174,6 @@ func Decrypt(src io.Reader, identities ...Identity) (io.Reader, error) {
|
||||
return nil, fmt.Errorf("failed to read header: %v", err)
|
||||
}
|
||||
|
||||
for _, r := range hdr.Recipients {
|
||||
if r.Type == "scrypt" && len(hdr.Recipients) != 1 {
|
||||
return nil, errors.New("an scrypt recipient must be the only one")
|
||||
}
|
||||
}
|
||||
|
||||
stanzas := make([]*Stanza, 0, len(hdr.Recipients))
|
||||
for _, s := range hdr.Recipients {
|
||||
stanzas = append(stanzas, (*Stanza)(s))
|
||||
|
||||
Reference in New Issue
Block a user