Re: ACTION-84: Finishing support for key derivation/key agreement (take 2)

On Tue, Jun 4, 2013 at 12:03 AM, Vijay Bharadwaj
<Vijay.Bharadwaj@microsoft.com> wrote:
> Following up on the previous thread (see http://lists.w3.org/Archives/Public/public-webcrypto/2013May/0106.html), here is a more fully-fleshed-out proposal based on the latest working draft. Please let me know if I missed anything from the previous discussion, or if you have new comments.
>
> Notes:
> - I am leaving out MQV from the algorithm definitions for now. If there is interest, this can be added. I'd like to point out that Windows and OpenSSL at least do not implement it and adoption may be low due to IPR-related concerns such as Ryan expressed on the earlier thread.
> - This is defined with reference to Futures. This is for consistency with the current draft. To the extent that open issues remain with Futures in the spec, those issues apply here as well.
> - This is also subject to the existing open issues around separation of operational and algorithm parameters.
> - Naming is hard. Existing methods are named <verb> or <verb><noun>. However agreeSecret and computeSecretAgreement sound clunky to me. If you have a better idea please share.
>
> Section 11:
> Add a new value "secretAgreement" to enum KeyUsage.
>
> Section 14:
>
> Add to interface SubtleCrypto:
>
> Future<any> secretAgreement(Key localPrivateKey, Key peerPublicKey, AlgorithmIdentifier agreementAlgorithm, AlgorithmIdentifier derivationAlgorithm, bool extractable = false);
>
> Future<any> deriveBits(AlgorithmIdentifier kdfAlgorithm, Key baseKey, unsigned long bitLength);
>
> Section 14.2:
>
> Add new subsections describing the above methods:
>
> 14.2.x. The secretAgreement method
>
> When invoked, secretAgreement MUST perform the following steps:
>
> 1. Let normalizedAgreementAlgorithm be the result of processing agreementAlgorithm according to the algorithm normalizing rules.
>
> 2. If normalizedAgreementAlgorithm does not describe a registered algorithm that supports the secretAgreement operation, throw a NotSupportedError and terminate the algorithm.
>
> 3. Let normalizedDerivationAlgorithm be the result of processing derivationAlgorithm according to the algorithm normalizing rules.
>
> 4. If normalizedDerivationAlgorithm does not describe a registered algorithm that supports the derive operation, throw a NotSupportedError and terminate the algorithm.
>
> 5. Let future be a new Future object and resolver its associated resolver.
>
> 6. Return future and continue executing the remaining steps asynchronously.
>
> 7. If an error occurs, run these substeps and then terminate the algorithm:
>         1. Let result be null.
>         2. Execute resolver's reject(value) algorithm, with result as the value argument.
>
> 8. If localPrivateKey, peerPublicKey, agreementAlgorithm.localPrivateKey2 (if present), agreementAlgorithm.localPublicKey2 (if present), and agreementAlgorithm.peerPublicKey2 (if present) are not all keys of type normalizedAgreementAlgorithm, terminate this algorithm with an error.
>
> 9. If localPrivateKey, peerPublicKey, agreementAlgorithm.localPrivateKey2 (if present), agreementAlgorithm.localPublicKey2 (if present), and agreementAlgorithm.peerPublicKey2 (if present) do not all contain the "secretAgreement" KeyUsage in their keyUsage properties, terminate this algorithm with an error.
>
> 10. Let secret be the result of executing the secret agreement algorithm defined by the algorithm indicated in normalizedAgreementAlgorithm.
>
> 11. Let result be the result of executing the importKey algorithm, with "raw" as format, with secret as keyData, with normalizedDerivationAlgorithm as algorithm, with extractable as extractable, and "derive" as keyUsages.
>
> 12. If the key import algorithm failed, terminate this algorithm with an error.
>
> 13. Execute resolver's resolve(value) algorithm, with result as the value argument.
>
>
> 14.2.y The deriveBits method
>
> When invoked, deriveBits MUST perform the following steps:
>
> 1. Let normalizedKdfAlgorithm be the result of processing kdfAlgorithm according to the algorithm normalizing rules.
>
> 2. If normalizedKdfAlgorithm does not describe a registered algorithm that supports the derive operation, throw a NotSupportedError and terminate the algorithm.
>
> 3. Let future be a new Future object and resolver its associated resolver.
>
> 4. Return future and continue executing the remaining steps asynchronously.
>
> 5. If an error occurs, run these substeps and then terminate the algorithm:
>         1. Let result be null.
>         2. Execute resolver's reject(value) algorithm, with result as the value argument.
>
> 6. If baseKey.keyUsage does not contain the "derive" KeyUsage, terminate this algorithm with an error.
>
> 7. Let result be an ArrayBuffer object containing the result of executing the key derivation algorithm defined by the algorithm indicated in normalizedKdfAlgorithm, with baseKey as the base key, to generate bitLength bits of output. If bitLength is not a multiple of 8, set the unused bits in the last byte of result to zero.
>
> 8. Execute resolver's resolve(value) algorithm, with result as the value argument.
>
>
> Section 18
>
> 18.8. ECDH
>
>
> 18.8.1. Description
>
> This describes using Elliptic Curve Diffie-Hellman (ECDH) for key generation and key agreement, as specified by X9.63.
>
>
> 18.8.2. Registration
>
> The recognized algorithm name for this algorithm is "ECDH".
>
>
> Operation               Parameters                      Result
> generateKey             EcKeyGenParams          KeyPair?
> secretAgreement EcdhSecretAgreementParams       Key?
>
>
> 18.8.3. EcdhSecretAgreementParams dictionary
>
> IDL
>
> dictionary EcdhSecretAgreementParams : Algorithm {
>   // The caller's secondary (ephemeral) private key, if used
>   Key? localPrivateKey2;
>   // The peer's secondary (ephemeral) public key, if used
>   Key? peerPublicKey2;
> };
>
> 18.8.4. Operations
> *Generate Key
> *Secret Agreement
> Perform the appropriate ECDH secret agreement scheme from SP 800-56A Section 6, depending on whether localPrivateKey2 and peerPublicKey2 are specified. The result is a Key object created by importing the shared secret Z.
>
> Note: X9.63 Section 5.4.2 and NIST SP 800-56A Section 5.7.1.2 specify a modified ECDH primitive that multiplies the shared secret value by the cofactor of the curve. The cofactor of the NIST recommended curves P-256, P-384, and P-521 is 1, so the standard and modified ECDH primitives are equivalent for those curves.
>
>
> 18.15. Diffie-Hellman
>
> 18.15.1. Description
>
> This describes using Diffie-Hellman for key generation and key agreement, as specified by PKCS #3.
>
> 18.15.2. Registration
>
> The recognized algorithm name for this algorithm is "DH".
>
> Operation               Parameters                      Result
> generateKey             DhKeyGenParams          KeyPair?
> secretArgeement DhSecretAgreementParams Key?
>
> 18.15.3. DhKeyGenParams dictionary
>
> IDL
>
> dictionary DhKeyGenParams : Algorithm {
>   // The prime p.
>   BigInteger prime;
>   // The base g.
>   BigInteger generator;
> };
>
> 18.15.4. DhSecretAgreementParams dictionary
>
> IDL
>
> dictionary DhSecretAgreementParams : Algorithm {
>   // The caller's secondary (ephemeral) private key, if used
>   Key? localPrivateKey2;
>   // The peer's secondary (ephemeral) public key, if used
>   Key? peerPublicKey2;
> };
>
> 18.15.5. Operations
> *Generate Key
> *Secret Agreement
> Perform the appropriate DH secret agreement scheme from SP 800-56A Section 6, depending on whether localPrivateKey2 and peerPublicKey2 are specified. The result is a Key object created by importing the shared secret Z.

Sorry for the delays in getting back on this - as I worked through all
the other ongoing discussions.

Let me make sure I understand all the appropriate synthesis.
1) Concat, HDKF, and PBKDF2 are all updated to support 'deriveKey' and
'deriveBits'. If you wish to derive a set of four keys (ex: client
write key, server write key, client hmac key, server hmac key), the
only acceptable thing is to use deriveBits.
2) DH & ECDH are updated to only support secretAgreement (eg: no
deriveKey, no deriveBits)

If that's a correct understanding, then I'm not sure if this will work
for supporting polyfills.

For example, consider the ZRTP (RFC 6189) case. ZRTP describes its own
KDF - one that is (arguably) compatible with SP800-56A 6.1.2.1 (DH
Ephemeral/Ephemeral agreement). If an application wished to polyfill
this, they would also have to implement the DH algorithm in JS, since
there is no way for an application to obtain Z (what is currently
returned by deriveKey). That seems much less flexible.

>From an API perspective, doesn't it seem more likely that the peers
will be using ephemeral/ephemeral agreement? At least using the text
proposed, it seems that localPrivateKey/peerPublicKey are meant to be
the static parameters, rather than the ephemeral keys (eg: from
generateKey over a pre-agreed domain)

While I totally agree with deriveBits as a quality short-hand, it
seems that the only thing that secretAgreement provides over deriveKey
is that it makes the peer key a mandatory parameter, rather than
conveyed via the algorithm params - but at the cost of only being
applicable to public/private key agreement schemes, and somewhat
poorly at that (since we still curry ephemeral keys via the params).

Have I missed an advantage?

Received on Monday, 22 July 2013 18:57:14 UTC