mirror of
https://github.com/FiloSottile/age.git
synced 2026-01-03 10:55:14 +00:00
cmd/age: reject passphrase-encrypted files if -i is used
Passphrase-encrypted files make age(1) block, which would be unexpected when decrypting files in a script using -i.
This commit is contained in:
@@ -265,14 +265,12 @@ func main() {
|
||||
}
|
||||
|
||||
switch {
|
||||
case decryptFlag && len(identityFlags) == 0:
|
||||
decryptPass(in, out)
|
||||
case decryptFlag:
|
||||
decrypt(identityFlags, in, out)
|
||||
decryptNotPass(identityFlags, in, out)
|
||||
case passFlag:
|
||||
pass, err := passphrasePromptForEncryption()
|
||||
if err != nil {
|
||||
errorf("%v", err)
|
||||
}
|
||||
encryptPass(pass, in, out, armorFlag)
|
||||
encryptPass(in, out, armorFlag)
|
||||
default:
|
||||
encryptNotPass(recipientFlags, recipientsFileFlags, identityFlags, in, out, armorFlag)
|
||||
}
|
||||
@@ -352,7 +350,12 @@ func encryptNotPass(recs, files []string, identities identityFlags, in io.Reader
|
||||
encrypt(recipients, in, out, armor)
|
||||
}
|
||||
|
||||
func encryptPass(pass string, in io.Reader, out io.Writer, armor bool) {
|
||||
func encryptPass(in io.Reader, out io.Writer, armor bool) {
|
||||
pass, err := passphrasePromptForEncryption()
|
||||
if err != nil {
|
||||
errorf("%v", err)
|
||||
}
|
||||
|
||||
r, err := age.NewScryptRecipient(pass)
|
||||
if err != nil {
|
||||
errorf("%v", err)
|
||||
@@ -388,12 +391,19 @@ func encrypt(recipients []age.Recipient, in io.Reader, out io.Writer, withArmor
|
||||
const crlfMangledIntro = "age-encryption.org/v1" + "\r"
|
||||
const utf16MangledIntro = "\xff\xfe" + "a\x00g\x00e\x00-\x00e\x00n\x00c\x00r\x00y\x00p\x00"
|
||||
|
||||
func decrypt(flags identityFlags, in io.Reader, out io.Writer) {
|
||||
identities := []age.Identity{
|
||||
// If there is an scrypt recipient (it will have to be the only one and)
|
||||
// this identity will be invoked.
|
||||
&LazyScryptIdentity{passphrasePromptForDecryption},
|
||||
type rejectScryptIdentity struct{}
|
||||
|
||||
func (rejectScryptIdentity) Unwrap(stanzas []*age.Stanza) ([]byte, error) {
|
||||
if len(stanzas) != 1 || stanzas[0].Type != "scrypt" {
|
||||
return nil, age.ErrIncorrectIdentity
|
||||
}
|
||||
errorWithHint("file is passphrase-encrypted but identities were specified with -i/--identity or -j",
|
||||
"remove all -i/--identity/-j flags to decrypt passphrase-encrypted files")
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func decryptNotPass(flags identityFlags, in io.Reader, out io.Writer) {
|
||||
identities := []age.Identity{rejectScryptIdentity{}}
|
||||
|
||||
for _, f := range flags {
|
||||
switch f.Type {
|
||||
@@ -412,6 +422,20 @@ func decrypt(flags identityFlags, in io.Reader, out io.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
decrypt(identities, in, out)
|
||||
}
|
||||
|
||||
func decryptPass(in io.Reader, out io.Writer) {
|
||||
identities := []age.Identity{
|
||||
// If there is an scrypt recipient (it will have to be the only one and)
|
||||
// this identity will be invoked.
|
||||
&LazyScryptIdentity{passphrasePromptForDecryption},
|
||||
}
|
||||
|
||||
decrypt(identities, in, out)
|
||||
}
|
||||
|
||||
func decrypt(identities []age.Identity, in io.Reader, out io.Writer) {
|
||||
rr := bufio.NewReader(in)
|
||||
if intro, _ := rr.Peek(len(crlfMangledIntro)); string(intro) == crlfMangledIntro ||
|
||||
string(intro) == utf16MangledIntro {
|
||||
|
||||
@@ -13,13 +13,13 @@ age(1) -- simple, modern, and secure file encryption
|
||||
optional and defaults to standard input. Only a single <INPUT> file may be
|
||||
specified. If `-o` is not specified, <OUTPUT> defaults to standard output.
|
||||
|
||||
If `--passphrase` is specified, the file is encrypted with a passphrase
|
||||
If `-p`/`--passphrase` is specified, the file is encrypted with a passphrase
|
||||
requested interactively. Otherwise, it's encrypted to one or more
|
||||
[RECIPIENTS][RECIPIENTS AND IDENTITIES] specified with `-r`/`--recipient` or
|
||||
`-R`/`--recipients-file`. Every recipient can decrypt the file.
|
||||
|
||||
In `--decrypt` mode, passphrase-encrypted files are detected automatically and
|
||||
the passphrase is requested interactively. Otherwise, one or more
|
||||
In `-d`/`--decrypt` mode, passphrase-encrypted files are detected automatically
|
||||
and the passphrase is requested interactively. Otherwise, one or more
|
||||
[IDENTITIES][RECIPIENTS AND IDENTITIES] specified with `-i`/`--identity` are
|
||||
used to decrypt the file.
|
||||
|
||||
@@ -111,9 +111,10 @@ overhead per recipient, plus 16 bytes every 64KiB of plaintext.
|
||||
d\. "`-`", causing one of the options above to be read from standard input.
|
||||
In this case, the <INPUT> argument must be specified.
|
||||
|
||||
This option can be repeated. Identities are tried in the order in which
|
||||
are provided, and the first one matching one of the file's recipients is
|
||||
used. Unused identities are ignored.
|
||||
This option can be repeated. Identities are tried in the order in which are
|
||||
provided, and the first one matching one of the file's recipients is used.
|
||||
Unused identities are ignored, but it is an error if the <INPUT> file is
|
||||
passphrase-encrypted and `-i`/`--identity` is specified.
|
||||
|
||||
If `-e`/`--encrypt` is explicitly specified (to avoid confusion),
|
||||
`-i`/`--identity` may also be used to encrypt to the `RECIPIENTS`
|
||||
|
||||
Reference in New Issue
Block a user