PKI.js icon indicating copy to clipboard operation
PKI.js copied to clipboard

Add support for HKDF when using KeyAgreeRecipientInfo in EnvelopedData

Open gnarea opened this issue 5 years ago • 3 comments

X9.63 is the only KDF supported by EnvelopedData, but I have to use HKDF instead. What's the best way to achieve this?

There's no method or property I can override to use a different function, so I think this can't be implemented without changing PKI.js itself. (I could potentially override .encrypt() and decrypt(), but I'd end up duplicating an awful lot of code from PKI.js, which wouldn't be a good idea.)

I'd be happy to put together a PR to add support for HKDF (and any other KDF), and here's what I have in mind:

Since KeyAgreeRecipientInfo doesn't hold any data about the KDF, we'd have to specify the KDF on each call to EnvelopedData.encrypt() and EnvelopedData.decrypt() (X9.63 would still be used by default for backwards compatibility). This extra argument could be a function with the signature kdf(sharedKey: CryptoKey, recipientInfo: KeyAgreeRecipientInfo): Promise<ArrayBuffer>.

How does this sound? I'm also open to a less invasive alternative, if there's one.

gnarea avatar Dec 12 '19 03:12 gnarea

Support tor HKDF is something that would be nice to have. A PR would be welcomed as long as it matches project style and has appropriate test coverage.

@YuryStrozhevsky is best to comment on approach but that sounds reasonable to me.

rmhrisk avatar Dec 12 '19 06:12 rmhrisk

@gnarea I have inverstigated the question a little. So, in fact there is a place in CMS where you could/should state which KDF you were using - KeyAgreeRecipientInfo.keyEncryptionAlgorithm. There you could state kaa-dhSinglePass-stdDH-hkdf-sha256-scheme OID, for example. And it could be implemented in PKIjs with not so big changes in the code. Also I need to mention that at the moment there is a parameter for EnvelopedData.encrypt function which describes KDF algorithm - kdfAlgorithm. But at the moment it is only a hash algorithm for standard KDF. So, it would requires to change getOIDByAlgorithm function plus changes in SubKeyAgreeRecipientInfo function in order to select necessary KDF function based on KeyAgreeRecipientInfo.keyEncryptionAlgorithm. I will think how to better cover it.

YuryStrozhevsky avatar Dec 12 '19 07:12 YuryStrozhevsky

@rmhrisk, @YuryStrozhevsky, thank you so much for the prompt and helpful replies!

So, in fact there is a place in CMS where you could/should state which KDF you were using - KeyAgreeRecipientInfo.keyEncryptionAlgorithm. There you could state kaa-dhSinglePass-stdDH-hkdf-sha256-scheme OID, for example.

Good catch! Just to be clear, I think you're referring to RFC 8418 which covers the use of X25519 and X448 in CMS, right? This approach would have the added bonus of helping with #89.

Also I need to mention that at the moment there is a parameter for EnvelopedData.encrypt function which describes KDF algorithm - kdfAlgorithm. But at the moment it is only a hash algorithm for standard KDF. So, it would requires to change getOIDByAlgorithm function plus changes in SubKeyAgreeRecipientInfo function in order to select necessary KDF function based on KeyAgreeRecipientInfo.keyEncryptionAlgorithm.

Good point. I missed that.

I will think how to better cover it.

Me too. I think I'm going to put together a proof of concept so we can have something more concrete to discuss.

gnarea avatar Dec 12 '19 12:12 gnarea