Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[spec] Per-recipient format is unspecified #9

Closed
str4d opened this issue Oct 9, 2019 · 6 comments
Closed

[spec] Per-recipient format is unspecified #9

str4d opened this issue Oct 9, 2019 · 6 comments

Comments

@str4d
Copy link

str4d commented Oct 9, 2019

The spec currently says:

Each recipient line starts with -> and its type name and can be followed by any number of arguments and additional lines. Unknown recipient types are ignored.

encode(data) is canonical base64url from RFC 4648 without padding, wrapped at 57 cols.

[...]

An X25519 recipient line is
-> X25519 encode(X25519(ephemeral secret, basepoint))
encode(encrypt[HKDF[salt, label](X25519(ephemeral secret, public key), 32)](file key))

This is insufficiently-specified, and does not indicate how arguments and additional lines should be parsed. In particular:

  • Should multi-space separators be allowed? (@FiloSottile has already said no)
  • For each recipient line type, which arguments should be space-separated and which should be newline-separated? The current Google Doc format in particular makes it very difficult to distinguish between the two.
  • How should cross-platform newlines be handled? (see also age fails to decrypt files generated in Windows PowerShell #2)
  • How should multiple arguments that require wrapping be handled? In particular, how should a parser distinguish a single wrapped argument, and two wrapped arguments where the first one's encoding is an integer multiple of 57 characters?
@FiloSottile
Copy link
Owner

Yeah, I realized line wrapping should not be defined in encode at all, but in the ssh-rsa definition, since it's the only multiline one.

@FiloSottile
Copy link
Owner

As a start, I moved the wrapping part to the ssh-rsa block, which should be a no-op.

@str4d
Copy link
Author

str4d commented Oct 9, 2019

Based on my current understanding of the format, I suggest something like the following:

The text header has the following format:

VERSION_STRING\n
RECIPIENT_LINE_1\n
[...]
RECIPIENT_LINE_N\n
--- MAC\n

All whitespace separators in the header are either a single space character or a single newline (\n) character.

Recipient lines within the header have the following format:

-> TYPE_NAME ARG_1 ARG_2 [...] ARG_J\nBODY

where BODY may have internal newline characters, but does not end in a newline character.

@str4d
Copy link
Author

str4d commented Dec 30, 2019

This issue needs to be resolved in order to clear up the definition of what a "recipient line" is, which constraints how implementations ignore unknown recipient types, and how future recipient lines are implemented.

@str4d
Copy link
Author

str4d commented Jan 5, 2020

In str4d/rage#52 I am parsing unknown recipient lines using the above format, with the additional constraints that BODY is only Base64-encoded data, and ARG_N may be either Base64-encoded data or a decimal integer.

@FiloSottile
Copy link
Owner

This is now fixed in the spec, I will make available some test cases of valid weird age files with arbitrary recipients or unknown versions.

The first line of the header is age-encryption.org/ followed by an arbitrary version string. Here and below, an arbitrary string is a sequence of ASCII characters with values 33 to 126. We describe version v1, other versions can change anything after the first line.

The rest of the header is a sequence of one or more recipient stanzas. Each recipient stanza starts with a line beginning with -> and its type name, followed by zero or more SP-separated arguments. The type name and the arguments are arbitrary strings. Unknown recipient types are ignored. The rest of the recipient stanza is a body of canonical base64 from RFC 4648 without padding wrapped at exactly 64 columns.

Repository owner locked and limited conversation to collaborators Apr 19, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants