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

> -----Original Message-----
> From: Ryan Sleevi [mailto:sleevi@google.com]
> Sent: Monday, July 22, 2013 3:58 PM
> To: Jim Schaad
> Cc: Vijay Bharadwaj; public-webcrypto@w3.org; Richard Barnes; Israel
Hilerio
> Subject: Re: ACTION-84: Finishing support for key derivation/key agreement
> (take 2)
> 
> On Mon, Jul 22, 2013 at 3:41 PM, Jim Schaad <ietf@augustcellars.com>
> wrote:
> >
> >
> >> -----Original Message-----
> >> From: Ryan Sleevi [mailto:sleevi@google.com]
> >> Sent: Monday, July 22, 2013 11:57 AM
> >> To: Vijay Bharadwaj
> >> Cc: public-webcrypto@w3.org; Richard Barnes; Jim Schaad; Israel
> >> Hilerio
> >> Subject: 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.htm
> >> l), 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.
> >
> > Just for my edification.  Is the problem that the built in version of
> > DH would be unable to make the call to the polyfill KDF function?
> 
> Correct - but it was based on a misunderstanding of Vijay's proposal.
> 
> I understood the original proposal was that Z would be fed directly into
the
> KDF, and the key returned was the derived key. However, after reading this
> again, I see that the Key returned wraps Z as a 'raw'
> key.
> 
> So the only issue here is that the algorithm (derivationAlgorithm) may be
> something being polyfilled - in which case, a native implementation cannot
> execute the algorithm normalization parameters or handle it for a
polyfilled
> case.
> 
> Normally, a JS application would use any of the ES5/ES6 methods available
to
> intercept and/or wrap window.crypto.subtle's prototype with its own
> extensions. However, in this case, it can't intercept the derivedKey
algorithm.
> 
> However, this issue exists in the current ED as well - the
derivedAlgorithm
> parameter (which isn't even specified fully - oops!) has the same issues.
> 
> Off the top of my head (eg: not having fully considered the implementation
> complexities/realities), I can see a couple solutions, but they all feel a
bit
> gross:
> - Expose a meta 'raw' algorithm to allow a Key object to be created that
can
> then be exported
> - Expose a meta 'raw' KDF, for which deriveBits() just exposes the key
bits
> - Expose some 'secret agree bits' function
> 
> Of this, I'm inclined to go for a 'raw' KDF, but if anyone else has better
> suggestions, I'm all for it.

Can't you just export the returned key object?  

> 
> >
> > The value of Z appears to be to be passed to the importKey algorithm,
> > but it is not clear what is returned in the resolve since that is
> > saying value not result.
> >
> 
> I don't understand what you mean here. Vijay's text seemed clear on this
> point:
> 
> 11.  Let result be the result of executing the importKey algorithm [...]
12. [...]
> 13. Execute resolver's resolve(value) algorithm, with result as the value
> argument.

One of these day's I will get use to how these things are written - I kind
of expected it to just say 'resolve(result)'

Received on Monday, 22 July 2013 23:18:22 UTC