Expose the generation of a X25519Identity using a seed

73 views
Skip to first unread message

Luca Corbo

unread,
Jul 5, 2020, 3:02:29 PM7/5/20
to age-dev
Hi all,
this is a follow up of a discussion on github [1]

I'm experimenting with an idea of password manager (cli + GUI in Go) that allow to generate services' password using a pure function and (optionally) fallback to custom ones where this is not applicable (i.e. imported passwords).
Neither the user's password nor the private key are stored, but the last one is used to derive passwords and store some settings along with the custom passwords into an encrypted file.

The flow is basically:
1. generate private key (pk) from user passprhase with scrypt
2a. generate password for a service (i.e. website) using a fn(hkdf(pk, serviceInfo))
2b. allow user to specify a custom password (i.e. import)
3. store the info and the custom password into a file encrypted using age

The ways I figured out for point 3 are:
- use the user's passprhase or the derived pk as input for an age ScryptIdentity / ScryptRecipient.
This allow to correctly encrypt the file but from the project's UX point of view increase the execution time, we run scrypt twice.

- use the derived pk to generate an ed25519 key from seed and then the agessh Ed25519Identity / Ed25519Recipient
This allow to correctly encrypt the file and reduce the execution time, but make feel me like using age not in the correct way.

- use the derived as input for a age X2519Identity / X25519Recipient
This sounds like the perfect solution for the use case but at the moment is not possible to create X2519Identity using a seed.
Hence the question about the possibility to expose newX25519IdentityFromScalar :-)

I know this is an edge case and probably out of scope for the age's API design since it already allow to encrypt the file in 2 of the 3 points above, but I was thinking worth
to point out anyway ;-)


K. York

unread,
Jul 5, 2020, 4:12:00 PM7/5/20
to Luca Corbo, age-dev
I think that a password manager needs a special purpose crypto implementation, due to the model of many lifetime updates and indexed random access.

Simpler options: You could mirror the Unix `pass` utility's design if you leave the index unencrypted, or use different crypto for the password name -> filename mapping (exposes update time and size metadata). Access would be a straightforward single age scrypt.

--
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/7a536d8f-bbf0-444d-a736-7cafad742797o%40googlegroups.com.

Luca Corbo

unread,
Jul 16, 2020, 4:20:02 AM7/16/20
to age-dev
Thanks for the feedback.
Indeed it was inspired by the Unix `pass` design, with the difference that all the data will be encrypted using age into a vault file that contains the identity -> info mapping (metadata + password).
The project will be open source and I hope to publish an initial version soon.

Il giorno domenica 5 luglio 2020 22:12:00 UTC+2, K. York ha scritto:
I think that a password manager needs a special purpose crypto implementation, due to the model of many lifetime updates and indexed random access.

Simpler options: You could mirror the Unix `pass` utility's design if you leave the index unencrypted, or use different crypto for the password name -> filename mapping (exposes update time and size metadata). Access would be a straightforward single age scrypt.

On Sun, Jul 5, 2020, 12:02 PM Luca Corbo <lu....@gmail.com> wrote:
Hi all,
this is a follow up of a discussion on github [1]

I'm experimenting with an idea of password manager (cli + GUI in Go) that allow to generate services' password using a pure function and (optionally) fallback to custom ones where this is not applicable (i.e. imported passwords).
Neither the user's password nor the private key are stored, but the last one is used to derive passwords and store some settings along with the custom passwords into an encrypted file.

The flow is basically:
1. generate private key (pk) from user passprhase with scrypt
2a. generate password for a service (i.e. website) using a fn(hkdf(pk, serviceInfo))
2b. allow user to specify a custom password (i.e. import)
3. store the info and the custom password into a file encrypted using age

The ways I figured out for point 3 are:
- use the user's passprhase or the derived pk as input for an age ScryptIdentity / ScryptRecipient.
This allow to correctly encrypt the file but from the project's UX point of view increase the execution time, we run scrypt twice.

- use the derived pk to generate an ed25519 key from seed and then the agessh Ed25519Identity / Ed25519Recipient
This allow to correctly encrypt the file and reduce the execution time, but make feel me like using age not in the correct way.

- use the derived as input for a age X2519Identity / X25519Recipient
This sounds like the perfect solution for the use case but at the moment is not possible to create X2519Identity using a seed.
Hence the question about the possibility to expose newX25519IdentityFromScalar :-)

I know this is an edge case and probably out of scope for the age's API design since it already allow to encrypt the file in 2 of the 3 points above, but I was thinking worth
to point out anyway ;-)


--
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...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages