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

Key format description #1

Open
cyberphone opened this issue Nov 13, 2023 · 5 comments
Open

Key format description #1

cyberphone opened this issue Nov 13, 2023 · 5 comments

Comments

@cyberphone
Copy link

I can't find any description of the ECDSA key format used by the CLI.
It would be nice if there was a way to convert native keys to the format used by the CLI.

@cyberphone
Copy link
Author

I'm still confused :(
in https://github.com/BlockchainCommons/bc-envelope-cli-rust/blob/master/docs/BasicExamples.md I found
ALICE_PUBKEYS="ur:crypto-pubkeys/lftanshfhdcxrdhgfsfsfsosrloebgwmfrfhsnlskegsjydecawybniadyzovehncacnlbmdbesstansgrhdcxytgefrmnbzftltcmcnaspaimhftbjehlatjklkhktidrpmjobslewkfretcaetbnwksorlbd"

After byteWords decoding I got:
82d99c565820ba573d3d3da7b7a212eb3b3fcd837c4c74281dee0c6330fbe4601d237f9510c4d99c4b5820f94a3b8e153a87162309b16a56d66b5d07738c59d02aad700f8af43b381d380c

This in turn returned the following after CBOR decoding:
[40022(h'ba573d3d3da7b7a212eb3b3fcd837c4c74281dee0c6330fbe4601d237f9510c4'), 40011(h'f94a3b8e153a87162309b16a56d66b5d07738c59d02aad700f8af43b381d380c')]

These are two 32-byte arguments which would in JWK mean "x" and "y" but according to https://github.com/BlockchainCommons/bc-components-rust/blob/bd1a506a6cdeaea32bfb707e986e711b60316543/src/tags.rs#L74
denote a private and public key respectively.

@cyberphone
Copy link
Author

Continued...
in https://github.com/BlockchainCommons/bc-envelope-cli-rust/blob/master/docs/BasicExamples.md I found
ALICE_PRVKEYS="ur:crypto-prvkeys/gdlfwfdwlphlfsghcphfcsaybekkkbaejksfnynsct"

After CBOR encoding I get a 16-byte blob:
h'82f32c855d3d542256180810797e0073'

This is not a private key. Do you SHA256 it order to get a private key?

@wolfmcnally
Copy link
Collaborator

wolfmcnally commented Nov 20, 2023

First of all, recall that when CBOR is UR-encoded, the outermost tag is replaced by the UR type string, crypto-pubkeys. This operation is reversed when converting back to CBOR. In other words, you need to be able to look up the CBOR tag that corresponds to crypto-pubkeys. This is in the Rust code here.

So the fully-serialzed dCBOR is:

40017([40022(h'ba573d3d3da7b7a212eb3b3fcd837c4c74281dee0c6330fbe4601d237f9510c4'), 40011(h'f94a3b8e153a87162309b16a56d66b5d07738c59d02aad700f8af43b381d380c')])

So now you see that there are two internal tags: 40022 and 40011. Those correspond to signing-public-key and agreement-public-key. This is because secp256k1 uses different methods to derive a public key used for Schnorr signing and a public key used for x25519 key agreement (public key cryptography). It's generally useful to bundle them together, and that is why this structure has the name public key base, crypto-pubkeys (plural).

The crypto-prvkeys is "key material," and not a key in and of itself, and it has no maximum size, so you can use as much entropy as you want for your private keys. The example you have uses a 128-bit base, but you can see our main codebase generates 256-bit key bases.

So it is also called a "base" because it can be used to derive all sorts of other private keys including Bitcoin BIP-32 HD keys, and it has no size limitation so it can be as big as you want. 128 bits (16 bytes) is an absolute minimum.

The actual key generation algorithm has to take this variable length private key base and use it to generate a key of a fixed length. The standard method of deriving each of the various private key types (ECDSA, Schnorr, x25519) varies. For example, PrivateKeyBase has a method called signingPrivateKey that eventually ends up in the bc-crypto library calling hkdf_hmac_sha256, which is the actual algorithm used to stretch (or shrink) the key base to the correct size for this purpose. So you weren't too far off from suggesting we might use SHA-256, but the hkdf_hmac_sha256 algorithm is considered more robust for this purpose.

Since you can't move back from a public key to a private key, the public key base bundles both a signing and an agreement public key. But this isn't required for a private key base as you can generate literally anything from it.

@wolfmcnally wolfmcnally reopened this Nov 20, 2023
@cyberphone
Copy link
Author

I now understand how private keys are represented in the CLI.

What I don't understand is the example from your documentation:
ALICE_PUBKEYS="ur:crypto-pubkeys/lftanshfhdcxrdhgfsfsfsosrloebgwmfrfhsnlskegsjydecawybniadyzovehncacnlbmdbesstansgrhdcxytgefrmnbzftltcmcnaspaimhftbjehlatjklkhktidrpmjobslewkfretcaetbnwksorlbd"
It contains a public and a private key. This is not how public keys are provided in other systems using crypto.
What key algorithm(s) does it denote?

Since you build on hard-coded crypto, you should probably write a separate document about this to aid third party developers.

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

No branches or pull requests

2 participants