Re: Proposal for key wrap/unwrap (ISSUE-35)

On Oct 30, 2012, at 10:04 AM, Ryan Sleevi wrote:

> On Tue, Oct 30, 2012 at 1:38 AM, Mark Watson <watsonm@netflix.com> wrote:
>> All,
>> 
>> Here is a proposal in response to ISSUE-35 [1], using JWK (with extensions)
>> as the format for the key and associated parameters before wrapping.
>> Wrapping and unwrapping are considered aspects of key export and import
>> (respectively). To export/import without wrapping the user just specifies
>> the wrap algorithm as null.
>> 
>> 1) Add "wrap" and "unwrap" to KeyUsage enum:
>> 
>> "10. Key interface
>> 
>> enum KeyUsage {
>>  "encrypt",
>>  "decrypt",
>>  "sign",
>>  "verify",
>>  "wrap",
>>  "unwrap",
>> };"
>> 
>> 2) Add wrapped attribute to KeyImporter and KeyExporter. Specify the
>> character encoding of JSON Web Keys (we assume that all key export
>> operations result in an ArrayBufferView):
>> 
>> "15. KeyImporter interface
>> 
>> enum KeyFormat {
>>  // An unformatted sequence of bytes. Intended for secret keys.
>>  "raw",
>>  // The BER encoding of the RSAPublicKey structure from RFC 3447.
>>  // Only usable with RSA keys.
>>  "pkcs1-public",
>>  // The BER encoding of the RSAPrivateKey structure from RFC 3447.
>>  // Only usable with RSA keys.
>>  "pkcs1-private",
>>  // The BER encoding of the PrivateKeyInfo structure from RFC 5208.
>>  "pkcs8",
>>  // The key is represented as UTF-8 encoded JSON according to the JSON Web
>> Key format.
>>  "jwk"
>> };
>> 
>> interface KeyImporter : KeyOperation {
>>  void import();
>> 
>>  readonly attribute KeyFormat format;
>>  readonly attribute boolean wrapped;
>> };
>> 
>> interface KeyExporter : KeyOperation {
>>  void export();
>> 
>>  readonly attribute KeyFormat format;
>>  readonly attribute boolean wrapped;
>> };
>> 
>> 15.1. JSON Web Key
>> 
>> Implementations SHOULD support additional JSON Web Key use values of:
>>  • wrap (key wrapping)
> 
> Is there a reason you didn't consider this a MUST?

It could be a MUST as far as I am concerned.

> 
> Note for readers - JWK currently only defines "sign" and "encrypt",
> and so there are a very different set of usages here.

Yep, for whatever reason sign/verify are signaled just as "sign" and encrypt/decrypt as "verify". I want to raise this in JOSE and find out why they didn't separate them. We say below that the usages after an import will be the intersection of those specified in the key data and those specified in the createKeyImporter call, so you can narrow the usages at import.

> 
>> Implementations SHOULD support additional JSON Web Key members of:
>>  • extractable (boolean indicating extractability)
>>  • startdate (key start date in seconds since the epoch)
>>  • enddate (key end date in seconds since the epoch)
> 
> Can you explain the difference between wrap and extractable here? In
> practical security considerations, they're better considered equal.

Do you mean that there is little point in wrapping a key if it is then immediately extractable ? That would be true if there was a difference in trust level between the UA and the client application, as there is in our use-cases, so from my point of view we could say that exportable is always false when unwrapping a key.

But I can imagine other use-cases where the script is entitled to access the key after unwrap, but there is still some reason it was wrapped (for example for transport or storage).

> 
> As for startdate/enddate -
>  - As previously discussed on the list, I thought (and will make a
> separate proposal) to remove the startDate/endDate attributes from the
> fundamental Key object (and let them be stored in the extra - since as
> both Vijay and I pointed out, they're application-specific notions)

Ok, let's discuss this separately and then I'll update the proposal if necessary.

>  - If we do continue with it, "the epoch" is, regrettably, undefined.
> Whose epoch? Unix epoch of 1970? Windows epoch of 1601?

We meant the UNIX one.

> 
>> Implementations SHOULD expose additional JSON Web Key members as attributes
>> contained within the extra attribute of the Key objects.
>> 
>> TODO: Specify encoding of key attributes of potentially arbitrary type into
>> extra attribute map
> 
> One of the issues I see here is whether the 'extra' attribute map gets
> flattened in directly to the JWK (which you seem to be proposing?) or
> get stored in a secondary attribute (eg: 'extra' on the JWK). It seems
> you're proposing the former, but it would seem the latter is necessary
> (eg: what if there is an 'extra' attribute named 'alg' or 'keyid' ?)

Yes, that needs to be worked out. We'd thought more about the other direction (JWK -> extra attributes) which also has some issues to be solved.

> 
>> TODO: Specify JWK formats for private and symmetric keys
>> TODO: Register the above values with IANA
>> TODO: Specify key compatibility between JWK algorithm names with WebCrypto
>> algorithm names."
>> 
>> 3) Modify createKeyImporter and createKeyExporter to take optional wrapping
>> algorithm and key
>> 
>> "18. Crypto interface
>> 
>> KeyImporter createKeyImporter( KeyFormat format,
>> ArrayBufferView key,
>> AlgorithmIdentifier? keyAlgorithm,
>> AlgorithmIdentifier? wrapAlgorithm,
>> Key? wrappingKey,
>> bool temporary = true,
>> bool extractable = false,
>> KeyUsage[] keyUsages = [] );
>> 
>> KeyExporter createKeyExporter( KeyFormat format,
>> Key key,
>> AlgorithmIdentifier? wrapAlgorithm,
>> Key? wrappingKey );
>> 
>> "18.1.8 The createKeyImporter method
>> 
>> The createKeyImporter method returns a new KeyImporter object that will
>> import
>> new keys of the, potentially wrapped, specified KeyFormat. It must act as
>> follows:
>> 
>>  1. If keyAlgorithm is specified, let normalizedKeyAlgorithm be the result
>> of processing keyAlgorithm according to
>>     the algorithm normalizing rules.
>>  2.  If keyAlgorithm is specified and if normalizedKeyAlgorithm does not
>> describe a registered algorithm throw a
>>     NotSupportedError and terminate the operation.
>>  3. If wrapAlgorithm is specified, let normalizedWrapAlgorithm be the
>> result of processing wrapAlgorithm according to
>>     the algorithm normalizing rules.
>>  4.  If wrapAlgorithm is specified and if normalizedWrapAlgorithm does not
>> describe a registered algorithm throw a
>>     NotSupportedError and terminate the operation.
>>  5. Return a new KeyImporter object S with the following characteristics:
>>     1. S.result = null
>>     2. S.format = format
>>     3. S.wrapped = true if wrapAlgorithm is not null, false otherwise
>> 
>> Imported keys SHALL be subject to the extraction and usage constraints of
>> the key
>> data, if any. The temporary argument SHALL be honored. The extractable
>> argument
>> SHALL NOT be honored if the key data does not allow extraction of the
>> imported key. The
>> imported key's usages SHALL consist of the intersection of the keyUsages
>> argument
>> and the usages specified in the key data of the imported key.
>> 
>> The keyAlgorithm may be null if the key algorithm is specified within the
>> key data.
>> 
>> 18.1.9 The createKeyExporter method
>> 
>> The createKeyExporter method returns a new KeyExporter object that will
>> export
>> existing keys in the specified KeyFormat. It must act as follows:
>> 
>>  1. If the key does not exist throw a KeyNotFoundError and terminate the
>>     operation.
>>  2. If wrapAlgorithm is specified, let normalizedWrapAlgorithm be the
>> result of processing wrapAlgorithm according to
>>     the algorithm normalizing rules.
>>  3.  If wrapAlgorithm is specified and if normalizedWrapAlgorithm does not
>> describe a registered algorithm throw a
>>     NotSupportedError and terminate the operation.
>>  4. If wrapAlgorithm is specified and wrappingKey is null, or if
>> wrapAlgorithm is null and wrappingKey is specified, throw a
>> NotSupportedError and terminate the operation
>>  4. If the wrappingKey is not null and does not exist throw a
>> KeyNotFoundError
>>     and terminate the operation.
>>  5. Return a new KeyExporter object S with the following characteristics:
>>     1. S.result = null
>>     2. S.format = format
>>     3. S.wrapped = true if wrapAlgorithm is not null, false otherwise"
>> 
>> 4) Add text on import/export for RSAES-PKCS1-v1_5 keys
>> 
>> "24.3. RSAES-PKCS1-v1_5
>> 
>> 24.3.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "RSAES-PKCS1-v1_5".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> encrypt     | None            | ArrayBufferView?
>> decrypt     | None            | ArrayBufferView?
>> generateKey | RsaKeyGenParams | KeyPair?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.3.4 Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the RSA key
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the RSA key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
>> 5) Add text on import/export for RSASSA-PKCS1-v1_5 keys
>> 
>> "24.4. RSASSA-PKCS1-v1_5
>> 
>> 24.4.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "RSASSA-PKCS1-v1_5".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> sign        | RsaSsaParams    | ArrayBufferView?
>> verify      | RsaSsaParams    | boolean?
>> generateKey | RsaKeyGenParams | KeyPair?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.4.4. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the RSA key
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the RSA key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
>> 6) Add text on import/export for RSA-PSS keys
>> 
>> "24.5. RSA-PSS
>> 
>> 24.5.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "RSA-PSS".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> sign        | RsaPssParams    | ArrayBufferView?
>> verify      | RsaPssParams    | boolean?
>> generateKey | RsaKeyGenParams | KeyPair?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.4.4. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the RSA key
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the RSA key into the format, including any wrap operations
>> as
>>         dictated by the format and wrapAlgorithm.
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
>> 7) Add text on import/export for RSA-OAEP keys
>> 
>> "24.6. RSA-OAEP
>> 
>> 24.6.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "RSA-OAEP".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> encrypt     | RsaOaepParams   | ArrayBufferView?
>> decrypt     | RsaOaepParams   | ArrayBufferView?
>> generateKey | RsaKeyGenParams | KeyPair?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.6.4. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the RSA key
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the RSA key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
>> 8) Add text on import/export for ECDSA keys
>> 
>> "24.7. ECDSA
>> 
>> 24.7.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "ECDSA".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> sign        | EcdsaParams     | ArrayBufferView?
>> verify      | EcdsaParams     | boolean?
>> generateKey | EcKeyGenParams  | KeyPair?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.7.5. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the ECC key
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the ECC key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
>> 9) Add import/export for AES-CTR keys
>> 
>> "24.9. AES-CTR
>> 
>> 24.9.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "AES-CTR".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> encrypt     | AesCtrParams    | ArrayBufferView?
>> decrypt     | AesCtrParams    | ArrayBufferView?
>> generateKey | AesKeyGenParams | Key?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.9.5. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the AES key
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be a Key of the imported secret key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the AES key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported secret key."
>> 
>> 10) Add import/export for AES-CBC keys
>> 
>> "24.10. AES-CBC
>> 
>> 24.10.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "AES-CBC".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> encrypt     | AesCbcParams    | ArrayBufferView?
>> decrypt     | AesCbcParams    | ArrayBufferView?
>> generateKey | AesKeyGenParams | Key?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.10.4. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the AES key.
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be a Key of the imported secret key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the AES key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported secret key."
>> 
>> 11) Add import/export for AES-GCM keys
>> 
>> "24.11. AES-GCM
>> 
>> 24.11.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "AES-GCM".
>> 
>> Operation   | Parameters      | Result
>> ================================================
>> encrypt     | AesGcmParams    | ArrayBufferView?
>> decrypt     | AesGcmParams    | ArrayBufferView?
>> generateKey | AesKeyGenParams | Key?
>> importKey   | None            | Key?
>> exportKey   | None            | ArrayBufferView?
>> 
>> 24.11.4. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the AES key
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be a Key of the imported secret key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the AES key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported secret key."
>> 
>> 12) Add import/export for HMAC keys
>> 
>> "24.12. HMAC
>> 
>> 24.12.2. Registration
>> 
>> The recognized algorithm name for this algorithm is "HMAC".
>> 
>> Operation   | Parameters       | Result
>> ================================================
>> sign        | HmacParams       | ArrayBufferView?
>> verify      | HmacParams       | boolean?
>> generateKey | HmacKeyGenParams | Key?
>> importKey   | None             | Key?
>> exportKey   | None             | ArrayBufferView?
>> 
>> 24.12.4. HmacKeyGenParams dictionary
>> 
>> dictionary HmacKeyGenParams : AlgorithmParameters {
>>  // The inner hash function to use.
>>  AlgorithmIdentifier hash;
>> };
>> 
>> 24.12.5. Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the HMAC key
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the HMAC key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If either operation resulted in an error, raise an error and
>> terminate the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key."
>> 
> 
> There are various issues regarding the copy/paste of text here, but
> those are minor and presumably would be fixed during editor
> integration. Just noting for future work.
> 
> 
>> 13) Add AES Key wrap algorithm
>> 
>> "24.16 AES Key Wrap
>> 
>> 24.16.1 Description
>> 
>> The AES Key Wrap algorithm is described in RFC3394. This specification also
>> requires the use of padding according to RFC5649 in order to support wrapped
>> keys of arbitrary size.
> 
> "requires" is a weak word here. Would you say that it's a correct
> interpretation that AES Key Wrap algorithm MUST support RFC 5649?

Yes, that's what I meant.

> 
>> 
>> 24.16.2 Registration
>> 
>> The recognized algorithm name for this algorithm is "AES-KW".
>> 
>> Operation   | Parameters       | Result
>> ================================================
>> generateKey | AesKeyGenParams  | Key
>> importKey   | None             | Key
>> exportKey   | None             | ArrayBufferView
>> wrap     | None             | ArrayBufferView
>> unwrap      | None             | Key
> 
> I must admit, I'm not entirely sure I follow the distinction between
> the wrap/unwrap operation here for AES-KW, and all of the
> import/export additions/changes to the other algorithms. It seems only
> one or the other is necessary/appropriate? Have I missed something?

import/export are for importing/exporting an AES Key Wrap Key.

wrap/unwrap are for wrapping/unwrapping another key using an AES Key Wrap Key for the wrap/unwrap.

The Import/Export operation descriptions for each key type refer to performing the unwrap/wrap operation as the first/last step of the import/export. The unwrap/wrap operations here describe how to do that step for the case of AES Key Wrap.

I found it confusing too. Suggestions on how to make this clearer welcome!

> 
>> 
>> 24.16.3 Operations
>> 
>> Import Key
>>  When importing a key, the resulting KeyImporter shall behave as follows:
>> 
>>    1. Upon invoking import:
>>      1. If the key is wrapped, perform the unwrap operation defined for the
>> wrapAlgorithm
>>      2. Parse and extract the AES Key Wrap key
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>        operation.
>>      4. Let result be a Key of the imported public or private key.
>> 
>> Export Key
>>  When exporting a key, the resulting KeyExporter shall behave as follows:
>> 
>>    1. Upon invoking export:
>>      1. Encode the AES Key Wrap key into the format
>>      2. If the key is to be wrapped, perform the wrap operation defined for
>> the wrapAlgorithm
>>      3. If the operation resulted in an error, raise an error and terminate
>> the
>>         operation.
>>      4. Let result be an ArrayBufferView of the exported public or private
>> key.
>> 
>> Unwrap:
>> 
>> When unwrapping and importing a wrapped key, the following unwrapping steps
>> shall be performed first, followed by the steps of the importKey operation
>> for the appropriate key algorithm:
>> 
>> 1. If the wrapKey is not an AES Key Wrap key, throw a NotSupporterError and
>> terminate the operation
>> 2. Apply the RFC5649 unwrapping operation to the provided key, using the
>> wrapKey
>> 1. If the result of the unwrapping operation is a failure of the data
>> integrity check, raise an error and terminate the operation
>> 2. Otherwise, if the key data specifies a key algorithm
>> 1. if the keyAlgorithm parameter to the import operation is not null and the
>> key algorithm specified by the key data is not compatible with the
>> keyAlgorithm parameter, raise an error and terminate the operation.
> 
> Can you clarify a bit on "key algorithm specified by the key data". It
> sounds like you mean translating the JWK alg (aka a JWA) into a Web
> Crypto alg, and then comparing them. Is that correct?

Yes.

> What if the
> keyAlgorithm parameters specifies parameters that cannot be encoded
> within JWA? Are those comparable/compatible? Is there some
> normalization that needs to occur before comparison?

One of the TODOs in the JWK section is to define these compatibility rules. The keyAlgorithm in the createKeyImporter call is primary. We need to define what it means for JWK alg values to be 'compatible' with a keyAlgorithm. Probably we need a table enumerating the cases and addressing parameters on an algorithm by algorithm basis.

> 
> If we do go with this, I would almost suggest dropping the comparison
> entirely - letting the algorithm be fully dictated by the
> unwrapper/importer.

Do you mean ignoring the alg value in the JWK ? Not sure we can do that: I can't import an RSA SSA key as an AES key.

If you mean ignoring the keyAlgorithm in the createKeyImporter (or requiring it to be null in the jwk unwrap case), we could do that.

> 
>> 2. Otherwise, if the keyAlgorithm parameter is null, set the key algorithm
>> to be the key algorithm specified by the key data
>> 3. Continue the key import operation using the output of the unwrap
>> operation according to the requirements of the key algorithm
>> 
>> Wrap
>> 
>> When wrapping and exporting a key, the resulting key exporter shall behave
>> according to the specification of the key algorithm with the following
>> additional requirements for the wrapping step:
>> 
>> 1. If the wrapKey is not an AES Key Wrap key, throw a NotSupporterError and
>> terminate the operation
>> 2. Apply the RFC5649 wrapping operation to the output of the key export
>> operation
>> 3. Let the result be an ArrayBufferView of the exported, wrapped, key"
>> 
>> 14) Provide an example of wrapped key import
>> 
>> "26.4 Wrapped key import
>> 
>> // The key type, exportability, start and end time are specified in the JWK
>> structure.
>> // It is assumed JWK is extended to support private and symmetric keys.
>> // For example, the following could describe an AES CTR encryption key (note
>> this uses values
>> // not specified in JWK which so far only addresses public keys. However,
>> JWK can be extended
>> // on a 'specification required' basis through registration with IANA).
>> //
>> // keyJwk = { "use" : "enc", "alg" : "A256", "exportable" : false, "key" :
>> "56giug87f298gf9724gf9==" }
>> //
>> // for the purposes of this example, wrappedKeyJwk = AESKeyWrap( keyJwk,
>> wrappingKey )
>> 
>> var keyImporter = window.crypto.createKeyImporter(  "jwk",
>> wrappedKeyJwk,
>> "AES-CTR",
>> "AES-KW",
>> wrappingKey,
>> true, // temporary
>> true, // extractable
>> [ "encrypt" ] );
>> keyImporter.onComplete = function(event) {
>>  var key = event.target.result;
>>  console.log("Imported key ID: " + key.id + "; algorithm " +
>> key.algorithm.name + "; exportable " + key.exportable );
>> };
>> keyImporter.import();
>> 
>> In the above example, the final output should indicate "exportable false",
>> because the exportable attribute in the wrapped JWK structure is set to
>> false."
> 
> If you've wrapped a key into JWK, I would strongly suggest that you
> just exported it :)
> 
> For example, using a known/fixed-by-an-attacker Key Wrapping Key in
> order to export the un-extractable/un-exportable key would allow me to
> easily recover the original key text.

Yes, if a key is not exportable, it should not be exportable in either wrapped or unwrapped form. Did I say something to the contrary ?

The example is of an *import*. It's not suggested that the structure being imported was generated by a WebCrypto export somewhere else. The example shows the exportable value in the JWK taking precedence over the value in the createKeyImporter call.

…Mark

> 
>> 
>> [1] http://www.w3.org/2012/webcrypto/track/issues/35
> 

Received on Tuesday, 30 October 2012 10:26:21 UTC