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

Can you provide more design rationale for choosing RSA-KEM, rather
than the much more widely supported RSA-OAEP (eg: RFC 3560). I don't
know of a single well-tested, CORRECT implementation of RSA-KEM in the
popular cryptographic libraries and bindings.

Your extension of RSAES-PKCS1-v1_5 is not at all correct, considering
that RSA-KEM has nothing to do with RSAES (eg: it is intentionally
structure-less). We're talking about an entirely different algorithm
here, orthogonal from RSASSA and RSAES, and distinct from RSA-PSS and
RSA-OAEP.

Further, the parameters necessary in order to specify RSA-KEM are huge
(see Section B.4 for a more visual example of all the details
necessary to be specified)

On Tue, Jan 15, 2013 at 4:37 PM, Mark Watson <watsonm@netflix.com> wrote:
> All,
>
> I have updated our proposal for this issue and posted it here:
> http://www.w3.org/2012/webcrypto/wiki/KeyWrap_Proposal
>
> Regards,
>
> Mark
>
> On Oct 30, 2012, at 1:38 AM, Mark Watson 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)
> 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 Thursday, 17 January 2013 03:13:42 UTC