Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support DID Auth #24

Closed
mrinalwadhwa opened this issue Feb 4, 2019 · 15 comments
Closed

Support DID Auth #24

mrinalwadhwa opened this issue Feb 4, 2019 · 15 comments

Comments

@mrinalwadhwa
Copy link
Member Author

This provides crypto_box for authenticated encryption
https://godoc.org/golang.org/x/crypto/nacl/box

@mrinalwadhwa
Copy link
Member Author

@mrinalwadhwa
Copy link
Member Author

c = crypto_box(m,n,pk,sk);

The crypto_box function encrypts and authenticates a message m using the sender's secret key sk, the receiver's public key pk, and a nonce n. The crypto_box function returns the resulting ciphertext c.

m = crypto_box_open(c,n,pk,sk)

The crypto_box_open function verifies and decrypts a ciphertext c using the receiver's secret key sk, the sender's public key pk, and a nonce n. The crypto_box_open function returns the resulting plaintext m.

@mrinalwadhwa
Copy link
Member Author

Distinct messages between the same {sender, receiver} set are required to have distinct nonces. For example, the lexicographically smaller public key can use nonce 1 for its first message to the other key, nonce 3 for its second message, nonce 5 for its third message, etc., while the lexicographically larger public key uses nonce 2 for its first message to the other key, nonce 4 for its second message, nonce 6 for its third message, etc. Nonces are long enough that randomly generated nonces have negligible risk of collision.

There is no harm in having the same nonce for different messages if the {sender, receiver} sets are different. This is true even if the sets overlap. For example, a sender can use the same nonce for two different messages if the messages are sent to two different public keys.

@mrinalwadhwa
Copy link
Member Author

Proposed Design:

device-service-auth
device-device-auth

@mrinalwadhwa
Copy link
Member Author

Authenticated Encryption in the Public-Key Setting: Security Notions and Analyses
https://eprint.iacr.org/2001/079

@mrinalwadhwa
Copy link
Member Author

Defective Sign & Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML
http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html

@mrinalwadhwa
Copy link
Member Author

I suspect these proposed designs don't prove to the initiator of the request to connect (step 2) the identity of the other party:

Does (by step 7) device know it is talking to the service it expect? I suspect no.
device-service-auth

Does (by step 7) device A know it is talking to device B? I suspect no.
device-device-auth

@mrinalwadhwa
Copy link
Member Author

Step 2, I suspect should also include an auth encrypted challenge
Step 4 should include a response to this challenge

This also implies 5 needs to happen before 2

@mrinalwadhwa
Copy link
Member Author

New Proposed design:

device-service-auth

device-device-auth

@malnick
Copy link
Contributor

malnick commented Mar 26, 2019

#41

This was referenced Mar 26, 2019
@WildCryptoFox
Copy link

WildCryptoFox commented Sep 30, 2019

@mrinalwadhwa If these "Auth Encrypt" packets are crypto_box(m, n, static public key, static secret key), this protocol is insecure against Key Compromise Impersonation and lacks Forward Secrecy.

An active attacker who learns either side's secret key can mount a MiTM attack, thus reading and manipulating messages in either direction. A passive attacker who records the transcript and later learns either party's secret key can recover all encrypted messages.

If you're maintaining session state, please use a KCI and FS secure key exchange such as Signal's Triple-DH, then use secret_box.

K = KDF(dh(ae, be) | dh(ae, bi) | dh(be, ai))

This yields both stronger security and faster performance as the asymmetric operations are only necessary during the handshake, not any further messages, unless the session lives long enough to consider key rotation. If the underlying transport already provides order, you may use Rogaway's OAE2 CHAIN construction (instead of secret_box) with an MRAE (such as SIV or HCTR). If the underlying transport does not ensure consistent order, you may still use OAE2's STREAM construction, which asks for at least an nAE but an MRAE as listed above is safer. Alternatively if you're set on libsodium, it somewhat recently learned about streams.

Even if we ignore Key Compromises, an attacker who sends garbage as their first packet will cause the receiver to perform the expensive asymmetric operations (DH) for each connection an attacker can open. If the responder is under load, consider using HIPv2's puzzles to avoid computation and state based denial of service attacks. I recommend just using HIPv2 as your authentication between hosts. Alternatively take what it has specified to influence your protocol design.

I'm planning to implement both HIPv2 and a lightweight UDP alternative with some additional goals; both in Rust.

@mrinalwadhwa
Copy link
Member Author

@james-darkfox Thank you for that detailed feedback ❤️

The above issue/discussion is somewhat stale. We realized many of these weaknesses some months ago and spent the past few months researching and discussing this protocol design internally.

The current draft of the key agreement protocol is roughly C(2e,2s) described here which uses DH with ephemeral keys and gets us Forward Secrecy (but not KCI protection). Signal's X3DH has been part of the on going discussion however we haven't formed an opinion yet on one-time prekeys within the contest of ockam's overall design.

We're also leaning on AEAD_AES_128_GCM_SIV as the AEAD construction after we have key agreement. We've been looking into the effort needed to implement it with the various hardware we want to support. Which, at least theoretically, seems feasible.

Greatly appreciate your post, I will try to publish our draft design over the next few weeks and would love to get more feedback.

@WildCryptoFox
Copy link

WildCryptoFox commented Sep 30, 2019

@mrinalwadhwa Signal's extension to 3DH only weakens the handshake for the convenience of bootstrapping asynchronous messaging; it takes away only one message at the cost of distributing and managing the single use prekeys and a 4th DH call. IMO it is unnecessary.

KCI resistance is critical. For a flexible protocol the core handshake should do nothing more than anonymous-DH to establish the session's key and to pass a session-bound token to the application for arbitrary authentication mechanisms of its choice. 3DH is cheap for mutual static-key authentication; (only beaten by schemes designed for stronger adversaries). OPAQUE for password authentication, optionally composed with a secure two-factor authentication protocol.

AES-128-GCM-SIV relies only on AES and CLMUL acceleration to be efficient. If you need a fallback for when they are not available; you may want to look into HS1-SIV (chacha20 based SIV), HPolyC (chacha20 + aes-soft + NH/poly1305 hybrid ADU), or a few others.

Regarding the DID -> public key lookup and locator meta; I recommend sending the public keys without relying on online access to a third party registry for the lookup. The identity can optionally point to a third party to check for revocation; that third party may be your blockchain or it may be an entity under the user's control.

Stronger symmetric credentials may be used with optional identity-bounds for authorization. Google's Macaroons rely only on a keyed-hash function and a single bit per credential a server mints. Macaroons are designed for single entities to mint and verify; while the clients can delegate and provision their authorities without identities and without having to talk to the server. I've noticed you're interested in object capabilities; macaroons are a great way to implement ocaps.

I'm happy to help. Ping me when you publish the next draft and I'll take a look. Are you on IRC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants