Skip to content

Commit

Permalink
Consistency
Browse files Browse the repository at this point in the history
  • Loading branch information
sander committed Jan 19, 2025
1 parent db0e0ae commit 0714c36
Showing 1 changed file with 65 additions and 102 deletions.
167 changes: 65 additions & 102 deletions draft-dijkhuis-cfrg-hdkeys.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ normative:
RFC8017:
RFC9180:
RFC9380:
RFC9497:
SEC2:
title: "SEC 2: Recommended Elliptic Curve Domain Parameters, Version 2.0"
target: https://www.secg.org/sec2-v2.pdf
Expand Down Expand Up @@ -101,6 +102,12 @@ informative:
author:
- name: E. Verheul
date: 2024-09-18
Wilson2023:
title: Post-Quantum Account Recovery for Passwordless Authentication. Master’s thesis
target: https://hdl.handle.net/10012/19316
author:
- name: Spencer MacLaren Wilson
date: 2023-04-24

--- abstract

Expand Down Expand Up @@ -223,11 +230,10 @@ Blinding methods can be constructed such that the secure cryptographic device do

The parameters of an HDK instantiation are:

- `ID`: A domain separation tag, represented as a string of ASCII bytes.
- `Ns`: The amount of bytes of a salt value with sufficient entropy.
- `H`: A cryptographic hash function.
- H(msg): Outputs `Ns` bytes.
- `BL`: A key blinding scheme with opaque blinding factors and algebraic properties, consisting of the functions:
- `BL`: A key blinding scheme [Wilson2023] with opaque blinding factors and algebraic properties, consisting of the functions:
- DeriveBlindKey(ikm): Outputs a blind key `bk` based on input keying material `ikm`.
- DeriveBlindingFactor(bk, ctx): Outputs a blinding factor `bf` based on a blind key `bk` and an application context byte string `ctx`.
- BlindPublicKey(pk, bk, ctx): Outputs the result public key `pk'` of blinding public key `pk` with blind key `bk` and application context byte string `ctx`.
Expand Down Expand Up @@ -279,10 +285,12 @@ Outputs:
- salt', the next salt for HDK derivation.

def DeriveSalt(salt, ctx):
salt' = H1(ID || salt || ctx)
salt' = H(salt || ctx)
return salt'
~~~

Salt values, including the original seed value, MUST NOT be reused outside of HDK.

## The HDK function

A local unit or a remote party deterministically computes an HDK from an index, a parent public key, a salt, and an optional parent blinding factor. The salt can be an initial seed value of `Ns` bytes or it can be taken from another parent HDK. The secure generation of the seed is out of scope for this specification.
Expand Down Expand Up @@ -397,7 +405,8 @@ Step 4 MAY be postponed to be combined with step 6. Steps 5 to 8 MAY be combined

Instantiations of HDK using digital signatures require the following cryptographic constructs:

- `DSA`: A digital signature algorithm , consisting of the functions:
- `DSA`: A digital signature algorithm, consisting of the functions:
- GenerateKeyPair(): Outputs a new key pair `(sk, pk)` consisting of private key `sk` and public key `pk`.
- Sign(sk, msg): Outputs the signature created using private signing key `sk` over byte string `msg`.
- Verify(signature, pk, msg): Outputs whether `signature` is a signature over `msg` using public verification key `pk`.

Expand All @@ -420,9 +429,11 @@ msg = create_message(pk, nonce) # out of scope for this spec
Verify(signature, pk, msg)
~~~

By design of `BL`, the same proof of possession protocol can be used with blinded key pairs and BlindSign, in such a way that the reader does not recognise that key blinding was used.
Instantiations of HDK using digital signatures instantiat the following:

An instantiation using `DSA` intantiates the following:
- `BL`: A cryptographic construct that extends `DSA` as specified in [I-D.draft-irtf-cfrg-signature-key-blinding-07], implementing the interface from [Instantiation parameters](#instantiation-parameters).

While [I-D.draft-irtf-cfrg-signature-key-blinding-07] does not expose blinding factors, it provides public algorithms to compute these. In HDK, the computed blinding factors are applied in `BL` as follows:

~~~
def BlindSign(sk, bf, msg):
Expand All @@ -431,22 +442,25 @@ def BlindSign(sk, bf, msg):
return signature
~~~

- [I-D.draft-irtf-cfrg-signature-key-blinding-07]
By design of `BL`, the same proof of possession protocol can be used with blinded key pairs and BlindSign, in such a way that the reader does not recognise that key blinding was used.

In the default implementation, BlindSign requires support from the secure cryptographic device protecting `sk`. In some cases, BlindSign can be implemented in an alternative, distributed way. An example will be provided below.

## Using elliptic curves
Applications MUST bind the message to be signed to the blinded public key. This mitigates attacks based on signature malleability. Several proof of possession protocols require including document data in the message, which includes the blinded public key indeed.

Instantiations of HDK using elliptic curves require the following cryptographic constructs:
## Using prime-order groups

- `EC`: An elliptic curve with elements of type Element and scalars of type Scalar, consisting of the functions:
- GenerateRandomScalar(): Outputs a random Scalar `k`.
Instantiations of HDK using prime-order groups require the following cryptographic constructs:

- `G`: A prime-order group as defined in [RFC9497] with elements of type Element and scalars of type Scalar, consisting of the functions:
- RandomScalar(): Outputs a random Scalar `k`.
- Add(A, B): Outputs the sum between Elements `A` and `B`.
- ScalarMult(A, k): Outputs the scalar multiplication between Element `A` and Scalar `k`.
- ScalarBaseMult(k): Outputs the scalar multiplication between the base Element and Scalar `k`.
- Order(): Outputs the order of the base Element.
- SerializeElement(A): Outputs a byte string representing Element `A`.
- SerializeScalar(k): Outputs a byte string representing Scalar `k`.`
- `H2C`: A hash-to-curve suite [RFC9380] for EC, providing the function:
- hash_to_field(msg, count): Outputs `count` EC Elements based on the result of cryptographically hashing `msg` (see [RFC9380], Section 5.2).
- HashToScalar(msg): Outputs the result of deterministically mapping a byte string `msg` to an element in the scalar field of the prime order subgroup of `G`, using the `hash_to_field` function from a hash-to-curve suite [RFC9380].

~~~
def GenerateKeyPair():
Expand All @@ -455,33 +469,21 @@ def GenerateKeyPair():
return (sk, pk)

def DeriveBlindKey(ikm):
bk_scalar = hash_to_field(ikm, 1) with the parameters:
DST: ID || ctx
F: GF(EC-Order()), the scalar field
of the prime order subgroup of EC
p: EC-Order()
m: 1
L: as defined in H2C
expand_message: as defined in H2C
bk_scalar = HashToScalar(ikm)
bk = SerializeScalar(bk_scalar)
return bk

def DeriveBlindingFactor(bk, ctx):
msg = bk || 0x00 || ctx
bf = hash_to_field(msg, 1) with the parameters:
DST: ID || ctx
F: GF(EC-Order()), the scalar field
of the prime order subgroup of EC
p: EC-Order()
m: 1
L: as defined in H2C
expand_message: as defined in H2C
bf = HashToScalar(msg)
return bf
~~~

## Using EC multiplicative blinding
Note that DeriveBlindingFactor is compatible with the definitions in [I-D.draft-irtf-cfrg-signature-key-blinding-07].

## Using multiplicative blinding

Such instantations of HDK use elliptic curves (see [Using elliptic curves](#using-elliptic-curves)) and instantiate the following:
Such instantations of HDK [use prime-order groups](#using-prime-order-groups) and instantiate the following:

~~~
def BlindPublicKey(pk, bk, ctx):
Expand All @@ -498,9 +500,9 @@ def Combine(bf1, bf2):
return bf
~~~

## Using EC additive blinding
## Using additive blinding

Such instantations of HDK use elliptic curves (see [Using elliptic curves](#using-elliptic-curves)) and instantiate the following:
Such instantations of HDK use [use prime-order groups](#using-prime-order-groups) and instantiate the following:

~~~
def BlindPublicKey(pk, bk, ctx):
Expand All @@ -519,12 +521,12 @@ def Combine(bf1, bf2):

## Using ECDH shared secrets

Such instantiations of HDK use EC multiplicative blinding (see [Using EC multiplicative blinding](#using-ec-multiplicative-blinding)) and require the following cryptographic construct:
Such instantiations of HDK [use multiplicative blinding](#using-multiplicative-blinding) and require the following cryptographic construct:

- `ECDH`: An Elliptic Curve Key Agreement Algorithm - Diffie-Hellman (ECKA-DH) [TR03111] with elliptic curve `EC`, consisting of the functions:
- `DH`: An Elliptic Curve Key Agreement Algorithm - Diffie-Hellman (ECKA-DH) [TR03111] with elliptic curve `EC`, consisting of the functions:
- CreateSharedSecret(skX, pkY): Outputs a shared secret byte string `Z_AB` representing the x-coordinate of the Element `ScalarMult(pkY, skX)`.

Note that ECDH enables an alternative way of authenticating a key pair `(sk, pk)` without creation or verification of a signature:
Note that DH enables an alternative way of authenticating a key pair `(sk, pk)` without creation or verification of a signature:

~~~
# 1. Unit shares with reader: pk
Expand Down Expand Up @@ -562,47 +564,11 @@ Z_AB = CreateSharedSecret(sk', pkR)
= CreateSharedSecret(sk, ScalarMult(pkR, bf))
~~~

## Using EC digital signatures

Such instantiations of HDK use EC additive blinding (see [Using EC additive blinding](#using-ec-additive-blinding)) and require the following cryptographic construct:

- `DSA`: An EC digital signature algorithm , consisting of the functions:
- Sign(sk, msg): Outputs the signature `(c, r)` created using private signing key `sk` over byte string `msg`.
- Verify(signature, pk, msg): Outputs whether `signature` is a signature over `msg` using public verification key `pk`.

Using these constructs, an example proof of possession protocol is:

~~~
# 1. Unit shares with reader: pk

# 2. Reader computes:
nonce = generate_random_nonce() # out of scope for this spec

# 3. Reader shares with unit: nonce

# 4. Unit computes:
msg = create_message(pk, nonce) # out of scope for this spec
signature = Sign(sk, msg)

# 5. Reader computes:
msg = create_message(pk, nonce) # out of scope for this spec
Verify(signature, pk, msg)
~~~

By design of `BL`, the same proof of possession protocol can be used with blinded key pairs and BlindSign, in such a way that the reader does not recognise that key blinding was used.

An instantiation using `DSA` intantiates the following:

~~~
def BlindSign(sk, bf, msg):
sk' = BlindPrivateKey(sk, bf)
signature = Sign(sk', msg)
return signature
~~~
Note that the value of `ScalarMult(pkR, bf)` does not need to be computed within the secure cryptographic device that protects `sk`.

## Using EC-SDSA signatures

Such instantiations of HDK use EC digital signatures (see [Using EC digital signatures](#using-ec-digital-signatures)) and instantiate the following:
Such instantiations of HDK [use digital signatures](#using-digital-signatures) and [use additive blinding](#using-additive-blinding) and instantiate the following:

- `DSA`: An EC-SDSA (Schnorr) digital signature algorithm [TR03111], representing signatures as pairs `(c, s)`.

Expand All @@ -620,53 +586,50 @@ def BlindSign(sk, bf, msg):
return signature
~~~

## Using ECDSA signatures
## Using P-256

Such instantiations of HDK use EC digital signatures (see [Using EC digital signatures](#using-ec-digital-signatures)) and instantiate the following:
Such instantiations of HDK [use prime-order groups](#using-prime-order-groups) and require the following parameter:

- `DSA`: An ECDSA digital signature algorithm [TR03111].
- `DST`: A domain separation tag for use with HashToScalar.

Due to potential patent claims, this document does not specify an instantiation with multi-party ECDSA signing, even though this would be theoretically possible using EC multiplicative blinding.
Such instantiations instantiate the following:

- `Ns`: 32
- `H`: SHA-256 [FIPS180-4].
- `G`: The NIST curve `secp256r1` (P-256) [SEC2] with:
- `HashToScalar(msg)`: Implemented by computing `hash_to_field(msg, 1)` with the parameters:
- `DST`: `DST`
- `F`: GF(EC-Order()), the scalar field of the prime order subgroup of `G`
- `p`: EC-Order()
- `m`: 1
- `L`: 48
- `expand_message`: `expand_message_xmd` with `H`
- `KEM`: DHKEM(P-256, HKDF-SHA256) [RFC9180].

# Concrete HDK instantiations

The RECOMMENDED instantiation is the HDK-ECDH-P256. This avoids the risk of having the holder unknowingly producing a potentially non-repudiable signature over reader-provided data. Secure cryptographic devices that enable a high level of assurance typically support managing ECDH keys with the P-256 elliptic curve.

## HDK-ECDH-P256

This instantiation uses ECDH for proof of possession (see [Using ECDH shared secrets](#using-ecdh-shared-secrets)) and for `KEM`.
This instantiation [uses P-256](#using-p-256) and [uses ECDH shared secrets](#using-ecdh-shared-secrets).

- `ID`: `"HDK-ECDH-P256-v1"`
- `Ns`: 32
- `H`: SHA-256 [FIPS180-4] with:
- `H(msg)`: Implemented by computing `H(ID || msg)`.
- `EC`: The NIST curve `secp256r1` (P-256) [SEC2]
- `ECDH`: ECKA-DH with curve `EC`
- `KEM`: DHKEM(P-256, HKDF-SHA256) [RFC9180]
- `DST`: `"ECDH Key Blind"`
- `DH`: ECKA-DH with curve `EC`.

## HDK-ECDSA-P256

This instantiation uses ECDSA for proof of possession (see [Using ECDSA signatures](#using-ecdsa-signatures)) and ECDH for `KEM`.
This instantiation [uses P-256](#using-p-256) and [uses digital signatures](#using-digital-signatures).

- `ID`: `"HDK-ECDSA-P256-v1"`
- `Ns`: 32
- `H`: SHA-256 [FIPS180-4] with:
- `H(msg)`: Implemented by computing `H(ID || msg)`.
- `EC`: The NIST curve `secp256r1` (P-256) [SEC2]
- `DSA`: ECDSA with curve `EC`.
- `KEM`: DHKEM(P-256, HKDF-SHA256) [RFC9180]
- `DST`: `"ECDSA Key Blind"`
- `DSA`: ECDSA [TR03111] with curve `G`.

## HDK-ECSDSA-P256

This instantiation uses EC-SDSA for proof of possession (see [Using EC-SDSA signatures](#using-ec-sdsa-signatures)) and ECDH for `KEM`.
This instantiation [uses P-256](#using-p-256) and [uses EC-SDSA signatures](#using-ec-sdsa-signatures).

- `ID`: `"HDK-ECSDSA-P256-v1"`
- `Ns`: 32
- `H`: SHA-256 [FIPS180-4] with:
- `H(msg)`: Implemented by computing `H(ID || msg)`.
- `EC`: The NIST curve `secp256r1` (P-256) [SEC2]
- `DSA`: EC-SDSA-opt (the optimised EC-SDSA) with curve `EC`.
- `KEM`: DHKEM(P-256, HKDF-SHA256) [RFC9180]
- `DST`: `"EC-SDSA Key Blind"`
- `DSA`: EC-SDSA-opt (the optimised EC-SDSA) with curve `G`.

# Application considerations

Expand Down

0 comments on commit 0714c36

Please sign in to comment.