Skip to content
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

Expose Go library functions (please review the API!) #63

Closed
schollz opened this issue Dec 31, 2019 · 27 comments
Closed

Expose Go library functions (please review the API!) #63

schollz opened this issue Dec 31, 2019 · 27 comments
Labels

Comments

@schollz
Copy link

schollz commented Dec 31, 2019

What were you trying to do

Use age encryption in a Go program by importing it.

What happened

Because age uses internal it prevents importing. I suspect this was on purpose, and that's okay, but just wanted to check if this was sought a possibility for this spec.

@ovalseven8
Copy link

According to the age documentation it's intended to be a library:

This is a design for a simple file encryption CLI tool, Go library, and format.

@xt0fer
Copy link

xt0fer commented Dec 31, 2019

perhaps we're just getting caught by the 1.4/1.5 design stricture? If internal was renamed to library or impl would that change the intention of the project?

@schollz
Copy link
Author

schollz commented Dec 31, 2019

@ovalseven8 That's great! I should have been more specific - I'm actually wondering if this implementation (filippo.io/age) is meant to serve as the Go library.

@schollz
Copy link
Author

schollz commented Dec 31, 2019

@xt0fer exactly, any name change would allow it to be used as a library. However it was probably purposely done to be internal, just wanted to double check

@abarisani
Copy link

I'd welcome this for attempting to compile this under TamaGo (https://github.com/inversepath/tamago).

@schollz
Copy link
Author

schollz commented Jan 8, 2020

I made this for now: https://github.com/schollz/age/ but I'd rather not have to merge upstream to keep it up to date, so it would be nice if this repo is the library.

@FiloSottile, do you plan on having this repo be used as a library?

@sashabaranov
Copy link

Exposing age as a library would very much benefit building mobile apps with good encryption through gomobile!

@richo
Copy link

richo commented Apr 28, 2020

Is there any word on this? I'd love to avoid shelling out to age if I can avoid it.

@cyb3rz3us
Copy link

cyb3rz3us commented Apr 28, 2020

Apologies in advance for not fully understanding the ask here but since 'age' is using the Go crypto library, why would someone then want to have 'age' be a crypto library for use in a Go program?

I guess I would think one would just use the same libs that 'age' uses for their Go program...please help me see what I am missing...

@hairyhenderson
Copy link

@cyb3rz3us it's not "just" using the Go crypto package... it's also implementing a specific format.

The simplest (and probably most naïve) solution to this issue would be to expose all the packages that are currently in https://github.com/FiloSottile/age/tree/master/internal; but I don't think @FiloSottile really wants to do that 😉...

@dncohen
Copy link

dncohen commented May 1, 2020

Count me in as wanting this all this age goodness as an importable package.

I think internal/age is the only one that needs moving out of the internal/ directory. That's what PR #119 does.

@stchris
Copy link
Contributor

stchris commented May 18, 2020

FYI https://twitter.com/FiloSottile/status/1262279790377291776?s=20

@FiloSottile
Copy link
Owner

Hey folks, sorry for taking so long, I am indeed preparing to expose an API and would love some feedback on the current plan which is to expose the age, agessh, and armor packages!

(Sorry for not just taking #120, but you won't be surprised to learn I have strong opinions on APIs :))

@FiloSottile FiloSottile changed the title UX: Use a Go library? Expose Go library functions May 18, 2020
@FiloSottile FiloSottile changed the title Expose Go library functions Expose Go library functions (please review the API!) May 18, 2020
@FiloSottile FiloSottile pinned this issue May 18, 2020
@dominikschulz
Copy link

Thanks for the initial API draft. It's a nice and clean API that seems to provide anything that gopass needs.

Some questions:

  • What about EncryptedSSHIdentity for encrypted SSH private keys? This would need to be handled by the caller?
  • Any thoughts about Agent support, e.g. yubikey-agent?
  • What about the hard coded recipient limit (20)? Any chance of raising / exposing this?

@FiloSottile
Copy link
Owner

FiloSottile commented May 19, 2020

Thank you for the feedback, all very useful!

  • What about EncryptedSSHIdentity for encrypted SSH private keys? This would need to be handled by the caller?

It's specifically for decryption deferral, if you are sure you need to decrypt it you can just use the x/crypto/ssh functions to do so. But I guess it is general enough to be useful, so I moved it to agessh, thanks for the suggestion.

@str4d and I worked on a plugin support which should make it possible to implement an agent as a plugin.

  • What about the hard coded recipient limit (20)? Any chance of raising / exposing this?

Hmm, yeah, this is a great example of something that would be nice to configure. The current API allows neither returning information about the file nor passing options.

kula added a commit to kula/age-pkcs11 that referenced this issue Jun 15, 2020
age uses a modification on bech32, and age isn't yet something
that can be imported - see
FiloSottile/age#63

For proof of concept, simply copy the code. License and copyright
as it appears in bech32/bech32.go still applies.
@FiloSottile
Copy link
Owner

FiloSottile commented Jun 28, 2020

It's out! There is now a Go API for age!

https://pkg.go.dev/filippo.io/age@v1.0.0-beta4
https://pkg.go.dev/filippo.io/age@v1.0.0-beta4/agessh
https://pkg.go.dev/filippo.io/age@v1.0.0-beta4/armor

Still in beta so we can fix it if we realize I made some horrible mistake (let me know!) but otherwise I expect it to be pretty stable (and probably to grow an EncryptWithOptions later).

@lucor
Copy link
Contributor

lucor commented Jul 4, 2020

Thanks for the tool and the API nice and clean!

Just a question, any thoughts about to expose in some way the generation of a X25519Identity using a seed (i.e. exposing the newX25519IdentityFromScalar) ?

@FiloSottile
Copy link
Owner

Just a question, any thoughts about to expose in some way the generation of a X25519Identity using a seed (i.e. exposing the newX25519IdentityFromScalar) ?

It used to be exposed but I realized it was probably more of a footgun than useful. What's your use case?

@lucor
Copy link
Contributor

lucor commented Jul 4, 2020

The use case is to encrypt a file using an existing private key derived from a user's password with scrypt.

@FiloSottile
Copy link
Owner

FiloSottile commented Jul 4, 2020 via email

@lucor
Copy link
Contributor

lucor commented Jul 4, 2020

Apologies, I'd have shared more details about the use case.
I'm experimenting with the idea of password manager 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.
I know it is an edge case and probably itself could not justify the addition of the new public method :-)

@FiloSottile
Copy link
Owner

FiloSottile commented Jul 4, 2020

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.

That sounds like it doesn't need a public key, so maybe you can use the ScryptIdentity / ScryptRecipient?

@lucor
Copy link
Contributor

lucor commented Jul 5, 2020

Indeed, this was my first try too. In this case I'm able to encrypt but still need to generate another private key with scrypt to generate the services' password :(. But this is something related to my project's UX not to age.

Right now I'm using with success agessh as below:

// error handling omitted for brevity
key, _ := scrypt.Key([]byte(password), salt, 1<<16, 8, 1, 32)
ed25519Key := ed25519.NewKeyFromSeed(key)
ageIdentity, _ := agessh.NewEd25519Identity(ed25519Key)
servicePassword, _ := fn(key, serviceInfo)

@FiloSottile
Copy link
Owner

still need to generate another private key with scrypt to generate the services' password

I don't really understand how this is not compatible with ScryptIdentity / ScryptRecipient, you can use the same passphrase, as the salts will be different.

(This is probably a better fit for the mailing list than the issue tracker.)

@lucor
Copy link
Contributor

lucor commented Jul 5, 2020

Agreed. Moved the discussion to the mailing list. Thanks @FiloSottile

@FiloSottile
Copy link
Owner

The API has now been around for a bit, closing this issue!

@FiloSottile FiloSottile unpinned this issue Jan 3, 2021
@littlecxm
Copy link

age/scrypt.go

Line 38 in 2e09054

func NewScryptRecipient(password string) (*ScryptRecipient, error) {

use []byte to replace exists arg password string should be better?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.