Re: JWK import/export as ECMAScript objects, rather than ArrayBuffer

Hi Ryan,

This looks good with the following comments:

(1) Why not add this capability, whilst keeping the existing JWK import /
export ? For example add a new format "jwk-obj". This would keep things
simple for the other use-case where the JWK is just being written to / read
from a wire protocol. Supporting both is hardly arduous since UAs must
support the serialization / de-serialization for wrap / unwrap anyway.

(2) WebIDL appears to be a little ambiguous with respect to unions of
Dictionaries. Section 14.2.25 says "If types includes a dictionary
type<http://www.w3.org/TR/WebIDL/#idl-dictionary>,
then return the result of
converting<http://www.w3.org/TR/WebIDL/#dfn-convert-ecmascript-to-idl-value>
 V to that dictionary type.
", which pointedly neglects to say which dictionary type in types, if
there is more than one.

(3) We need a
JwkKeyDictionary subclass for symmetric keys:

JwkSecretKeyDictionary : JwkKeyDictionary {
  DOMString k;
};

(4) usages in JwkKeyDictionary should be "key_ops"

(5) Do we want to include the "use" member ? I thought we checked that for
consistency ?

...Mark


On Tue, Mar 11, 2014 at 5:22 PM, Ryan Sleevi <sleevi@google.com> wrote:

> The motivation:
>
> * Provide a means of easy interchange with Web Sockets (eg: by allowing
> Text Frame, rather than imposing Binary Frame, as done by send(ArrayBuffer)
> )
> * Provide a means of easy interchange of JWK with postMessage (eg: by not
> requiring a Key object itself be posted)
> * Provide a means of easy integration with larger JSON-backed messages
>
> That is, presume a structure
> {
>   'larger_message': 'something',
>   'jwk': [{
>     'kid': 'foo',
>     'alg': 'RSA',
>     'kty': 'RSA1_5',
>     'n': '....',
>     'e': '....'
>   }]
> }
>
> Under the current API, one has two options - depending on UA support for
> http://encoding.spec.whatwg.org/#api
>
> With Encoding support:
>
> // Makes 3 additional copies of message.jwk
> // 1 for the .stringify
> // 1 for the TextEncoder
> // 1 for the importKey (cloning the ArrayBuffer)
> // By definition, this copies *all* fields of message.jwk, including those
> not used by importKey (eg: 'kid')
>
> message = JSON.parse(message);
> jwkBuf = (new TextEncoder("utf-8")).encode(JSON.stringify(message.jwk));
> window.crypto.subtle.importKey("jwk", jwkBuf, { name: "RSAES-PKCS1-v1_5"
> }, [ "encrypt", "decrypt"] );
>
> Without Encoding support:
> It's necessary to do something like strToUTF8Arr (
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding)
>
> Under the proposed API, one simply does
>
> // Makes 1 additional copy of message.jwk
> // 1 for the importKey (cloning message.jwk)
> // By definition, this *does not* copy all fields of message.jwk - only
> those fields used for the import (eg: 'kid' is NOT copied)
> window.crypto.subtle.importKey("jwk", message.jwk, { name:
> "RSAES-PKCS1-v1_5" }, [ "encrypt", "decrypt" ]);
>
>
> Types used:
>
> dictionary JwkKeyDictionary {
>   DOMString kty;
>   DOMString alg;
>   boolean ext;
>   DOMString[] usages;
> };
>
> dictionary JwkEcKeyDictionary : JwkKeyDictionary {
>   DOMString crv;
>   DOMString x;
>   DOMString y;
>   DOMString d;
> };
>
> dictionary JwkRsaOtherPrimeDictionary {
>   DOMString r;
>   DOMString d;
>   DOMString t;
> };
>
> dictionary JwkRsaKeyDictionary : JwkKeyDictionary {
>   DOMString n;
>   DOMString e;
>   DOMString d;
>   DOMString p;
>   DOMString dp;
>   DOMString dq;
>   DOMString qi;
>   JwkRsaOtherPrimeDictionary[] oth;
> };
>
>
>
> Changes to signatures:
> Old:
> Promise<any> importKey(KeyFormat format, CryptoOperationData keyData,
> AlgorithmIdentifier? algorithm, boolean extractable, KeyUsage[] keyUsages);
> Promise<any> exportKey(KeyFormat format, Key key);
>
> New:
> Promise<any> importKey(KeyFormat format, (CryptoOperationData or
> JwkRsaKeyDictionary or JwkEcKeyDictionary), AlgorithmIdentifier algorithm,
> boolean extractable, KeyUsage[] keyUsages);
> Promise<any> exportKey(KeyFormat format, Key key);
>
>
> Changes to algorithms:
> Wrap Key ( 14.3.1 /
> https://dvcs.w3.org/hg/webcrypto-api/raw-file/3f7df730b2c7/spec/Overview.html#SubtleCrypto-method-wrapKey)
>
> 12.
> * If format is "spki":
>   - Let bytes be the result of performing the export key operation
> specified the algorithm attribute of key using key and format.
> * If format is "pkcs8"
>   - Let bytes be the result of performing the export key operation
> specified the algorithm attribute of key using key and format.
> * If format is "jwk"
>   - Let object be the result of performing the export key operation
> specified by the algorithm attribute of key using key and format.
>   - Let stringifiedJwk be the result of invoking the JSON.stringify method
> specified in Section 15.12.3 of [ECMA-252], with /object/ as /value/.
>   - Let bytes be the UTF-8 encoding of stringifiedJwk
>
>
> From the algorithm-specific import key sections eg: using
> https://dvcs.w3.org/hg/webcrypto-api/raw-file/3f7df730b2c7/spec/Overview.html#rsassa-pkcs1-operationsas an example
>
> 4. If format is "jwk"
>   1. If /keyData/ is not an instance of a JwkRsaKeyDictionary, return an
> error ...
>   2. Let /jwk/ be /keyData/
>
> From the algorithm-specific export key sections - eg: using again
> RSASSA-PKCS1
>
> 4. If format is "jwk"
>   * Let /jwk/ be a new ECMAScript object created as if by the expression
> ({})
>   * _Set the property "n" of /jwk/_ to the _base64url-encoded_ modulus of
> the RSA public key represented by /key/, as specified by Section 6.3.1 of
> [JWA]
>   * _Set the property "e" of /jwk/_ to the _base64url-encoded_ big integer
> exponent representation of the RSA public key represented by /key/, as
> specified by Section 6.3.1 of [JWA]
>   ...
>   * Let /result/ be /jwk/
>
> Terminology:
> When this specification says Set the property /name/ of /object/ to
> /value/, call the [[DefineOwnProperty]] internal method of /object/ with
> property name /name/, the Property Descriptor { [[Writable]]: true,
> [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: /value/ }, and the
> Boolean flag false.
>
>
>
>

Received on Wednesday, 12 March 2014 00:45:12 UTC