solokeys / solo1

Solo 1 firmware in C
https://solokeys.com/
Other
2.31k stars 274 forks source link

Vendor command for signing SHA256 hash #395

Open rgerganov opened 4 years ago

rgerganov commented 4 years ago

I wonder what others think about having a vendor command for signing an arbitrary SHA256 hash. The use case for this would be using a Solo key for file signing. The hash of the file will be computed on the host and then it will be passed to the key for signing. This is how it would look like from user perspective:

# generate a new key pair, the output is cred_id and public.pem
$ solo key make-credential

# sign "file.dat" and store the signature in "file.dat.sig"
$ solo key sign cred_id -in file.dat -out file.dat.sig

# verify the signature with openssl
$ openssl dgst -verify public.pem -keyform pem -sha256 -signature file.dat.sig file.dat

We cannot do that with the standard command for getting assertion but we can easily implement a new custom command. Thoughts?

nickray commented 4 years ago

I like it! I made an experiment in this direction a long time ago (see CTAPHID_PROBE command, we'd want to pick a different one).

Perhaps you can open an "RFC issue" with a sketch of a plan? E.g., we'd definitely need to follow analogous "PIN rules" as elsewhere.

Additional input: I'm a big fan of OpenBSD's signify, the ultimate ideal for me would be to support being a backend for that. Directly doing so would lead to supporting Ed25519 though (for which we have https://github.com/ycrypto/salty/blob/main/c-api/salty.h, but there are complications surrounding multiple key types as raised elsewhere). So I think it would be fine to start with just P256 signatures.

(Just a nit, I'd ask that solo CLI tool use "normal" argument/option syntax, not copy openssl's weirdness).

rgerganov commented 4 years ago

I like it! I made an experiment in this direction a long time ago (see CTAPHID_PROBE command, we'd want to pick a different one).

Interesting. I see that you choose to implement a new CTAPHID command. I was thinking of using CTAPHID_CBOR with a new vendor command. Not sure what are the pros and cons.

Perhaps you can open an "RFC issue" with a sketch of a plan? E.g., we'd definitely need to follow analogous "PIN rules" as elsewhere.

I could do that but I prefer to create a PoC first.

Additional input: I'm a big fan of OpenBSD's signify, the ultimate ideal for me would be to support being a backend for that. Directly doing so would lead to supporting Ed25519 though (for which we have https://github.com/ycrypto/salty/blob/main/c-api/salty.h, but there are complications surrounding multiple key types as raised elsewhere). So I think it would be fine to start with just P256 signatures.

Yeah, P256 is the low-hanging fruit here but I am also interested into Ed25519

nickray commented 4 years ago

Regarding CTAPHID vs. CTAPHID_CBOR vendor command: I think I was just using the easiest way I saw back then (with little understanding). Probably if you are doing something that expects a CBOR map of arguments, it makes most sense to do it with CTAPHID_CBOR (and re-use the infrastructure).

rgerganov commented 4 years ago

I have the first PoC ready. You need to patch both solo and solo-python if you want to give it a try. I am also using the fido2-cred tool from libfido2. This is how it works:

# Create a new credential and save the id and the public key  of the credential in "cred"
$ echo credential challenge | openssl sha256 -binary | base64 > cred_param
$ echo relying party >> cred_param
$ echo user name >> cred_param
$ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param
$ fido2-cred -M -i cred_param /dev/hidraw6 | fido2-cred -V -o cred
$ cat cred
8BNpSl5onmiOYJNb68ZroWJtJvveCLXyC7l/gVFG0uF/kq6wOISXyMPTdcFX7nIGmKx4eL6HCtjxqpk3L6xdtFtUGgAAAA==
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2T3KDkdhtOqVODP+4YH5k/yMzeAq
atKglLqflwzZTdHBvs6S1V9qsTC1l65DJCPZIn8MQYgsVvgwbalcgRp5Cw==
-----END PUBLIC KEY-----

# extract the public key into public.pem
$ tail -4 cred > public.pem

# generate a random file for signing
$ head -c 1M < /dev/urandom > file.dat

# sign the file with Solo
$ solo key sign-file 8BNpSl5onmiOYJNb68ZroWJtJvveCLXyC7l/gVFG0uF/kq6wOISXyMPTdcFX7nIGmKx4eL6HCtjxqpk3L6xdtFtUGgAAAA== file.dat
810743111f7f70cb64b5ef07b4930c2d2b298de743286609905b6f7873738a76  file.dat
Please press the button on your Solo key
Saving signature to file.dat.sig

# verify the signature with openssl
$ openssl dgst -verify public.pem -sha256 -signature file.dat.sig file.dat
Verified OK
conorpp commented 4 years ago

I think this would be okay but I think it would have to enforce pinAuth if a PIN is set, otherwise this could be used to bypass PIN restrictions on normal FIDO2 transactions.

rgerganov commented 4 years ago

Correct, I have added support for pinAuth in the last version of the PR. The solo key sign-file also accepts --pin now.

My1 commented 4 years ago

The solo key sign-file also accepts --pin now.

btw might it not be nicer to have a hidden live prompt for the pin instead of giving it in the command itself (especially as most linux things I used so far keep a log of used commands which may end a bit well fun)

rgerganov commented 4 years ago

I have implemented PGP signing with Solo and now I can sign git commits with my Solo Hacker! :tada: You can find the project here: https://github.com/rgerganov/solo-pgp The last two commits are signed with Solo :)

@conorpp @nickray if you decide to go with this vendor command, I can work on adding the PGP stuff to solo-pyton. Even though PGP is a huge clusterfuck we can implement the git signing with ~200 lines of Python code as you can see from my project.

nickray commented 4 years ago

You're awesome! Will dig in soon.

My1 commented 4 years ago

totally sounds fun

nickray commented 4 years ago

Had a good look now @rgerganov. This is exactly how I imagined this should work :)

If you have the time/energy, would be great to add your two scripts to solo-python.

Regarding API, I'd suggest the following:

My1 commented 4 years ago

also when running PGP why not also add something to decrypt as well? so you can have some fun with encrypted PGP mails and stuff

nickray commented 4 years ago

@My1, different topic. This is a vendor command to sign.

rgerganov commented 4 years ago

Had a good look now @rgerganov. This is exactly how I imagined this should work :)

If you have the time/energy, would be great to add your two scripts to solo-python.

Sure, will start working on this soon.

BrunoP-dev commented 3 years ago

Hey 1) is their a support for that product or a forum? if not can we create one? 2) here my experimentation with that sign-file feature. Anything wrong ? thanks log.log

stevenwdv commented 3 years ago

This was referred to in #575 and I noticed it is not merged yet and hasn't seen much activity lately. Are the reasons for this similar to those mentioned in #575 (e.g. reusing authentication keys for signing etc.)?