[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Using G-Expressions for public keys (substitutes and possibly more)
From: |
Jelle Licht |
Subject: |
Re: Using G-Expressions for public keys (substitutes and possibly more) |
Date: |
Sun, 21 Nov 2021 01:12:27 +0100 |
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
- Re: Using G-Expressions for public keys (substitutes and possibly more),
Jelle Licht <=