Proposal for key wrap/unwrap (ISSUE-35)

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)
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)
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
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."

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.

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

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.
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."

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

Received on Tuesday, 30 October 2012 08:39:31 UTC