Re: A few comments on ‘age’

1,265 views
Skip to first unread message

Filippo Valsorda

unread,
Dec 31, 2019, 5:55:50 AM12/31/19
to age-dev

A blog post was recently published with some comments on the age design. I think it's awesome that people are looking at and discussing the design. Here are my initial thoughts on it.

Authenticated encryption This is a core disagreement on what age should do, or even on what users should want to do, I think. We designed age as a confidentiality tool, to replace the very very common task of encrypting a file to a PGP public key. I believe it delivers strictly better security guarantees than that, and I don't think the author disputes that. AEADs are required for confidentiality to defeat oracle attacks, so of course we use AEADs, but we are intentionally making no claim of sender authentication.

Solving for sender authentication instantly makes the UX and UI far more complicated. You can see that already in the author's post, where he finds themselves suggesting TOFU and filesystem keyrings. That's not just a confidentiality tool anymore.

Still, what the author suggests is not signing: anyone who could decrypt the file could alter it. I can't think of any way to communicate to a user who's specifying a verification key that the file is not actually guaranteed to come from the holder of the verification key. I'd fully expect users to shoot themselves in the foot with it, making it a bad security UX.

(I think there's actually a chance that the public key is required to generate a file that will decrypt for a certain secret key, making it an authenticator key already, but I'd be reticent to document that even if it turned out to be true, not to overload the semantics.)

Threat model The spec should absolutely explicitly address the threat model and security goals, agreed.

(I have a TODO item for it.)

crypto_box As an aside, I am no fan of crypto_box. It fails to separate sender key and recipient key, leading for example to trivial reflection attacks, similarly to the verification key issue above. (The docs delegate responsibility to the application: "just use odd nonces for the lexicographically lower key!") It's also a ludicrous C API, but libsodium fixed that.

Just use libsodium I don't think designing a new format is a good time to follow the overused "don't roll your own crypto" mantra. I stuck to the most boring thing that would do the job. We disagree on what the job should be, but that decision shouldn't be made based on what is available in libsodium.

JOSE alg header I don't see the parallel: keys are indeed tied to a single algorithm, like the linked post suggests. The algorithm names in the header don't instruct the implementation on how to process the message, they are just there to easily match to the available user-provided identities.

In particular this bit seems like a misunderstanding:

In order to decrypt the file key it trusts the header to tell it what algorithm to use.

The implementations trust the configured identities, and then match them to the header recipients.

Cryptographic Doom Principle Heh, I remember thinking about this when adding the header MAC, but this is unavoidable: you always need to do key establishment before you can check a MAC.


Neil Madden

unread,
Jan 1, 2020, 3:01:21 AM1/1/20
to age-dev
Happy new year to all. I wrote a brief response in the comments on my blog, but I thought I’d send a more detailed response here.

On Tuesday, 31 December 2019 10:55:50 UTC, Filippo Valsorda wrote:
> A blog post was recently published with some comments on the age design. I think it's awesome that people are looking at and discussing the design. Here are my initial thoughts on it.
>
> Authenticated encryption This is a core disagreement on what age should do, or even on what users should want to do, I think. We designed age as a confidentiality tool, to replace the very very common task of encrypting a file to a PGP public key. I believe it delivers strictly better security guarantees than that, and I don't think the author disputes that. AEADs are required for confidentiality to defeat oracle attacks, so of course we use AEADs, but we are intentionally making no claim of sender authentication.

What oracle attacks are you worried about in an offline file encryption tool?

As I mentioned in my blog post, the age spec links to a blog post from Adam Langley [1] that discusses the risks of streaming decryption when piping into downstream tools like tar or shell. The attacks mentioned in that blog post are not against confidentiality but due to the release of unauthenticated plaintext. *All* of the plaintext is unauthenticated when using age with anything other than scrypt currently.

An attacker who is in a position to carry out any chosen ciphertext attack against age is also in a position to simply replace the entire encrypted content with one of their own choosing, which is absolutely devastating in these cases.

>
> Solving for sender authentication instantly makes the UX and UI far more complicated. You can see that already in the author's post, where he finds themselves suggesting TOFU and filesystem keyrings. That's not just a confidentiality tool anymore.

Agreed, but I fundamentally disagree that a confidentiality-only tool is safe to use.

>
> Still, what the author suggests is not signing: anyone who could decrypt the file could alter it. I can't think of any way to communicate to a user who's specifying a verification key that the file is not actually guaranteed to come from the holder of the verification key. I'd fully expect users to shoot themselves in the foot with it, making it a bad security UX.

Firstly, I think this is a much lesser problem than the issues age currently has with releasing unauthenticated plaintext.

Secondly, this is only a problem with multi-recipient messages. Outside of email I’m not sure what the use-cases are for multi-recipient file encryption.

Thirdly, this can be fixed at the cost of other trade-offs. For example, you can include a hash of the entire file in each per-recipient encrypted key blob at the cost of giving up streaming support. Or you can give up streaming support for encryption only and include the root of a hash chain in the recipient blobs and then the hash of the next segment in each prior segment. Or you can include a list of hashes of each segment, which would allow both streaming encryption and streaming decryption at the cost of increased storage space, changing the header to a footer, and requiring random access during decryption (to read the footer and then seek back to the start). I’m sure there are more sophisticated variants.

>
> (I think there's actually a chance that the public key is required to generate a file that will decrypt for a certain secret key, making it an authenticator key already, but I'd be reticent to document that even if it turned out to be true, not to overload the semantics.)

I don’t think keeping the public key secret is a good strategy. For a start when using ssh keys these are obviously known to any server the user has authenticated to (not to mention GitHub). Secondly, cryptographic primitives may leak details of the public key - eg you can recover the public key (or a small number of candidates) from an ECDSA signature, and RSA leaks details of the modulus over time.

>
> Threat model The spec should absolutely explicitly address the threat model and security goals, agreed.
>
> (I have a TODO item for it.)
>
> crypto_box As an aside, I am no fan of crypto_box. It fails to separate sender key and recipient key, leading for example to trivial reflection attacks, similarly to the verification key issue above. (The docs delegate responsibility to the application: "just use odd nonces for the lexicographically lower key!") It's also a ludicrous C API, but libsodium fixed that.
>
> Just use libsodium I don't think designing a new format is a good time to follow the overused "don't roll your own crypto" mantra. I stuck to the most boring thing that would do the job. We disagree on what the job should be, but that decision shouldn't be made based on what is available in libsodium.
>

I’m not sure you can criticise crypto_box for not providing high-level application-specific semantics (are reflection attacks relevant for file encryption) and also say that libsodium is not flexible enough for your application-specific needs. Personally I think crypto_box is exactly what you need and libsodium already implemented exactly the streaming AEAD interface you need [2].


> JOSE alg header I don't see the parallel: keys are indeed tied to a single algorithm, like the linked post suggests. The algorithm names in the header don't instruct the implementation on how to process the message, they are just there to easily match to the available user-provided identities.
>
> In particular this bit seems like a misunderstanding:
>
> In order to decrypt the file key it trusts the header to tell it what algorithm to use.
>
> The implementations trust the configured identities, and then match them to the header recipients.

Ok, this is a misunderstanding on my part of how age processes the header. Apologies, I’ll correct that in the blog.

Out of interest, why use the key type for this at all rather than say a truncated hash of the public key (as you do for ssh keys)? The key type would seem not very selective.

>
> Cryptographic Doom Principle Heh, I remember thinking about this when adding the header MAC, but this is unavoidable: you always need to do key establishment before you can check a MAC.

If you’re not making any kind of trust decision based on anything in the header, do you need the MAC?

[1]: https://www.imperialviolet.org/2014/06/27/streamingencryption.html
[2]: https://download.libsodium.org/doc/secret-key_cryptography/secretstream

K. York

unread,
Jan 2, 2020, 9:54:45 AM1/2/20
to Neil Madden, age-dev
One comment on use cases; I will leave the cryptography to the cryptographers.


On Wed, Jan 1, 2020, 12:01 AM Neil Madden <neil.e...@gmail.com> wrote:
Happy new year to all. I wrote a brief response in the comments on my blog, but I thought I’d send a more detailed response here.

On Tuesday, 31 December 2019 10:55:50 UTC, Filippo Valsorda  wrote:
> A blog post was recently published with some comments on the age design. I think it's awesome that people are looking at and discussing the design. Here are my initial thoughts on it.
>
> Authenticated encryption This is a core disagreement on what age should do, or even on what users should want to do, I think. We designed age as a confidentiality tool, to replace the very very common task of encrypting a file to a PGP public key. I believe it delivers strictly better security guarantees than that, and I don't think the author disputes that. AEADs are required for confidentiality to defeat oracle attacks, so of course we use AEADs, but we are intentionally making no claim of sender authentication.

What oracle attacks are you worried about in an offline file encryption tool?
I guarantee that someone is going to hook it up to a web server, that's just what people do these days :)

You can imagine an interface like SecureDrop that allows anonymous submission of encrypted files.

--
You received this message because you are subscribed to the Google Groups "age-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to age-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/age-dev/e2ec4400-b3e8-462c-8ff3-1c29266a6def%40googlegroups.com.

Neil Madden

unread,
Jan 2, 2020, 11:37:27 AM1/2/20
to K. York, age-dev
On 2 Jan 2020, at 14:54, K. York <kane...@gmail.com> wrote:

One comment on use cases; I will leave the cryptography to the cryptographers.

On Wed, Jan 1, 2020, 12:01 AM Neil Madden <neil.e...@gmail.com> wrote:
Happy new year to all. I wrote a brief response in the comments on my blog, but I thought I’d send a more detailed response here.

On Tuesday, 31 December 2019 10:55:50 UTC, Filippo Valsorda  wrote:
> A blog post was recently published with some comments on the age design. I think it's awesome that people are looking at and discussing the design. Here are my initial thoughts on it.
>
> Authenticated encryption This is a core disagreement on what age should do, or even on what users should want to do, I think. We designed age as a confidentiality tool, to replace the very very common task of encrypting a file to a PGP public key. I believe it delivers strictly better security guarantees than that, and I don't think the author disputes that. AEADs are required for confidentiality to defeat oracle attacks, so of course we use AEADs, but we are intentionally making no claim of sender authentication.

What oracle attacks are you worried about in an offline file encryption tool?
I guarantee that someone is going to hook it up to a web server, that's just what people do these days :)

You can imagine an interface like SecureDrop that allows anonymous submission of encrypted files.

Surely the whole point of SecureDrop is that the decryption happens offline on an air-gapped computer?

-- Neil

podde...@fh-muenster.de

unread,
Jan 7, 2020, 11:18:51 AM1/7/20
to age-dev
Filippo, you said that,

```
(...) users should never be faced with an algorithm choice. Ever.

Users should be faced with use case choices. Do you want a public key? Do you want a passphrase?
```

I completly agree on the first part. That's why I like to discuss if <passphrase> and <public key> are really the use cases age should advertise to its users.

The problem is that

    `age -r <pubkey>  -o backup.zip.age  backup.zip`

is *probably* not what a user should do. Yet, the tool makes it very simple.

Encryption is an overloaded term often confused with "secure". With that mental model, it is tempting to upload files somewhere for later retrieval. However, encryption in age comes with a huge caveat: it does not guarantee that you have decrypted *your* files. Contrary, uploading passphrase-encrypted files is (probably) fine. We should not try to explain this to users.

On a side note: the decision if a file is "authentic" or not can often be made by common sense (as we know and hate from email). A text message can be "authentic" based on its content (don't judge me.) An attacker can exchange the whole message, but may never learn a secret place or a high-entropy secret nickname.

So, in a sense, the nature and appropriation of a file determines which encryption method is appropriate. I am worried people will get this wrong.

Maybe we can *really* make use cases part of the interface?

E.g.

`age lock <file> ...`
`age unlock <file> ...`

`age wrap-to <pubkey> ...`
`age unwrap-unknown-package ...`

(This are only half-baked examples, but I hope you get the idea.)

I fear that for now only experts can correctly determine what age should and should not be used for.
Reply all
Reply to author
Forward
0 new messages