Hacker News new | past | comments | ask | show | jobs | submit | more FiloSottile's comments login

Thanks for sharing, always happy when my projects inspire alternatives addressing different parts of the design space. Here are a few quick comments based on skimming the documentation, let me know if I misinterpreted anything.

- signing support

This has always been a non-goal for age. It makes the UX significantly more complex, but it's good if different tools have different goals.

I can't quite make out from https://www.kryptor.co.uk/specification if it does proper signcryption, sign-then-encrypt (vulnerable to signature stripping and re-signing), or encrypt-then-sign (vulnerable to decrypt-reencrypt-forward, like OpenPGP). If the latter two, it's a missed opportunity to offer more security than age+minisign can offer and I encourage the author to look into it!

- sender authentication

I wrote about this. tl;dr age has authentication, but I am not sure what a non-sharp UX around it would be, so I don't advertise it. https://words.filippo.io/dispatches/age-authentication/

- post-quantum security

As https://www.kryptor.co.uk/security-limitations#post-quantum-... acknowledges, "the asymmetric algorithms in Kryptor aren't post-quantum secure". There is support for adding a pre-shared symmetric key, although I did not find the pre-shared key in the usage section, but I would argue that is not asymmetric encryption.

In this sense, I would actually argue that Kryptor is just as post-quantum secure as age: age's symmetric encryption (the passphrase mode) is post-quantum (see https://words.filippo.io/dispatches/post-quantum-age/). We don't support adding a pre-shared symmetric key to asymmetric encryption, but if you have a secure channel to establish a pre-shared key, you should just use passphrase mode.

age does have a third-party fully post-quantum asymmetric encryption plugin (https://github.com/keisentraut/age-plugin-sntrup761x25519) and I plan to make an ML-KEM one once the standard is out.

- key commitment

This is a pretty wonky topic. age as a whole is key committing (you can't make a file that decrypts with two age identities as different plaintexts, some academic researchers tried!). Our file key encryption is not (https://github.com/FiloSottile/age/commit/2194f6962c8bb3bca8...) which means that if you host an online service that accepts an age file and decrypts it with a passphrase and returns an error if it's incorrect, an attacker can do a bruteforce two passphrases at a time instead of one at a time. Given the online oracle is already unusual as a setting, I am not interested in adding complexity to solve this one.

- private key encryption

age supports that! https://github.com/FiloSottile/age?tab=readme-ov-file#passph...

It's not the default because most threat models don't need it: if you have FDE, who's an attacker that can read files from your disk but not replace the age binary in $PATH?

- indistinguishability from random

Not an age goal, actually we very intentionally put "age-encryption.org/v1" in the header so you can run file(1), and specify the type of the recipients to help plugins disambiguate files. The default recipient type doesn't leak any other metadata (i.e. you can't link age files encrypted to the same recipient).

- size padding

This is a good idea and slated for age v2.


Massive fan of age and congrats on its success!! On size padding, I know you've patiently listened to me before on this, but I'll always take a chance to advocate for an approach like PURBs ( https://petsymposium.org/2019/files/papers/issue4/popets-201... ).

Let's say you're in a country that suppresses certain material, like copies of the Bible, or the Hacker Manifesto, or whatever; if the authorities find an encrypted file that closely matches the size of that material; that could do you in. But maybe a more realistic case is how the size of maps tiles alone is enough to figure out where you are looking on a map (https://ioactive.com/ssl-traffic-analysis-on-google-maps/), or the size of streaming video segments (https://www.cs.cornell.edu/~shmat/shmat_usenix17.pdf) gives away what you are watching. Both real-world examples of size side-channels. It's not un-imaginable that someone could use a tool like age to build bigger systems like that, where the leaks creep in.


My age v2 note for padding says “use Padmé, see Colm’s comments” :)

I’m not really sold on the UR part of PURBs, though: age wants to avoid asking for a passphrase if the file is not passphrase encrypted, and age-plugin-yubikey wants to avoid asking for a PIN if it’s for the wrong YubiKey. These are tradeoffs and it’s not obvious the very end of the spectrum (uniform random) is the right spot.


re: https://words.filippo.io/dispatches/age-authentication/#on-c...

other than inelegance and the computational overhead, is there a reason why sign then encrypt then sign wouldn't work for this?


Assuming that implementation never skip verifying the second signature, and compare the signing keys, that should be ok.


_o/ hi all, age author here! age is the one of my projects that grew most organically into an ecosystem. It's always great to see what people build with it. Happy to answer any questions.

Here are some previous discussions

132 points on Feb 26, 2023 | 77 comments | https://news.ycombinator.com/item?id=34936504

126 points on Sept 26, 2022 | 54 comments | https://news.ycombinator.com/item?id=32980141

113 points on June 11, 2022 | 33 comments | https://news.ycombinator.com/item?id=31705670

494 points on Sept 6, 2021 | 88 comments | https://news.ycombinator.com/item?id=28435613

466 points on Dec 27, 2019 | 199 comments | https://news.ycombinator.com/item?id=21895671

and here some related resources

- a list of age ecosystem projects https://github.com/FiloSottile/awesome-age

- the format specification https://c2sp.org/age

- the Go library docs https://pkg.go.dev/filippo.io/age

- the CLI man page https://filippo.io/age/age.1

- the large reusable test suite (which I should write about!) https://c2sp.org/CCTV/age

- an interoperable Rust implementation by @str4d https://github.com/str4d/rage

- an official TypeScript implementation https://github.com/FiloSottile/typage (based on libsodium.js in the latest version, and on pure-js Noble libraries on main)

- a YubiKey plugin by @str4d https://github.com/str4d/age-plugin-yubikey

- the plugin protocol specification https://c2sp.org/age-plugin

- a Windows GUI by @spieglt https://github.com/spieglt/winage

- a discussion of the authentication properties of age https://words.filippo.io/dispatches/age-authentication/

- a discussion of the plugin architecture https://words.filippo.io/dispatches/age-plugins/

- a discussion of a potential post-quantum plugin https://words.filippo.io/dispatches/post-quantum-age/

- a password-store fork that uses age instead of gpg https://github.com/FiloSottile/passage (see also: how I use it with a YubiKey https://words.filippo.io/dispatches/passage/)


Age is great. I used the rust crate to write an ftp server that encrypts the files before they hit disk (specific use case is having a drop box for my network scanner) and I love the simplicity and composability it provides.

One feature request: it would be awesome to have paraphrase encryption for age private keys.


Identity files can be passphrase encrypted and cmd/age will transparently ask for the passphrase before using them. Is that what you meant?

https://github.com/FiloSottile/age?tab=readme-ov-file#passph...


Yeah that’s it. Probably just wasn’t supported in the rust age library when I used it. Will double check.


Have you considered writing passage in Go to integrate age and age-plugin-yubikey as a single binary to make it more convenient to setup and use?


Combining Passage, pass-otp, and age into a single Go app has actually been on my personal hobby-project TODO list (but I haven't gotten around to it yet).

Integrating age plugins into this binary is not something I would do, though. Besides the fact that the plugins are separate projects with their own release schedules, they are also in different languages (plugin-yubikey is Rust, plugin-se is Swift, ...), and you would need to fork them anyway for communication. I guess you could bundle the binaries together in a package, and make sure the search path searches for the bundled binaries as a fallback.


Maybe I'm dense but I can't figure out howto verify/authenticate encrypted files.

Is there something missing in the documentation.


Age is designed for a single purpose: Encryption and decryption of files. To create digital signatures use another specialized tool like minisign instead.

Specialized tools are simpler than one do-it-all tool.


Simpler, but not necessarily as capable! From < https://words.filippo.io/dispatches/age-authentication/>:

> If you encrypt and then sign, an attacker can strip your signature, replace it with their own, and make it look like they encrypted the file even if they don't actually know the contents.

> If you sign and then encrypt, the recipient can decrypt the file, keep your signature, and encrypt it to a different recipient, making it look like you intended to send the file to them.


Both cases assume that the user doesn't understand what a signature means. In either case it means that the signer certified the thing signed. Are paper signatures getting so rare that we are collectively starting to forget this?


> make it look like they encrypted the file even if they don't actually know the contents.

I might as well encrypt a message "add $10000 to my account" with the bank's public key, sign it with my own key and send it...


Afaik the x25519 recipient uses chacha20poly1305 which is authenticated


Only in the case of symmetrical encryption. Then the authentication is based on the shared secret key.


Hi

Do you have an opinion or comment on this? https://news.ycombinator.com/item?id=41159236


For those wondering, they answered https://news.ycombinator.com/item?id=41160037


That exist(ed)! c2goasm would compile C and then decompile it into Go asm.

https://github.com/minio/c2goasm


Elligator is a bidirectional map from random bytes to elliptic curve points, which is mainly useful for censorship resistance. Its state-of-the-art protocol integration as far as I know is obfs4 (https://gitlab.com/yawning/obfs4), one of the Tor circumvention pluggable transports (https://tb-manual.torproject.org/circumvention/). The others rely on disguising as other protocols rather than looking random.

Elligator implementations have a history of subtle bugs, arguably because there was not a spec, only a paper, although it looks like there are some third-party test vectors now.

In general the "inverse map" from random bytes to point is used only for censorship-resistance use cases, but the "direct map" turning random bytes (like a CSPRNG output or a hash) into a point is useful for a number of purposes in cryptography, like VRFs. That led to the direct map being specified more rigorously, like in https://www.rfc-editor.org/rfc/rfc9496.html#name-element-der... and https://datatracker.ietf.org/doc/html/rfc9380.

IMHO a map from a fixed amount of random bytes should be part of the fundamental group abstraction, and that's what Ristretto provides. The CFRG approach is slightly different, providing full domain-separated hash "suites" that go straight into a curve point.


As a historical note, the first time I recall seeing the anti-censorship use case was in “Telex” [1] which uses it to steganographically embed a ciphertext into a TLS random nonce, so that a router in the middle can detect whether the connection should go to its terminus or be routed somewhere else. However the authors of that paper didn’t have a standard primitive for doing this and so they had to make their own approach. Ironically, an even older use of the general approach is the NSA’s Dual EC DRBG generator [2], which has to encode elliptic curve points into random-looking bit sequences as part of its design as a PRNG. They ended up homebrewing that using standard curves by dropping several bits of each X coordinate, which in theory is all they need because there’s no need to go in the inverse direction. However the conjecture is that Dual EC is backdoored, and the backdoor requires an inverse mapping from bitstrings back to points; this has to be achieved by brute-forcing every possible point and testing.

None of this has anything to do with your comment but I love the history of these steganographic tricks.

[1] https://www.usenix.org/conference/usenix-security-11/telex-a... [2] https://en.m.wikipedia.org/wiki/Dual_EC_DRBG


Koblitz in "Elliptic Curve Cryptosystems" [1] dedicated section 3 to how to embed binary strings into points and back, which is of course necessary for elliptic curve ElGamal.

[1] https://doi.org/10.1090/S0025-5718-1987-0866109-5


Interestingly, the RCE fix was "smuggled" in public almost a month ago.

    When PerSourcePenalties are enabled, sshd(8) will monitor the exit
    status of its child pre-auth session processes. Through the exit
    status, it can observe situations where the session did not
    authenticate as expected. These conditions include when the client
    repeatedly attempted authentication unsucessfully (possibly indicating
    an attack against one or more accounts, e.g. password guessing), or
    when client behaviour caused sshd to crash (possibly indicating
    attempts to exploit sshd).

    When such a condition is observed, sshd will record a penalty of some
    duration (e.g. 30 seconds) against the client's address.
https://github.com/openssh/openssh-portable/commit/81c1099d2...

It's not really a reversable patch that gives anything away to attackers: it changes the binary architecture in a way that has the side-effect of removing the specific vulnerability and also mitigates the whole exploit class, if I understand it correctly. Very clever.


That's not the RCE fix, this is the RCE fix https://news.ycombinator.com/item?id=40843865

That's a previously-announced feature for dealing with junk connections that also happens to mitigate this vulnerability because it makes it harder to win the race. Discussed previously https://news.ycombinator.com/item?id=40610621


The ones you link are the "minimal patches for those can't/don't want to upgrade". The commit I am linking to is taken straight from the advisory.

    On June 6, 2024, this signal handler race condition was fixed by commit
    81c1099 ("Add a facility to sshd(8) to penalise particular problematic
    client behaviours"), which moved the async-signal-unsafe code from
    sshd's SIGALRM handler to sshd's listener process, where it can be
    handled synchronously:

      https://github.com/openssh/openssh-portable/commit/81c1099d22b81ebfd20a334ce986c4f753b0db29

    Because this fix is part of a large commit (81c1099), on top of an even
    larger defense-in-depth commit (03e3de4, "Start the process of splitting
    sshd into separate binaries"), it might prove difficult to backport. In
    that case, the signal handler race condition itself can be fixed by
    removing or commenting out the async-signal-unsafe code from the
    sshsigdie() function
The cleverness here is that this commit is both "a previously-announced feature for dealing with junk connections", and a mitigation for the exploit class against similar but unknown vulnerabilities, and a patch for the specific vulnerability because it "moved the async-signal-unsafe code from sshd's SIGALRM handler to sshd's listener process, where it can be handled synchronously".

The cleverness is that it fixes the vulnerability as part of doing something that makes sense on its own, so you wouldn't know it's the patch even looking at it.


No, it's a fix. It completely removes the signal race as well as introducing a mitigation for similar future bugs


These lines from the diff linked above are the fix:

    - /\* Log error and exit. \*/
    - sigdie("Timeout before authentication for %s port %d",
    -     ssh_remote_ipaddr(the_active_state),
    -     ssh_remote_port(the_active_state));
    + _exit(EXIT_LOGIN_GRACE);


Has this fix been pushed to / pulled by distributions yet?


It's fixed in Debian 12[1]. Debian 11 and earlier's SSH version was not vulnerable.

[1] https://security-tracker.debian.org/tracker/source-package/o...



And https://bugzilla.redhat.com/show_bug.cgi?id=2294904 (Fedora 40 issue)

EL 9 is also affected, but not yet released. The tracking task will update as things move along.


Fix pushed in openssh-9.3p1-11.fc39 and (in progress) openssh-9.6p1-1.fc40.4.


Ubuntu's also got patches out for 22.04 LTS, 23.10, and 24.04 LTS. See https://ubuntu.com/security/notices/USN-6859-1.

Amazon Linux 2023 is affected; Amazon Linux 1 & 2 are not. Status updates will be posted to https://explore.alas.aws.amazon.com/CVE-2024-6387.html


Gentoo: update to "net-misc/openssh-9.7_p1-r6" available since ~Mon 1.Jul.2024.

GLSA 202407-09: https://glsa.gentoo.org/glsa/202407-09

Package metadata & log: https://packages.gentoo.org/packages/net-misc/openssh


SUSE has the fixes under testing. I assume you could install them directly from OBS. I have not tried because I have no exposed system. https://www.suse.com/security/cve/CVE-2024-6387.html


Interesting that this comment has remained the topmost one for 2 days despite being incorrect and being corrected in the message right below it. I wonder if people are only reading the first message in the thread and upvoting and then leaving with the wrong impression.


It appears you’ve not read past the topmost reply to the topmost comment, and left with the wrong impression.


So it seems!


Assuming you’re referring to the birthday bound on blocks (https://sweet32.info) that’s a limit on blocks encrypted with a single key. XAES derives large keys per message, so it achieves what are commonly referred to as “better-than-birthday” bounds.


There is no space for 256 bits: 192 bits is 96 bits from the underlying nonce space, and 96 bits that go into the 128-bit CMAC block (along with the necessary prefix). We could make the CMAC input longer, but then we'd have to run the AES-256 block function more times (and we'd hit some annoying key control issues in the CMAC KDF).

This is actually similar to why XChaCha20Poly1305 has 192-bit nonces, and consistency with the other major extended-nonce AEAD is another mild advantage.


Reducing security below 128 bits in order to save a block of AES will anger the gods and surely we will be made to pay. Turn back now, while there is still time.


I don't disagree, actually. I was copying the NIST source document notation with 0¹²⁸ and 0¹²⁰10000111, but it probably does more harm than good. `X` was just me being too clever. (In my defense, `X` is formatted differently from variables in the original, and all variables are defined.)

Done. https://github.com/C2SP/C2SP/pull/86/files


“All of them” in what sense?

I use WhatsApp dozens of times a day, and interact with business accounts every couple months at most.


Good for you, you probably do not live in a country under digital colonialism where the gov allowed facebook et al to force internet providers to tax the pop with absurdly low and expensive data limits and then "not count" things like facebook and whatsapp and one music app.

In most of the global south, 100% of business have a whatsapp. In those places it pretty much replaced telephone and the green whatsapp icon is now what the current young generation recognize as the we did the black telephone outline on a business front next to a number.

and if you own a business, or is self employed, it is even worse: you live by that app.


Are you saying this is a worse alternative to other communication methods with businesses? What would you use with them that has better encryption?


The lack of encryption between myself and a business is less offensive than replacing an open standard (plain old telephone systems, eMail) with a proprietary and closed one, backed by a single, private corporation


I don't think they've been replaced, though?


De jure or de facto?


Neither.


i completely agree with your sentiment, but i will also say this.

As an expat, this feature has enabled me to transact with locals from the convenience of my phone, even though i don't have any local line and i will not bother to get a local SIM card, nor do i want to have a US SIM and a local one interchangeably.

It also enables me to be very effective when requesting services on demand, and cutting thru the on-hold time, disconnected calls, or the needless chitchat.

I have many bad things to say about WA, but making living more difficult in a foreign country is not one of them.


All of that can be achieved in the same way via email.


All of that can also be achieved by pigeon post.


The only difference is that email is more sane and actually does the job.


See, that's the problem.

Telephony is an artificial monopoly. There's not a single reason why you cannot call everyone around the globe for mostly free, as whatsapp proves. Yet here we are.


That’s the first TLS change suggestion, under the “Intermediate elision” heading.


Not quite, that is described as using transparancy logs to distribute the intermediate certs. Not optionally passed inline.


Wait, are we talking about removing OCSP stapling from TLS?


Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: