parallaxsecond / parsec

Platform AbstRaction for SECurity service
https://parsec.community/
Apache License 2.0
471 stars 68 forks source link

Create a Parsec Ockam Vault: investigation #507

Open hug-dev opened 3 years ago

hug-dev commented 3 years ago

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 the parsec-client dependency would have to be created and that structure would have to implement the ockam_vault_core traits.

Let's review them one per one (for the 0.20.0 version).

AsymmetricVault

ec_diffie_hellman: this seems to be the psa_raw_key_agreement function with the Ecdh algorithm. However, if the output Secret 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 operation psa_key_derivation_key_agreement. This operation is a multi-part operation that has not yet been designed in Parsec.

Hasher

sha256 is available as psa_hash_compute with the Sha256 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 that ec_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:

The SecretAttributes look close enough to the Attributes with the following details:

For key types:

Signer

sign should map to psa_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 for data (or is it already hashed with something?). The format returned in Signature might not be the one we use in Parsec.

SymmetricVault

aead_aes_gcm_encrypt and _decrypt should be covered with psa_aead_encrypt and _decrypt. The algorithm to use should be Aes::Gcm.

Verifier

Similar to Signer with psa_verify_message.

mrinalwadhwa commented 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.

SanjoDeundiak commented 3 years ago

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:

  1. Partial compatibility. Implementation compatible only with itself, the expectation here is that all communicating parties use the same Vault implementation, and things may break if one of the parties switch it do different implementation. In this case there are less constraints on what's actually happening inside such implementation in terms of input/output formats. It's only important that implementation match general expectation of particular trait, and it also limited by using types we declare in ockam_vault_core crate
  2. Full compatibility. Implementation compatible with existing software implementation of Ockam Vault, that we provide. This is better, since it's much easier to make sure everything works and is secure, because it comes down to testing both implementation using test suite with same test vectors. This implementation is harder to achieve, since it's required to use exactly same crypto and exactly same input/output formats that we do. I'll provide more details about our implementation as of ockam_vault and ockam_vault_core version v0.20.0

    AsymmetricVault

    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

    Hasher

    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.

    KeyIdVault

    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

    SecretVault

    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.

    Signer

    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:

hug-dev commented 3 years ago

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.

SanjoDeundiak commented 3 years ago

@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!