Giter Site home page Giter Site logo

cfrg / draft-irtf-cfrg-opaque Goto Github PK

View Code? Open in Web Editor NEW
98.0 98.0 21.0 4.38 MB

The OPAQUE Asymmetric PAKE Protocol

Home Page: https://cfrg.github.io/draft-irtf-cfrg-opaque/draft-irtf-cfrg-opaque.html

License: Other

Makefile 1.43% Python 86.18% Sage 12.39%

draft-irtf-cfrg-opaque's People

Contributors

afbase avatar aldenml avatar armfazh avatar bytemare avatar cdrubin avatar chris-wood avatar claucece avatar creemama avatar fmarier avatar hugokraw avatar jamesw1892 avatar jansen44 avatar kevinlewi avatar mitar avatar n-l-i avatar nikgraf avatar sc00bz avatar soatok avatar stef avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

draft-irtf-cfrg-opaque's Issues

HMQV key derivation

The following changes the HMQV key derivation to include the session identifier (essentially what the value info is) under the key calculation (the changes are in the last 4 lines below)

Values IKM and info are defined for each protocol:

For HMQV:

  • info = "HMQV keys" | nonceU | nonceS | IdU | IdS

  • IKM = Khmqv

    where Khmqv is computed:

    • by the client: Khmqv = (ePubS * PubS^s)^{ePrivU + u*PrivU}

    • by the server: Khmqv = (ePubU * PubU^u)^{ePrivS + s*PrivS}

    and u = H(ePubU | "user" | info) and s = H(ePubS | "srvr" | info).

Also, in subsection "Instantiation of OPAQUE with HMQV and 3DH", before the KEY DERIVATION heading, add the following note:

[[TODO: Specify that in the login phase, ephemeral DH values need to be
verified to belong to the correct group (via membership tests or cofactor
exponentiation). Same for public keys during the registration phase.
Details of verification depend on the particular group/curve. (What's done in
TLS 1.3?)]]

typos/comments from Eric Crockett

Page 4, second paragraph: “OKI-free” -> “PKI-free”

In that same paragraph "it works for RSA" should be replaced with a better explanation. The point is that SRP requires a ring: it mixes additions and multiplications. It does not work over plain elliptic curves.

Page 8, section 2.1. DH-OPEF -> DH-OPRF

Allow OPRF context creation with external key

This is more of an issue with the OPRF draft, but noting it here for now. The OPRF context constructor does not allow creation of a server with an existing key, which makes the OPRF credential response generation function somewhat annoying to implement.

Nail down AKE instantiations

TLS 1.3 is the SIGMA-I instantiation, so I think we should drop this from the OPAQUE document. It's redundant, and will likely cause confusion between people who want to choose between one or the other.

cc @kevinlewi

uint24 in ProtocolMessage

ProtocolMessage defines the length field to be of type uint24, i understand this is to handle messages that are composed of a few max 2^16 long parts, and possibly to conserve bandwidth? is it possible to make this 32bit which is a native and widely used size instead of 24bits.

Specify harden parameters

Clients need a way to recover credential information during registration. So we should either (a) fix some Harden parameters, or (b) have servers send these during the registration and authentication flows.

@kevinlewi, what do you think?

Derive fresh nonces at envelope creation

The nonce used in envelope encryption should not be derived from RwdU but rather chosen freshly at random at the time of encryption (envelope creation) and be stored (and sent) as part of the envelope. This avoids reusing the same encryption stream for encrypting two different plaintexts.

Add common configurations for OPAQUE

This basically specifies different configurations, where each configuration identifies the OPRF, RKR-AEAD, and MHF algorithm. For example, one configuration might be DH-OPRF with OPRF-curve448-HKDF-SHA512-ELL2-RO, CTR+HMAC with AES-256 and HMAC-SHA256, and scrypt (with reasonable parameters).

Should the nonce length be a parameter?

It's currently set 32 bytes, which may be too much (?) in some circumstances. However, adding yet another parameter that applications must choose is not great.

Swap 3DH label strings around

Currently, the 3DH key schedule computes two MAC and two encryption keys, as follows:

Km2 = HKDF-Expand-Label(handshake_secret, "client mac", "", Hash.length)
Km3 = HKDF-Expand-Label(handshake_secret, "server mac", "", Hash.length)
Ke2 = HKDF-Expand-Label(handshake_secret, "client enc", "", key_length)
Ke3 = HKDF-Expand-Label(handshake_secret, "server enc", "", key_length)

Km2 is the key used to compute the server's MAC in KE2:

KE2 = credential_response, nonceS, info2, epkS, Einfo2, MAC(Km2; transcript2),

Using the label "client mac" to derive Km2 seems backwards. Let's swap them around, like so:

Km2 = HKDF-Expand-Label(handshake_secret, "server mac", "", Hash.length)
Km3 = HKDF-Expand-Label(handshake_secret, "client mac", "", Hash.length)
Ke2 = HKDF-Expand-Label(handshake_secret, "server enc", "", key_length)
Ke3 = HKDF-Expand-Label(handshake_secret, "client enc", "", key_length)

cc @hugokraw, @kevinlewi

rename Evaluate() to Contribute()

since github does not support reviewing markdown documents i'm submitting this as an issue:

The OPRF primitive defines a

Evaluate(k, M): Evaluate input M using private key k.

function, semantically i think it makes more sense to call this function Contribute as this conveys better what is happening, Evaluate() is less specific to the purpose of what is happening here.

Investigate OPRF generality

We currently rely on a GenerateScalar function from the OPRF, which might not be a thing for OPRFs that are not based on Diffie-Hellman. We should consider how we might generalize this here, or perhaps in the OPRF document itself.

lengths of elements

Who, when and how determines the length of elements to be generated or received. For example, how does the client know what the value of Nk should be. More significant how does the client know Nk or len(pt) when receiving the envelope?

On a related note, for a derivation like
SK, Km2, Km3, Ke2, Ke3 = HKDF(salt=0, IKM, info, L)
we need to assume that the client knows how to parse the key stream correctly and uniquely hence it needs to know the lengths of each key. This is also needed even if we compute a separate HKDF-Expand for each value (since Expand requires to define a length value). How does the client know these values, are these determined by the specific algorithms or ciphersuite ? Should this information be part of the information authenticated by the envelope or some other mechanism?
How does TLS 1.3 deals with this, namely, how it communicates and authenticates the ciphersuite/algorithms/version?

Clarify server trust

Should we clarify how much trust we place in the server? For example, since OPAQUE stores encrypted keys in the server, and that same server has the OPRF secret key, it could in theory do a dictionary attack and recover the private key for each user. This is pretty nonsensical, but I think it does highlight that OPAQUE assumes the server is honest-but-curious, rather than entirely malicious.

This is sort of fundamental, but some folks might miss it.

OPRF evaluation output

The output of Evaluate in the OPRF draft is an Evaluation object, which has both a blinded and signed element, as well as a proof. We should either adopt that type here, or make it clear in our notation that the output of Evaluate is just the blinded and signed element.

Note that this affects what's carried in a RequestMetadata struct.

Omitting idU parameter in RegistrationRequest and CredentialRequest messages

The idU parameter is not used by the server when receiving the RegistrationRequest and CredentialRequest messages from the client. Can this parameter be omitted from the specification of these messages?

In theory, the server does need some "username" equivalent in order to look up the client's record, so this information does need to be sent, but I don't think it should be included in the OPAQUE messages, since it has no function within OPAQUE other than to set/retrieve the appropriate password file.

Presumably, any wrapper protocol which uses OPAQUE will not want to look into the bytes of the OPAQUE messages in order to figure out what the username is.

Typo: nonce appears twice

In line
export_key = HKDF-Expand(RwdU, concat(nonce, "ExportKey", nonce), Nk)
nonce appears twice

Reconsider "cost" details section

The "cost" details are written assuming a traditional DH-based KE protocol. Should we try to generalize this, e.g., to cover KEM-based protocols? Moreover, the cost details might not age well as TLS 1.3 develops and possibly moves away from signatures, via, e.g., semi-static DH. Or we might just remove this section entirely.

Clarify KDF(Expand) and MAC requirements

Future implementers may wish to replace HKDF-Expand and HMAC with their own (read:faster?) variants, so we should make clear the rationale for using these. Per the analysis, we require random-key robustness from HMAC, which is not something all MACs provide. (GMAC and poly1305 don't, for example.) HKDF-Expand could possibly be replaced by a different variable-length output PRF.

Consider adding a registry

The configurations are rather loosely defined. A registry that allows one to encode an entire configuration (AKE, OPRF, MHF, etc) could be useful.

On including pkU in the envelope

Add a note: pkU is often not needed by the client to run the key exchange stage in which case it can be omitted from the envelope and not sent from server to client in the online stage. In particular, this is the case for the three instantiations here: 3DH, HMQV and SIGMA.

rename StoreUserRecord to indicating the finalization instead of optional persistence

Just as we dropped the ProtocolMessages part, for the protocol it might be not necessary to call the function StoreUserRecord. For instance my implementation does not care about any kind of persistence or transport of the outcome of the protocol. It might be that the use-case does not need the storage of the user record, for example by just keeping it in memory, or the record might be further processed before storage. Thus i propose to rename the function to FinalizeUserRecord instead.

Why does FinalizeRequest take in idU as a parameter?

According to this, idU is used to construct FinalizeRequest, despite it only being applicable if the application decides to include it in the Credentials struct: > "Applications may optionally include

pkU, idU, or idS in the Credentials.cleartext_credentials structure, or in
Credentials.secret_credentials if secrecy of these values is desired."

But if this is the case, then why not also make idS and pkU parameters to FinalizeRequest as well?

Same goes for RecoverCredentials. Either they should take in all of these optional parameters as inputs, or they should not include any of them.

XOR-based encryption for Ke2 and Ke3 encryption keys in AKE?

From the definition of Ke2 and Ke3, the encryption keys used to encrypt the optional Einfo parameters in the AKE section, it seems like the application would need to pick an encryption algorithm for OPAQUE to use here.

Can we avoid this selection and simply use an XOR-based one-time pad for encryption here (is this secure)? Thus, instead of setting key_length to be a fixed constant, it would simply be the length of Einfo2 and Einfo3.

Validate ephemeral key shares

Specify that in the login phase, ephemeral DH values need to be verified to belong to the correct group (via membership tests or cofactor exponentiation). Same holds for public keys during the registration phase. Details of verification depend on the particular group/curve.

Private key encodings

We might use PKCS#8 as an encoding for credential private keys, or we might use language that suggests this is specific to each instantiation.

Typo in 3DH key derivation

The key K3dh needs to computed by the server as
K3dh = ePubU^ePrivS | ePubU^PrivS | PubU^ePrivS
The current draft inverts the order between the last two elements making it inconsistent with the way the client computes the key.
(Reported by Kevin Lewi)

credential_lists in CreateRegistrationResponse

in this section https://github.com/cfrg/draft-irtf-cfrg-opaque/blob/master/draft-irtf-cfrg-opaque.md#registration-messages

struct {
    opaque data<0..2^16-1>;
    opaque pkS<0..2^16-1>;
    CredentialType secret_types<1..255>;
    CredentialType cleartext_types<0..255>;
} RegistrationResponse;

Specifies

  • secret_credentials_list, a list of CredentialType values clients should include in the secret_credentials list of their Credentials structure
  • cleartext_credentials_list, a list of CredentialType values clients should include in the cleartext_credentials list of their Credentials structure

what if a CredentialType is in both of these lists? Why not pack this information in 10 bits, where each CredentialType has 2 bits for signalling:

  NotPackaged = 0,  // field is not packaged in envelope
  InSecEnv = 1,        // field is encrypted
  InClrEnv = 2          // field is plaintext, but authenticated

Clarifying optional versus required parameters in the AKE section

In this section on AKE, we should clear up exactly which parameters are required and which are optional. Then we can also work towards defining a wire format for these AKEs if necessary.

A couple of concrete questions:

  1. Can we simply set idU = static pkU and idS = static pkS?
  2. Can we remove mention of all of the following: info1*, info2*, Einfo2*, info3*, Einfo3*?

note regarding omitting skU from envelope and deriving it from rwd instead

in the source there's a commented out part ## Envelope considerations which mentions that not even skU needs to be included in the credentials wrapped in the envelope, instead skU can be derived from rwd. there's a note that this part should be "brought back after updating". if this is indeed the case, do not forget to change

Applications MUST include skU in secret_credentials
in the {#protocol-messages} section.

id missing in CredentialRequest

in the section https://github.com/cfrg/draft-irtf-cfrg-opaque/blob/master/draft-irtf-cfrg-opaque.md#authenticated-key-exchange-messages CredentialRequest is defined as:

struct {
    opaque data<1..2^16-1>;
} CredentialRequest;

and right below that is this line:

data : An encoded element in the OPRF group. See {{I-D.irtf-cfrg-voprf}} for a description of this encoding.
and in the https://github.com/cfrg/draft-irtf-cfrg-opaque/blob/master/draft-irtf-cfrg-opaque.md#createcredentialresponserequest section it is even referred to as:

1. (kU, envU, pkU) = LookupUserRecord(request.id)

even though trivial, it might make sense to include id in the CredentialRequest structure definition.

parsing of envelope when ct/pt are variable length

At the end of the #protocol-messages section is a description of the envelope structure as seen here:

OPAQUE uses an `Envelope` structure to encapsulate an encrypted `Credentials` structure.
It is encoded as follows.

~~~
struct {
  opaque nonce[32];
  opaque ct<1..2^16-1>;
  opaque auth_data<0..2^16-1>;
  opaque auth_tag<1..2^16-1>;
} Envelope;
~~~

nonce
: A unique 32-byte nonce used to protect this Envelope.

ct
: Encoding of encrypted and authenticated credential extensions list.

auth_data
: Encoding of an authenticated credential extensions list.

auth_tag
: Authentication tag protecting the contents of the envelope.

as an implementer of opaque (see here https://github.com/stef/libsphinx/blob/master/src/opaque.c) i wonder how to parse this structure when both fields might be of variable length. In such a case it is useful to have the lengths included in the auth_data section at known offsets of the envelope. hence i propose to move the auth_data section infront of the ct section, either at the very beginning before the nonce, or between the nonce and the ct, in both cases an instantiation of the protocol can decide to include the lengths at known offsets and will be able to parse the envelope, even if this means that these lengths are used before they are authenticated.

KdKey rationale

We need to add the rationale for KdKey somewhere. Can use the following as a basis:

The main use case I have in mind is retrieving a non-OPAQUE encrypted credential. Namely, expanding the use of OPAQUE with a credential-retrieval functionality. You could always put additional stuff in the envelope but I would prefer to restrict the envelope with its OPAQUE-specific functionality. In addition, having a separate encrypted credential can achieve several properties: allowing the server to send it only after the user authenticated; send it under the session key with forward secrecy; allowing the addition of a credential to the user's record after registration; allowing the use of non-RKR encryption for credential encryption; and just giving better extensibility, flexibility and separation from the core OPAQUE protocol.

What is an OPRF keypair?

in the Cryptographic primitives section there is this sentence:

We also assume the existence of a function KeyGen, which generates an OPRF private and public key.

i'm sorry, but what does that mean? The notion of a keypair in the OPRF context makes no sense to me.

Using HKDF-Expand in deriving KEYS

Instead of KEYS = HKDF(salt=0, IKM=k, info="EnvU", Length=L1+L2+L3) one could do
KEYS = HKDF-Expand(key=k, info="EnvU", Length=L1+L2+L3)
which makes more sense since k is already a pseudo random key, we would only need to specify that k is the length of an HMAC key.

protocol messages

in the specification there is a part which defines {#protocol-messages}:

enum {
    registration_request(1),
    registration_response(2),
    registration_upload(3),
    credential_request(4),
    credential_response(5),
    (255)
} ProtocolMessageType;

struct {
    ProtocolMessageType msg_type;    /* protocol message type */
    uint24 length;                   /* remaining bytes in message */
    select (ProtocolMessage.msg_type) {
        case registration_request: RegistrationRequest;
        case registration_response: RegistrationResponse;
        case registration_upload: RegistrationUpload;
        case credential_request: CredentialRequest;
        case credential_response: CredentialResponse;
    };
} ProtocolMessage;

in our implementation at https://github.com/stef/libopaque we omitted implementing this, for the following reasons:

  • this is depending on how an application is using this protocol, it might not be necessary to wrap protocol messages in such frames, for example because the app already has it's own framing, or different ways to communicate this.
  • parsing any kind of input from possible adversaries should be done higher up the stack, where possibilities are richer to do so in memory safe ways or by implementing language security mechanisms to do so.

libopaque does however implement the credential and envelope structures.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.