Open hug-dev opened 3 years ago
@hug-dev Thank you for starting this investigation. 🎉 We're super excited about the integration and would love to help.
Inviting @SanjoDeundiak to this discussion so he can share his thoughts and feedback on your notes above.
Hey @hug-dev :wave:. It's nice to cooperate with Parsec! I'd like to mention that I can think of two ways of implementing Ockam Vault:
ec_diffie_hellman
is expected to perform raw Curve25519 Diffie-Hellman. We don't expect any additional key derivation here. The output Secret is expected to have Buffer type, and can be transformed to AES key using hkdf
sha256
is expected to compute sha256 using binaries, as for now, we don't use it for any sensitive information, only state hashes and public data. I think it's fine to implement it using software only.
hkdf_sha256
is expected to ikm (as Secret), salt (as Secret) and info (as binary) and compute hkdf_sha256. Function also takes an array of n SecretAttributes (with AES or Buffer types), so that function is expected to produce n Secrets that match input Attributes.
The expectation here is that compute_key_id_for_public_key
always produces the same key id for the same PublicKey, and get_secret_by_key_id
returns Secret value that always corresponds to the same secret, even if Vault instance is recreated. We implement key id as a sha256 of public key
Parsec only support persistent keys
Maybe it's possible to implement ephemeral key as a persistent key that is destroyed when Vault instance is destroyed?
the length of Parsec keys is in bits
I hope it's easy to transform depending on key type
SecretType::P256 should be the same as above but with the ECC family set to EccFamily::SecpR1 and bits to 256. To double-check between SecpR1 and SecpK1.
We currently do not use P256, and there is no plan to support it in the nearest feature.
SecretType::Bls: if this refer to that, I am not sure this is defined in the PSA Crypto API and hence we could not use it :(
Bls is not as widespread as Curve25519, I think that's fine (at least for the first implementation) to use ockam_vault crate for dealing with Bls secrets.
For signing with Curve25519 we use XEdDSA. There are other options for curve25519, as well as creating dedicated Ed25519 key, but at the moment we only support XEdDSA. We pass pre-hashed data here, but hashing is also a part of XEdDSA scheme. For other algorithms we probably need to create a convention.
Maybe it will be easier to start with Partial compatibility and then move towards Full compatibility. Cheers :thumbsup:
Hey @SanjoDeundiak ,
Thanks a lot for your reply and the detailed information here. Sorry for my lack of responses the past few weeks, I was on holidays 🌴
ec_diffie_hellman is expected to perform raw Curve25519 Diffie-Hellman. We don't expect any additional key derivation here. The output Secret is expected to have Buffer type, and can be transformed to AES key using hkdf
That works! The only catch here for Parsec is that the key agreement operation produces a raw shared secret which is returned to the client. The client would then have to import it again into the crypto hardware as raw data. Later on they can perform key derivation from it. That means that there would be a period of time where the raw secret is exposed out of the hardware which is not ideal. The secure way is to chain key agreement and derivation and then everything happens inside the hardware. In Ockam, do you use the raw secret for something else than key derivation afterwards?
Maybe it's possible to implement ephemeral key as a persistent key that is destroyed when Vault instance is destroyed?
Should be possible yes!
For signing with Curve25519 we use XEdDSA. There are other options for curve25519, as well as creating dedicated Ed25519 key, but at the moment we only support XEdDSA. We pass pre-hashed data here, but hashing is also a part of XEdDSA scheme. For other algorithms we probably need to create a convention.
There is no support currently in PSA Crypto for EdDSA or XedDSA 😢 In future versions there might be for EdDSA
.
Maybe it will be easier to start with Partial compatibility and then move towards Full compatibility.
I was also thinking that we could start from an exact copy of the software implementation of Ockam Vault and modify it piece by piece with Parsec. If that's possible that way we will keep full compatibility as we develop it and eventually replace everything by the Parsec implementation? With that as well we could include the vault in some existing integration testing and make sure that it keeps working when using Parsec instead.
@hug-dev
In Ockam, do you use the raw secret for something else than key derivation afterwards?
Kind of... We have X3DH implementation (which we don't use for now), in this case multiple dh outputs are first concatenated and then go to hkdf. In Noise XX (which we use for Secure Channels) dh output goes straight to HKDF as ikm.
I was also thinking that we could start from an exact copy of the software implementation of Ockam Vault and modify it piece by piece with Parsec. If that's possible that way we will keep full compatibility as we develop it and eventually replace everything by the Parsec implementation? With that as well we could include the vault in some existing integration testing and make sure that it keeps working when using Parsec instead.
Sounds great!
Parsec, and more specifically the Parsec Rust client, would be a good candidate for an Ockam Vault implementation. See this discussion for context.
This issue is about investigating what needs to be done to make it happen.
A
Vault
structure that uses theparsec-client
dependency would have to be created and that structure would have to implement theockam_vault_core
traits.Let's review them one per one (for the
0.20.0
version).AsymmetricVault
ec_diffie_hellman
: this seems to be thepsa_raw_key_agreement
function with theEcdh
algorithm. However, if the outputSecret
is meant to be used as key material stored securely, this is not enough (see this warning). Instead, we will have to chain a key agreement and a key derivation using the Parsec version of the PSA Crypto operationpsa_key_derivation_key_agreement
. This operation is a multi-part operation that has not yet been designed in Parsec.Hasher
sha256
is available aspsa_hash_compute
with theSha256
algorithm. Although since this operation should not be sensitive it could be implemented using a software library?hkdf_sha256
: The HKDF algorithm is part of the Parsec interface but as key derivation is a multi-step operation, it has not yet been designed in Parsec.Note to myself: if
hkdf_sha256
exists, does it mean thatec_diffie_hellman
should only do the key agreement part but not the derivation? Does Ockam perform these two operations one after the other anyway?KeyIdVault
Parsec already uses
String
to refer to keys stored in the various crypto backends so those methods should be trivial to implement.SecretVault
All of those key management methods are already available in Parsec. Respectively:
psa_generate_key
psa_import_key
psa_export_key
key_attributes
psa_export_public_key
psa_destroy_key
The
SecretAttributes
look close enough to theAttributes
with the following details:For key types:
SecretType::Buffer
should map toType:RawData
SecretType::Aes
should map toType::Aes
SecretType::Curve25519
should map toType::EccKeyPair
orType::EccPublicKey
(I guess depending on the context) with the familyEccFamily::Montgomery
. For the Curve25519, thebits
field should be 255. See this.SecretType::P256
should be the same as above but with the ECC family set toEccFamily::SecpR1
andbits
to 256. To double-check betweenSecpR1
andSecpK1
.SecretType::Bls
: if this refer to that, I am not sure this is defined in the PSA Crypto API and hence we could not use it :(Signer
sign
should map topsa_sign_message
. If we use a software implementation to hash the data before signing it,psa_sign_hash
should be enough. I guess the algorithm to use could be deduced from the key type. Looks like it is going to be ECDSA in all cases? The input data and signature format should be checked: what hash needs to be used fordata
(or is it already hashed with something?). The format returned inSignature
might not be the one we use in Parsec.SymmetricVault
aead_aes_gcm_encrypt
and_decrypt
should be covered withpsa_aead_encrypt
and_decrypt
. The algorithm to use should beAes::Gcm
.Verifier
Similar to
Signer
withpsa_verify_message
.