unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / Atom feed
* Using G-Expressions for public keys (substitutes and possibly more)
@ 2021-10-17 12:47 Liliana Marie Prikler
  2021-10-21 20:13 ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Liliana Marie Prikler @ 2021-10-17 12:47 UTC (permalink / raw)
  To: guix-devel

Hi Guix,

let's say I wanted to add my own substitute server to my config.scm. 
At the time of writing, I would have to add said server's public key to
the authorized-keys of my guix-configuration like so:
  (cons* (local-file "my-key.pub") %default-authorized-guix-keys)
or similarily with append.  This local-file incantation is however
pretty weak.  It changes based on the current working directory and
even if I were to use an absolute path, I'd have to copy both that file
and the config.scm to a new machine were I to use the same
configuration there as well.

However, it turns out that the format for said key files is some
actually pretty readable Lisp-esque stuff.  For instance, an ECC key
reads like
  (public-key (ecc (curve CURVE) (q #Q#)))
with spaces omitted for simplicity.
Were it not for the (q #Q#) bit, we could construct it using scheme-
file.  In fact, it is so simple that in my local config I now do
exactly that.

(define-record-type* <ecc-key> ...)
(define-gexp-compiler (ecc-key-compiler (ecc-key <ecc-key>) ...) ...)

(ecc-key
  (name "my-key.pub")
  (curve 'Ed25519)
  (q "ABCDE..."))

Could/should we support such formats out of the box?  WDYT?

Regards,
Liliana



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-10-17 12:47 Using G-Expressions for public keys (substitutes and possibly more) Liliana Marie Prikler
@ 2021-10-21 20:13 ` Ludovic Courtès
  2021-10-22  4:47   ` Liliana Marie Prikler
  0 siblings, 1 reply; 9+ messages in thread
From: Ludovic Courtès @ 2021-10-21 20:13 UTC (permalink / raw)
  To: Liliana Marie Prikler; +Cc: guix-devel

Hi!

Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:

> let's say I wanted to add my own substitute server to my config.scm. 
> At the time of writing, I would have to add said server's public key to
> the authorized-keys of my guix-configuration like so:
>   (cons* (local-file "my-key.pub") %default-authorized-guix-keys)
> or similarily with append.  This local-file incantation is however
> pretty weak.  It changes based on the current working directory and
> even if I were to use an absolute path, I'd have to copy both that file
> and the config.scm to a new machine were I to use the same
> configuration there as well.

Note that you could use ‘plain-file’ instead of ‘local-file’ and inline
the key canonical sexp in there.

> However, it turns out that the format for said key files is some
> actually pretty readable Lisp-esque stuff.  For instance, an ECC key
> reads like
>   (public-key (ecc (curve CURVE) (q #Q#)))
> with spaces omitted for simplicity.
> Were it not for the (q #Q#) bit, we could construct it using scheme-
> file.  In fact, it is so simple that in my local config I now do
> exactly that.

Yeah it’s frustrating that canonical sexps are almost, but not quite,
Scheme sexps.  :-)

(gcrypt pk-crypto) has a ‘canonical-sexp->sexp’ procedure:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,use(gcrypt pk-crypto)
scheme@(guile-user)> ,use(rnrs io ports)
scheme@(guile-user)> (string->canonical-sexp
		      (call-with-input-file "etc/substitutes/ci.guix.info.pub"
			get-string-all))
$18 = #<canonical-sexp 7fce7f4e8b40 | 15d96a0>
scheme@(guile-user)> ,pp (canonical-sexp->sexp $18)
$19 = (public-key
  (ecc (curve Ed25519)
       (q #vu8(141 21 111 41 93 36 176 217 168 111 165 116 26 132 15 242 210 79 96 247 182 196 19 72 20 173 85 98 89 113 179 148))))
--8<---------------cut here---------------end--------------->8---

> (define-record-type* <ecc-key> ...)
> (define-gexp-compiler (ecc-key-compiler (ecc-key <ecc-key>) ...) ...)
>
> (ecc-key
>   (name "my-key.pub")
>   (curve 'Ed25519)
>   (q "ABCDE..."))
>
> Could/should we support such formats out of the box?  WDYT?

With this approach, we’d end up mirroring all the canonical sexps used
by libgcrypt, which doesn’t sound great from a maintenance POV.

Would providing an example in the doc that uses ‘canonical-sexp->sexp’
and its dual help?

Thanks,
Ludo’.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-10-21 20:13 ` Ludovic Courtès
@ 2021-10-22  4:47   ` Liliana Marie Prikler
  2021-11-21  0:12     ` Jelle Licht
  0 siblings, 1 reply; 9+ messages in thread
From: Liliana Marie Prikler @ 2021-10-22  4:47 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guix-devel

Hi Ludo,

Am Donnerstag, den 21.10.2021, 22:13 +0200 schrieb Ludovic Courtès:
> Hi!
> 
> Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:
> 
> > let's say I wanted to add my own substitute server to my
> > config.scm. 
> > At the time of writing, I would have to add said server's public
> > key to
> > the authorized-keys of my guix-configuration like so:
> >   (cons* (local-file "my-key.pub") %default-authorized-guix-keys)
> > or similarily with append.  This local-file incantation is however
> > pretty weak.  It changes based on the current working directory and
> > even if I were to use an absolute path, I'd have to copy both that
> > file
> > and the config.scm to a new machine were I to use the same
> > configuration there as well.
> 
> Note that you could use ‘plain-file’ instead of ‘local-file’ and
> inline the key canonical sexp in there.
Yes, but for that I'd have to either write a (multi-line) string
directly, which visibly "breaks" indentation of the rest of the file,
or somehow generate a string which adds at least one layer of
indentation.  The former is imo unacceptable, the latter merely
inconvenient.

> > However, it turns out that the format for said key files is some
> > actually pretty readable Lisp-esque stuff.  For instance, an ECC
> > key reads like
> >   (public-key (ecc (curve CURVE) (q #Q#)))
> > with spaces omitted for simplicity.
> > Were it not for the (q #Q#) bit, we could construct it using
> > scheme-file.  In fact, it is so simple that in my local config I
> > now do exactly that.
> 
> Yeah it’s frustrating that canonical sexps are almost, but not quite,
> Scheme sexps.  :-)
> 
> (gcrypt pk-crypto) has a ‘canonical-sexp->sexp’ procedure:
> 
> --8<---------------cut here---------------start------------->8---
> scheme@(guile-user)> ,use(gcrypt pk-crypto)
> scheme@(guile-user)> ,use(rnrs io ports)
> scheme@(guile-user)> (string->canonical-sexp
> 		      (call-with-input-file
> "etc/substitutes/ci.guix.info.pub"
> 			get-string-all))
> $18 = #<canonical-sexp 7fce7f4e8b40 | 15d96a0>
> scheme@(guile-user)> ,pp (canonical-sexp->sexp $18)
> $19 = (public-key
>   (ecc (curve Ed25519)
>        (q #vu8(141 21 111 41 93 36 176 217 168 111 165 116 26 132 15
> 242 210 79 96 247 182 196 19 72 20 173 85 98 89 113 179 148))))
> --8<---------------cut here---------------end--------------->8---
> 
> > (define-record-type* <ecc-key> ...)
> > (define-gexp-compiler (ecc-key-compiler (ecc-key <ecc-key>) ...)
> > ...)
> > 
> > (ecc-key
> >   (name "my-key.pub")
> >   (curve 'Ed25519)
> >   (q "ABCDE..."))
> > 
> > Could/should we support such formats out of the box?  WDYT?
> 
> With this approach, we’d end up mirroring all the canonical sexps
> used by libgcrypt, which doesn’t sound great from a maintenance POV.
Given that we can use canonical sexps, what about a single canonical-
sexp compiler then?  I'd have to think about this a bit more when I
have the time to, but having a way of writing the canonical sexp
"directly" would imo be advantageous.

> Would providing an example in the doc that uses ‘canonical-sexp-
> >sexp’ and its dual help?
I'm not sure whether it'd be in the doc or as a cookbook entry, but
providing an example would in my opinion definitely help.

I'll take a closer look at guile-gcrypt later.  Hopefully they have
scheme-ified constructors for everything, which would make this quite
simple.

Thanks,
Liliana



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-10-22  4:47   ` Liliana Marie Prikler
@ 2021-11-21  0:12     ` Jelle Licht
  2021-11-21  8:28       ` Liliana Marie Prikler
  0 siblings, 1 reply; 9+ messages in thread
From: Jelle Licht @ 2021-11-21  0:12 UTC (permalink / raw)
  To: Liliana Marie Prikler, Ludovic Courtès; +Cc: guix-devel

Hey folks,

Liliana Marie Prikler <liliana.prikler@gmail.com> writes:

> Hi Ludo,
>
> Am Donnerstag, den 21.10.2021, 22:13 +0200 schrieb Ludovic Courtès:
>> Hi!
>> 
>> Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:
>> 
>> > let's say I wanted to add my own substitute server to my
>> > config.scm. 
>> > At the time of writing, I would have to add said server's public
>> > key to
>> > the authorized-keys of my guix-configuration like so:
>> >   (cons* (local-file "my-key.pub") %default-authorized-guix-keys)
>> > or similarily with append.  This local-file incantation is however
>> > pretty weak.  It changes based on the current working directory and
>> > even if I were to use an absolute path, I'd have to copy both that
>> > file
>> > and the config.scm to a new machine were I to use the same
>> > configuration there as well.
>> 
>> Note that you could use ‘plain-file’ instead of ‘local-file’ and
>> inline the key canonical sexp in there.
> Yes, but for that I'd have to either write a (multi-line) string
> directly, which visibly "breaks" indentation of the rest of the file,
> or somehow generate a string which adds at least one layer of
> indentation.  The former is imo unacceptable, the latter merely
> inconvenient.

Would some arbitrary s-expression be a workable solution? See below for
an example for what I understood was your current use-case.

>> > However, it turns out that the format for said key files is some
>> > actually pretty readable Lisp-esque stuff.  For instance, an ECC
>> > key reads like
>> >   (public-key (ecc (curve CURVE) (q #Q#)))
>> > with spaces omitted for simplicity.
>> > Were it not for the (q #Q#) bit, we could construct it using
>> > scheme-file.  In fact, it is so simple that in my local config I
>> > now do exactly that.
>> 
>> Yeah it’s frustrating that canonical sexps are almost, but not quite,
>> Scheme sexps.  :-)
>> 
>> (gcrypt pk-crypto) has a ‘canonical-sexp->sexp’ procedure:
>> 
>> --8<---------------cut here---------------start------------->8---
>> scheme@(guile-user)> ,use(gcrypt pk-crypto)
>> scheme@(guile-user)> ,use(rnrs io ports)
>> scheme@(guile-user)> (string->canonical-sexp
>> 		      (call-with-input-file
>> "etc/substitutes/ci.guix.info.pub"
>> 			get-string-all))
>> $18 = #<canonical-sexp 7fce7f4e8b40 | 15d96a0>
>> scheme@(guile-user)> ,pp (canonical-sexp->sexp $18)
>> $19 = (public-key
>>   (ecc (curve Ed25519)
>>        (q #vu8(141 21 111 41 93 36 176 217 168 111 165 116 26 132 15
>> 242 210 79 96 247 182 196 19 72 20 173 85 98 89 113 179 148))))
>> --8<---------------cut here---------------end--------------->8---
>> 
>> > (define-record-type* <ecc-key> ...)
>> > (define-gexp-compiler (ecc-key-compiler (ecc-key <ecc-key>) ...)
>> > ...)
>> > 
>> > (ecc-key
>> >   (name "my-key.pub")
>> >   (curve 'Ed25519)
>> >   (q "ABCDE..."))
>> > 
>> > Could/should we support such formats out of the box?  WDYT?
>> 
>> With this approach, we’d end up mirroring all the canonical sexps
>> used by libgcrypt, which doesn’t sound great from a maintenance POV.
> Given that we can use canonical sexps, what about a single canonical-
> sexp compiler then?  I'd have to think about this a bit more when I
> have the time to, but having a way of writing the canonical sexp
> "directly" would imo be advantageous.

What about something such as the following?

--8<---------------cut here---------------start------------->8---
(use-modules (gcrypt base16)
             (gcrypt pk-crypto))

(define-record-type <canonical-sexp-wrapper>
  (canonical-sexp-wrapper name sexp)
  canonical-sexp-wrapper?
  (name canonical-sexp-wrapper-name)
  (sexp canonical-sexp-wrapper-sexp))

(define-gexp-compiler (canonical-sexp-wrapper-compiler
                       (wrapper <canonical-sexp-wrapper>) system target)
  (match wrapper
    (($ <canonical-sexp-wrapper> name sexp)
     (text-file name (canonical-sexp->string
                      (sexp->canonical-sexp sexp)) '()))))
--8<---------------cut here---------------end--------------->8---

This would still leave constructing your s-expression as an exercise to
the reader, which is definitely not amazing. In this specific instance,
I had to look at the output of canonical-sexp->sexp, which is of course
whatever the opposite of discoverable and good UX :).

For the Ed25519 key:
--8<---------------cut here---------------start------------->8---
(define my-public-key
  (canonical-sexp-wrapper
   "my-key.pub"
   `(public-key
     (ecc
      (curve Ed25519)
      (q ,(base16-string->bytevector
           (string-downcase
            "C9F307AE...")))))))
--8<---------------cut here---------------end--------------->8---

To improve on this, is one sexp-based-gexp-compiler + N helper functions
to construct the most-used value types a direction worth exploring?

 - Jelle


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-11-21  0:12     ` Jelle Licht
@ 2021-11-21  8:28       ` Liliana Marie Prikler
  2021-11-22 13:27         ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Liliana Marie Prikler @ 2021-11-21  8:28 UTC (permalink / raw)
  To: Jelle Licht, Ludovic Courtès; +Cc: guix-devel

Hi,

Am Sonntag, den 21.11.2021, 01:12 +0100 schrieb Jelle Licht:
> What about something such as the following?
> 
> --8<---------------cut here---------------start------------->8---
> (use-modules (gcrypt base16)
>              (gcrypt pk-crypto))
> 
> (define-record-type <canonical-sexp-wrapper>
>   (canonical-sexp-wrapper name sexp)
>   canonical-sexp-wrapper?
>   (name canonical-sexp-wrapper-name)
>   (sexp canonical-sexp-wrapper-sexp))
> 
> (define-gexp-compiler (canonical-sexp-wrapper-compiler
>                        (wrapper <canonical-sexp-wrapper>) system
> target)
>   (match wrapper
>     (($ <canonical-sexp-wrapper> name sexp)
>      (text-file name (canonical-sexp->string
>                       (sexp->canonical-sexp sexp)) '()))))
> --8<---------------cut here---------------end--------------->8---
> 
> This would still leave constructing your s-expression as an exercise
> to the reader, which is definitely not amazing. In this specific
> instance, I had to look at the output of canonical-sexp->sexp, which
> is of course whatever the opposite of discoverable and good UX :).
Apart from the name "-wrapper" instead of "-file", I think this would
be acceptable.  I think we ought to handle two cases here, though: one
with sexp being a sexp, and one with it being a canonical sexp.

> For the Ed25519 key:
> --8<---------------cut here---------------start------------->8---
> (define my-public-key
>   (canonical-sexp-wrapper
>    "my-key.pub"
>    `(public-key
>      (ecc
>       (curve Ed25519)
>       (q ,(base16-string->bytevector
>            (string-downcase
>             "C9F307AE...")))))))
> --8<---------------cut here---------------end--------------->8---
> 
> To improve on this, is one sexp-based-gexp-compiler + N helper
> functions to construct the most-used value types a direction worth
> exploring?
I think we would probably want to improve on this end in the guile-
gcrypt module, i.e. have a public-key "constructor" that returns a
canonical-sexp and so on.  WDYT?



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-11-21  8:28       ` Liliana Marie Prikler
@ 2021-11-22 13:27         ` Ludovic Courtès
  2021-11-22 14:32           ` Jelle Licht
  2021-11-22 19:35           ` Liliana Marie Prikler
  0 siblings, 2 replies; 9+ messages in thread
From: Ludovic Courtès @ 2021-11-22 13:27 UTC (permalink / raw)
  To: Liliana Marie Prikler; +Cc: guix-devel

Hi,

Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:

> I think we would probably want to improve on this end in the guile-
> gcrypt module, i.e. have a public-key "constructor" that returns a
> canonical-sexp and so on.  WDYT?

I don’t find it very compelling given there’s already
‘sexp->canonical-sexp’ & co.  WDYT?

Ludo’.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-11-22 13:27         ` Ludovic Courtès
@ 2021-11-22 14:32           ` Jelle Licht
  2021-11-22 19:35           ` Liliana Marie Prikler
  1 sibling, 0 replies; 9+ messages in thread
From: Jelle Licht @ 2021-11-22 14:32 UTC (permalink / raw)
  To: Ludovic Courtès, Liliana Marie Prikler; +Cc: guix-devel

Ludovic Courtès <ludo@gnu.org> writes:

> Hi,
>
> Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:
>
>> I think we would probably want to improve on this end in the guile-
>> gcrypt module, i.e. have a public-key "constructor" that returns a
>> canonical-sexp and so on.  WDYT?
>
> I don’t find it very compelling given there’s already
> ‘sexp->canonical-sexp’ & co.  WDYT?

Well, the issue here is 'knowing' what sexp to pass along to that
function in the first place. Are Liliana & I missing something
obvious here?

I had to take a string representation of a valid canonical-sexp, and
pass it through string->canonical-sexp and canonical-sexp->sexp. It's
definitely not an issue for managing my local configuration, but it
seems silly to force _anyone_ wanting to write a canonical-sexp as a
sexp through this REPL adventure, for each kind of canonical-sexp.

- Jelle


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-11-22 13:27         ` Ludovic Courtès
  2021-11-22 14:32           ` Jelle Licht
@ 2021-11-22 19:35           ` Liliana Marie Prikler
  2021-11-23 17:14             ` Ludovic Courtès
  1 sibling, 1 reply; 9+ messages in thread
From: Liliana Marie Prikler @ 2021-11-22 19:35 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guix-devel

Am Montag, den 22.11.2021, 14:27 +0100 schrieb Ludovic Courtès:
> Hi,
> 
> Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:
> 
> > I think we would probably want to improve on this end in the guile-
> > gcrypt module, i.e. have a public-key "constructor" that returns a
> > canonical-sexp and so on.  WDYT?
> 
> I don’t find it very compelling given there’s already
> ‘sexp->canonical-sexp’ & co.  WDYT?
sexp->canonical-sexp is from the comment surrounding it a rather hacky
beast.  I think (guile-)gcrypt could very well benefit from having a
better sexp construction API, but again that's outside the scope of
Guix.

But since you're asking, I do feel there's a lot guile-gcrypt could
borrow from Guix, just not right now in an efficient manner thanks to
needing to jump through the sexp->canonical-sexp hoops.  It could have
semantic constructors and field sanitization à la (guix records) for
example.  WDYT?



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Using G-Expressions for public keys (substitutes and possibly more)
  2021-11-22 19:35           ` Liliana Marie Prikler
@ 2021-11-23 17:14             ` Ludovic Courtès
  0 siblings, 0 replies; 9+ messages in thread
From: Ludovic Courtès @ 2021-11-23 17:14 UTC (permalink / raw)
  To: Liliana Marie Prikler; +Cc: guix-devel

Liliana Marie Prikler <liliana.prikler@gmail.com> skribis:

> Am Montag, den 22.11.2021, 14:27 +0100 schrieb Ludovic Courtès:

[...]

> sexp->canonical-sexp is from the comment surrounding it a rather hacky
> beast.  I think (guile-)gcrypt could very well benefit from having a
> better sexp construction API, but again that's outside the scope of
> Guix.
>
> But since you're asking, I do feel there's a lot guile-gcrypt could
> borrow from Guix, just not right now in an efficient manner thanks to
> needing to jump through the sexp->canonical-sexp hoops.  It could have
> semantic constructors and field sanitization à la (guix records) for
> example.  WDYT?

Fundamentally, Guile-Gcrypt is just bindings to libgcrypt.  As such, it
tries hard to remain close to libgcrypt’s API, and I think that’s a safe
approach for bindings in general.

Libgcrypt internally uses canonical sexps for key material,
configuration options, etc. (an illustration of Greenspun’s Tenth Rule
:-)), so that’s what Guile-Gcrypt exposes, and I think it’s fine.

Thanks,
Ludo’.


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-11-23 17:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-17 12:47 Using G-Expressions for public keys (substitutes and possibly more) Liliana Marie Prikler
2021-10-21 20:13 ` Ludovic Courtès
2021-10-22  4:47   ` Liliana Marie Prikler
2021-11-21  0:12     ` Jelle Licht
2021-11-21  8:28       ` Liliana Marie Prikler
2021-11-22 13:27         ` Ludovic Courtès
2021-11-22 14:32           ` Jelle Licht
2021-11-22 19:35           ` Liliana Marie Prikler
2021-11-23 17:14             ` Ludovic Courtès

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).