diff --git a/doc/age-keygen.1 b/doc/age-keygen.1 index b60958f..100c0bf 100644 --- a/doc/age-keygen.1 +++ b/doc/age-keygen.1 @@ -1,10 +1,10 @@ .\" generated with Ronn-NG/v0.9.1 .\" http://github.com/apjanke/ronn-ng/tree/0.9.1 -.TH "AGE\-KEYGEN" "1" "June 2024" "" +.TH "AGE\-KEYGEN" "1" "December 2025" "" .SH "NAME" \fBage\-keygen\fR \- generate age(1) key pairs .SH "SYNOPSIS" -\fBage\-keygen\fR [\fB\-o\fR \fIOUTPUT\fR] +\fBage\-keygen\fR [\fB\-pq\fR] [\fB\-o\fR \fIOUTPUT\fR] .br \fBage\-keygen\fR \fB\-y\fR [\fB\-o\fR \fIOUTPUT\fR] [\fIINPUT\fR] .br @@ -14,6 +14,11 @@ If the output is not going to a terminal, \fBage\-keygen\fR prints the public key to standard error\. .SH "OPTIONS" .TP +\fB\-pq\fR +Generate a post\-quantum hybrid ML\-KEM\-768 + X25519 key pair\. +.IP +In the future, this might become the default\. +.TP \fB\-o\fR, \fB\-\-output\fR=\fIOUTPUT\fR Write the identity to \fIOUTPUT\fR instead of standard output\. .IP @@ -25,7 +30,17 @@ Read an identity file from \fIINPUT\fR or from standard input and output the cor \fB\-\-version\fR Print the version and exit\. .SH "EXAMPLES" -Generate a new identity: +Generate a new post\-quantum identity: +.IP "" 4 +.nf +$ age\-keygen \-pq +# created: 2025\-11\-17T13:39:06+01:00 +# public key: age1pq167[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] +AGE\-SECRET\-KEY\-PQ\-1K30MYPZAHAXHR22YHH27EGDVLU0QNSUH3DSV7J7NR3X6D9LHXNWSDLTV4T +.fi +.IP "" 0 +.P +Generate a new traditional identity: .IP "" 4 .nf $ age\-keygen @@ -35,11 +50,11 @@ AGE\-SECRET\-KEY\-1N9JEPW6DWJ0ZQUDX63F5A03GX8QUW7PXDE39N8UYF82VZ9PC8UFS3M7XA9 .fi .IP "" 0 .P -Write a new identity to \fBkey\.txt\fR: +Write a new post\-quantum identity to \fBkey\.txt\fR: .IP "" 4 .nf $ age\-keygen \-o key\.txt -Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p +Public key: age1pq1cd[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] .fi .IP "" 0 .P @@ -47,7 +62,7 @@ Convert an identity to a recipient: .IP "" 4 .nf $ age\-keygen \-y key\.txt -age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p +age1pq1cd[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] .fi .IP "" 0 .SH "SEE ALSO" diff --git a/doc/age-keygen.1.html b/doc/age-keygen.1.html index c05c175..eaf5e39 100644 --- a/doc/age-keygen.1.html +++ b/doc/age-keygen.1.html @@ -76,7 +76,7 @@

SYNOPSIS

-

age-keygen [-o OUTPUT]
+

age-keygen [-pq] [-o OUTPUT]
age-keygen -y [-o OUTPUT] [INPUT]

DESCRIPTION

@@ -91,6 +91,11 @@ standard error.

OPTIONS

+
-pq
+
Generate a post-quantum hybrid ML-KEM-768 + X25519 key pair. + +

In the future, this might become the default.

+
-o, --output=OUTPUT
@@ -107,7 +112,15 @@ standard error.

EXAMPLES

-

Generate a new identity:

+

Generate a new post-quantum identity:

+ +
$ age-keygen -pq
+# created: 2025-11-17T13:39:06+01:00
+# public key: age1pq167[... 1950 more characters ...]
+AGE-SECRET-KEY-PQ-1K30MYPZAHAXHR22YHH27EGDVLU0QNSUH3DSV7J7NR3X6D9LHXNWSDLTV4T
+
+ +

Generate a new traditional identity:

$ age-keygen
 # created: 2021-01-02T15:30:45+01:00
@@ -115,16 +128,16 @@ standard error.

AGE-SECRET-KEY-1N9JEPW6DWJ0ZQUDX63F5A03GX8QUW7PXDE39N8UYF82VZ9PC8UFS3M7XA9
-

Write a new identity to key.txt:

+

Write a new post-quantum identity to key.txt:

$ age-keygen -o key.txt
-Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
+Public key: age1pq1cd[... 1950 more characters ...]
 

Convert an identity to a recipient:

$ age-keygen -y key.txt
-age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
+age1pq1cd[... 1950 more characters ...]
 

SEE ALSO

@@ -137,7 +150,7 @@ age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
  1. -
  2. June 2024
  3. +
  4. December 2025
  5. age-keygen(1)
diff --git a/doc/age.1 b/doc/age.1 index 6a3f3ea..d77fc31 100644 --- a/doc/age.1 +++ b/doc/age.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.9.1 .\" http://github.com/apjanke/ronn-ng/tree/0.9.1 -.TH "AGE" "1" "June 2024" "" +.TH "AGE" "1" "December 2025" "" .SH "NAME" \fBage\fR \- simple, modern, and secure file encryption .SH "SYNOPSIS" @@ -99,23 +99,39 @@ Decrypt using the data\-less \fIplugin\fR \fIPLUGIN\fR\. This is equivalent to using \fB\-i\fR/\fB\-\-identity\fR with a file that contains a single plugin \fBIDENTITY\fR that encodes no plugin\-specific data\. .SH "RECIPIENTS AND IDENTITIES" \fBRECIPIENTS\fR are public values, like a public key, that a file can be encrypted to\. \fBIDENTITIES\fR are private values, like a private key, that allow decrypting a file encrypted to the corresponding \fBRECIPIENT\fR\. -.SS "Native X25519 keys" -Native \fBage\fR key pairs are generated with age\-keygen(1), and provide small encodings and strong encryption based on X25519\. They are the recommended recipient type for most applications\. +.SS "Native keys" +Native \fBage\fR key pairs are generated with age\-keygen(1), and provide small encodings and strong encryption based on X25519 for classic keys, and X25519 + ML\-KEM\-768 for post\-quantum hybrid keys\. The post\-quantum hybrid keys are secure against future quantum computers and are the recommended recipient type for most applications\. .P -A \fBRECIPIENT\fR encoding begins with \fBage1\fR and looks like the following: +A hybrid \fBRECIPIENT\fR encoding begins with \fBage1pq1\fR and looks like the following: +.IP "" 4 +.nf +age1pq167[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] +.fi +.IP "" 0 +.P +A hybrid \fBIDENTITY\fR encoding begins with \fBAGE\-SECRET\-KEY\-PQ\-1\fR and looks like the following: +.IP "" 4 +.nf +AGE\-SECRET\-KEY\-PQ\-1K30MYPZAHAXHR22YHH27EGDVLU0QNSUH3DSV7J7NR3X6D9LHXNWSDLTV4T +.fi +.IP "" 0 +.P +A classic \fBRECIPIENT\fR encoding begins with \fBage1\fR and looks like the following: .IP "" 4 .nf age1gde3ncmahlqd9gg50tanl99r960llztrhfapnmx853s4tjum03uqfssgdh .fi .IP "" 0 .P -An \fBIDENTITY\fR encoding begins with \fBAGE\-SECRET\-KEY\-1\fR and looks like the following: +A classic \fBIDENTITY\fR encoding begins with \fBAGE\-SECRET\-KEY\-1\fR and looks like the following: .IP "" 4 .nf AGE\-SECRET\-KEY\-1KTYK6RVLN5TAPE7VF6FQQSKZ9HWWCDSKUGXXNUQDWZ7XXT5YK5LSF3UTKQ .fi .IP "" 0 .P +A file can't be encrypted to both post\-quantum and classic keys, as that would defeat the post\-quantum security of the encryption\. +.P An encrypted file can't be linked to the native recipient it's encrypted to without access to the corresponding identity\. .SS "SSH keys" As a convenience feature, \fBage\fR also supports encrypting to RSA or Ed25519 ssh(1) keys\. RSA keys must be at least 2048 bits\. This feature employs more complex cryptography, and should only be used when a native key is not available for the recipient\. Note that SSH keys might not be protected long\-term by the recipient, since they are revokable when used only for authentication\. @@ -147,6 +163,12 @@ Plugins can be freely mixed with other plugins or natively supported keys\. A plugin is not bound to only encrypt or decrypt files meant for or generated by the plugin\. For example, a plugin can be used to decrypt files encrypted to a native X25519 \fBRECIPIENT\fR or even with a passphrase\. Similarly, a plugin can encrypt a file such that it can be decrypted without the use of any plugin\. .P Plugins for which the \fBIDENTITY\fR/\fBRECIPIENT\fR distinction doesn't make sense (such as a symmetric encryption plugin) may generate only an \fBIDENTITY\fR and instruct the user to perform encryption with the \fB\-e\fR/\fB\-\-encrypt\fR and \fB\-i\fR/\fB\-\-identity\fR flags\. Plugins for which the concept of separate identities doesn't make sense (such as a password\-encryption plugin) may instruct the user to use the \fB\-j\fR flag\. +.P +\fBage\fR can natively encrypt to recipients starting with \fBage1tag1\fR (using P\-256 ECDH) or \fBage1tagpq1\fR (using the ML\-KEM\-768 + P\-256 post\-quantum hybrid)\. These are intended to be the public side of private keys held in hardware\. +.P +They are directly supported to avoid the need to install the plugin, which may be platform\-specific, on the encrypting side\. +.P +The tag reduces privacy, by allowing an observer to correlate files with a recipient (but not files amongst them without knowledge of the recipient), but this is also a desirable property for hardware keys that require user interaction for each decryption operation\. .SH "EXIT STATUS" \fBage\fR will exit 0 if and only if encryption or decryption are successful for the full length of the input\. .P @@ -156,13 +178,13 @@ Files encrypted with a stable version (not alpha, beta, or release candidate) of .P If decrypting older files poses a security risk, doing so might cause an error by default\. In this case, a flag will be provided to force the operation\. .SH "EXAMPLES" -Generate a new identity, encrypt data, and decrypt: +Generate a new post\-quantum identity, encrypt data, and decrypt: .IP "" 4 .nf -$ age\-keygen \-o key\.txt -Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p +$ age\-keygen \-pq \-o key\.txt +Public key: age1pq167[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] -$ tar cvz ~/data | age \-r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p > data\.tar\.gz\.age +$ tar cvz ~/data | age \-r age1pq167[\|\.\|\.\|\.] > data\.tar\.gz\.age $ age \-d \-o data\.tar\.gz \-i key\.txt data\.tar\.gz\.age .fi @@ -171,8 +193,7 @@ $ age \-d \-o data\.tar\.gz \-i key\.txt data\.tar\.gz\.age Encrypt \fBexample\.jpg\fR to multiple recipients and output to \fBexample\.jpg\.age\fR: .IP "" 4 .nf -$ age \-o example\.jpg\.age \-r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \e - \-r age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg example\.jpg +$ age \-o example\.jpg\.age \-r age1pq167[\|\.\|\.\|\.] \-r age1pq1e3[\|\.\|\.\|\.] example\.jpg .fi .IP "" 0 .P @@ -181,9 +202,9 @@ Encrypt to a list of recipients: .nf $ cat > recipients\.txt # Alice -age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p +age1pq167[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] # Bob -age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg +age1pq1e3[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.] $ age \-R recipients\.txt example\.jpg > example\.jpg\.age .fi diff --git a/doc/age.1.html b/doc/age.1.html index 20c62ce..eff3fc2 100644 --- a/doc/age.1.html +++ b/doc/age.1.html @@ -253,23 +253,39 @@ overhead per recipient, plus 16 bytes every 64KiB of plaintext.

to. IDENTITIES are private values, like a private key, that allow decrypting a file encrypted to the corresponding RECIPIENT.

-

Native X25519 keys

+

Native keys

Native age key pairs are generated with age-keygen(1), and provide small -encodings and strong encryption based on X25519. They are the recommended -recipient type for most applications.

+encodings and strong encryption based on X25519 for classic keys, and X25519 + +ML-KEM-768 for post-quantum hybrid keys. The post-quantum hybrid keys are secure +against future quantum computers and are the recommended recipient type for most +applications.

-

A RECIPIENT encoding begins with age1 and looks like the following:

+

A hybrid RECIPIENT encoding begins with age1pq1 and looks like the following:

+ +
age1pq167[... 1950 more characters ...]
+
+ +

A hybrid IDENTITY encoding begins with AGE-SECRET-KEY-PQ-1 and looks like +the following:

+ +
AGE-SECRET-KEY-PQ-1K30MYPZAHAXHR22YHH27EGDVLU0QNSUH3DSV7J7NR3X6D9LHXNWSDLTV4T
+
+ +

A classic RECIPIENT encoding begins with age1 and looks like the following:

age1gde3ncmahlqd9gg50tanl99r960llztrhfapnmx853s4tjum03uqfssgdh
 
-

An IDENTITY encoding begins with AGE-SECRET-KEY-1 and looks like the +

A classic IDENTITY encoding begins with AGE-SECRET-KEY-1 and looks like the following:

AGE-SECRET-KEY-1KTYK6RVLN5TAPE7VF6FQQSKZ9HWWCDSKUGXXNUQDWZ7XXT5YK5LSF3UTKQ
 
+

A file can't be encrypted to both post-quantum and classic keys, as that would +defeat the post-quantum security of the encryption.

+

An encrypted file can't be linked to the native recipient it's encrypted to without access to the corresponding identity.

@@ -331,6 +347,20 @@ instruct the user to perform encryption with the -e/--encrypt doesn't make sense (such as a password-encryption plugin) may instruct the user to use the -j flag.

+

Tagged recipients

+ +

age can natively encrypt to recipients starting with age1tag1 (using P-256 +ECDH) or age1tagpq1 (using the ML-KEM-768 + P-256 post-quantum hybrid). These +are intended to be the public side of private keys held in hardware.

+ +

They are directly supported to avoid the need to install the plugin, which may +be platform-specific, on the encrypting side.

+ +

The tag reduces privacy, by allowing an observer to correlate files with a +recipient (but not files amongst them without knowledge of the recipient), +but this is also a desirable property for hardware keys that require user +interaction for each decryption operation.

+

EXIT STATUS

age will exit 0 if and only if encryption or decryption are successful for the @@ -351,29 +381,28 @@ by default. In this case, a flag will be provided to force the operation.

EXAMPLES

-

Generate a new identity, encrypt data, and decrypt:

+

Generate a new post-quantum identity, encrypt data, and decrypt:

-
$ age-keygen -o key.txt
-Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
+
$ age-keygen -pq -o key.txt
+Public key: age1pq167[... 1950 more characters ...]
 
-$ tar cvz ~/data | age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p > data.tar.gz.age
+$ tar cvz ~/data | age -r age1pq167[...] > data.tar.gz.age
 
 $ age -d -o data.tar.gz -i key.txt data.tar.gz.age
 

Encrypt example.jpg to multiple recipients and output to example.jpg.age:

-
$ age -o example.jpg.age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
-    -r age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg example.jpg
+
$ age -o example.jpg.age -r age1pq167[...] -r age1pq1e3[...] example.jpg
 

Encrypt to a list of recipients:

$ cat > recipients.txt
 # Alice
-age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
+age1pq167[... 1950 more characters ...]
 # Bob
-age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg
+age1pq1e3[... 1950 more characters ...]
 
 $ age -R recipients.txt example.jpg > example.jpg.age
 
@@ -432,7 +461,7 @@ $ age -d -i age-yubikey-identity-388178f3.txt secrets.txt.age
  1. -
  2. June 2024
  3. +
  4. December 2025
  5. age(1)