Abstract

This is a first attempt at specifying Curve25519 ECDH in WebCrypto.

Status of This Document

First draft.

Table of Contents

1. ECDH-CURVE25519 

1.1. Description 

This describes using Elliptic Curve Diffie-Hellman (ECDH) for key generation and key agreement, as specified by Curve25519.

1.2. Registration 

The recognized algorithm name for this algorithm is "ECDH-CURVE25519".

Operation Parameters Result
generateKey None CryptoKeyPair
deriveBits EcdhKeyDeriveParams Octet string
importKey None CryptoKey
exportKey None object

1.3. Operations 

Generate Key
  1. If usages contains a value which is not one of "deriveKey" or "deriveBits", then return an error named InvalidAccessError.

  2. Generate an Elliptic Curve key pair, as defined in [Curve25519].

  3. If performing the operation results in an error, then return an error named OperationError.

  4. Let algorithm be a new KeyAlgorithm object.

  5. Set the name member of algorithm to "ECDH-CURVE25519".

  6. Let publicKey be a new CryptoKey object representing the public key of the generated key pair.

  7. Set the [[type]] internal slot of publicKey to "public"

  8. Set the [[algorithm]] internal slot of publicKey to algorithm.

  9. Set the [[extractable]] internal slot of publicKey to true.

  10. Set the [[usages]] internal slot of publicKey to be the empty list.

  11. Let privateKey be a new CryptoKey object representing the private key of the generated key pair.

  12. Set the [[type]] internal slot of privateKey to "private"

  13. Set the [[algorithm]] internal slot of privateKey to algorithm.

  14. Set the [[extractable]] internal slot of privateKey to extractable.

  15. Set the [[usages]] internal slot of privateKey to be the usage intersection of usages and [ "deriveKey", "deriveBits" ].

  16. Let result be a new CryptoKeyPair dictionary.

  17. Set the publicKey attribute of result to be publicKey.

  18. Set the privateKey attribute of result to be privateKey.

  19. Return the result of converting result to an ECMAScript Object, as defined by [WEBIDL].

Derive Bits
  1. If the [[type]] internal slot of key is not "private", then return an error named InvalidAccessError.

  2. Let publicKey be the public member of normalizedAlgorithm.

  3. If the name attribute of the [[algorithm]] internal slot of publicKey is not "ECDH-CURVE25519", then return an error named InvalidAccessError.

  4. If the [[type]] internal slot of publicKey is not "public", then return an error named InvalidAccessError.

  5. Perform the Curve25519 function specified in Curve25519 with key as the EC private key (first argument) and the EC public key represented by the [[handle]] internal slot of publicKey (second argument).

  6. If performing the operation results in an error, then return an error named OperationError.

  7. Let secret be the 32-byte octet string output from the Curve25519 function defined in Curve25519. In other words, secret is the unique 32-byte little-endian encoding of an integer >= 0 and < 2255-19.

  8. If length is null:
    Return secret
    Otherwise:
    If 256 is less than length:
    Return an error named DataError.
    Otherwise:
    Return the first length bits of secret.
Import Key
  1. Let keyData be the key data to be imported.

  2. If format is "jwk":
    1. Let jwk be the JsonWebKey dictionary represented by keyData.

    2. If an error occurred while parsing, then return an error named DataError.

    3. If the "kty" field of jwk is not "oct", then return an error named DataError.

    4. If the "use" field of jwk is present, then return an error named DataError.

    5. If the "key_ops" field of jwk is present, and is invalid according to the requirements of JSON Web Key, or it does not contain all of the specified usages values, then return an error named DataError.

    6. If the "ext" field of jwk is present and has the value false and extractable is true, then return an error named DataError.

    7. If the "k" field of jwk is not a base64url encoding of a 32-byte octet string then return an error named DataError.

    8. If the "k" field of jwk does not have bits 0, 1, and 2 of the first byte clear, bit 7 of the last byte clear, and bit 6 of the last byte set, as per Curve25519 Section 3, then return an error named DataError.

    9. Let key be a new CryptoKey object that represents the Elliptic Curve private key identified by interpreting the "k" field of jwk as a private key according to Curve25519.

    10. Let algorithm be a new instance of a KeyAlgorithm object.

    11. Set the name attribute of algorithm to "ECDH-CURVE25519".

    12. Set the [[algorithm]] internal slot of key to algorithm.

    If format is "raw":
    1. If usages is not the empty list, then return an error named DataError.

    2. If extractable is false, then return an error named InvalidAccessError.

    3. Let Q be the Curve25519 public key identified by interpreting keyData according to Curve25519. In other words, keyData is the 32-byte little-endian encoding of an integer >= 0 and < 2255-19. The high-order bit is ignored. If the remaining 255 bits encode a number >= 2255-19, that number is reduced modulo 2255-19.

    4. Let algorithm be a new KeyAlgorithm object.

    5. Set the name attribute of algorithm to "ECDH-CURVE25519".

    6. Let key be a new CryptoKey object.

    7. Set the [[type]] internal slot of key to "public"

    8. Set the [[algorithm]] internal slot of key to algorithm.

    9. Set the [[usages]] internal slot of key to usages.

    10. Set the [[extractable]] internal slot of key to extractable.

    Otherwise:

    Return an error named NotSupportedError.

  3. Return key

Export Key
  1. Let key be the CryptoKey to be exported.

  2. If the underlying cryptographic key material represented by the [[handle]] internal slot of key cannot be accessed, then return an error named OperationError.

  3. If format is "jwk":
    1. If the [[type]] internal slot of key is not "private", then return an error named OperationError.

    2. Let jwk be a new JsonWebKey dictionary.

    3. Set the kty attribute of jwk to "oct".

    4. Set the k attribute of jwk to a base64url encoding of the 32-octet curve25519 private key. In other words, the base64url-encoded value is a 32-byte encoding of a little-endian integer with bits 0, 1, and 2 of the first byte clear, bit 7 of the last byte clear, and bit 6 of the last byte set.

    5. Set the key_ops attribute of jwk to the usages attribute of key.

    6. Set the ext attribute of jwk to the [[extractable]] internal slot of key.

    7. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WEBIDL].

    If format is "raw":
    1. If the [[type]] internal slot of key is not "public", then return an error named InvalidAccessError.

    2. Let data be the 32-byte octet string representing the Curve25519 public key represented by [[handle]] internal slot of key according to Curve25519. In other words, data is the unique 32-byte little-endian encoding of an integer >= 0 and < 2255-19.

    3. Let result be a new ArrayBuffer containing data.

    Otherwise:

    Return an error named NotSupportedError.

  4. Return result.

A. Acknowledgements

Thanks to Dan Berstein for Curve25519. Thanks to Ryan Sleevi for advice.