Services/Sync/P2P Key Exchange And Rotation: Difference between revisions
(eXfio Peer v2 Final) |
(Revised eXfio Peer v2 to use digest of authorised client state) |
||
| Line 104: | Line 104: | ||
AEs AEp, BEp | AEs AEp, BEp | ||
BIp | BIp | ||
BEp = BE | BEp = BE[X]p, X ∈ {1..n} | ||
S = KDF(3DHE(AIs, AEs, BIp, BEp)) | S = KDF(3DHE(AIs, AEs, BIp, BEp)) | ||
t2 BIs | t2 BIs | ||
BEs ∈ BE | BEs ∈ BE[X]s, X ∈ {1..n} | ||
AIp | AIp | ||
AEp | AEp | ||
| Line 152: | Line 152: | ||
</pre> | </pre> | ||
=== eXfio Peer v1 === | === Authorisation Protocol === | ||
==== eXfio Peer v1 ==== | |||
'''IMPORTANT:''' If the attacker has full access to the storage, i.e. a hostile systems administrator, '''and''' knows the password a '''man-in-the-middle (MITM) attack is possible'''. At this time there is an implicit (and quite possibly incorrect) assumption that the systems administrator does not know the password. See [[#eXfio Peer v2|version 2]] of protocol for improved handling of this risk. | |||
When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below. | When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below. | ||
| Line 164: | Line 168: | ||
# Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved' | # Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved' | ||
# Client A: On authorisation declined no action taken | # Client A: On authorisation declined no action taken | ||
<pre> | |||
Alice (Client A) Eve (Public) Bob (Client B) | |||
t0 AIs AIp, BIp BIs | |||
BE{1..n}p BE{1..n}s | |||
t1 AIs AIp, BIp | |||
AEs AEp, BEp | |||
BIp AD | |||
BEp = BE[X]p, X ∈ {1..n} | |||
S = KDF(3DHE(AIs, AEs, BIp, BEp)) | |||
VC = RANDOM() | |||
AD = DIGEST(VC + DIGEST(password)) | |||
t2 BIs | |||
BEs ∈ BE[X]s, X ∈ {1..n} | |||
AIp | |||
AEp | |||
AD | |||
S = KDF(3DHE(BIs, BEs, AIp, AEp)) | |||
VC = <user input> | |||
BD = DIGEST(VC + DIGEST(password)) | |||
Verified = (AD == BD) | |||
</pre> | |||
'''Notes:''' | '''Notes:''' | ||
* The authcode is a random alphanumeric string which needs to be entered on the authorising device to verify the authenticity of the request. If the authcode is entered correctly then a man-in-the-middle attack is highly unlikely. | * The authcode is a random alphanumeric string which needs to be entered on the authorising device to verify the authenticity of the request. If the authcode is entered correctly then a man-in-the-middle attack is highly unlikely. | ||
| Line 198: | Line 226: | ||
</pre> | </pre> | ||
=== eXfio Peer v2 === | ==== eXfio Peer v2 ==== | ||
Version 2 of the eXfio Peer protocol improves the protection against a man in the middle (MITM) attack, while also simplifying the protocol. Importantly the starting assumption is that an attacker has full access to the storage, i.e. a hostile systems administrator, '''and''' knows the password. Fortunately an elegant means to mitigate against this threat is, rather than introducing a random authcode, to instead generate the authcode using a digest of the | Version 2 of the eXfio Peer protocol improves the protection against a man in the middle (MITM) attack, while also simplifying the protocol. Importantly the starting assumption is that an attacker has full access to the storage, i.e. a hostile systems administrator, '''and''' knows the password. Fortunately an elegant means to mitigate against this threat is, rather than introducing a random authcode, to instead generate the authcode using a digest of the state, including time and a salt value. | ||
The time needed for an attacker to generate an ECDH key and salt that results in a collision with the authcode can be made prohibitive, by using KDF designed to slow such attacks down. And finally to further protect against this attack a time-based one-time password (TOTP) authcode could optionally be used thus requiring an attacker to generate a series of collisions. | |||
When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below. | When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below. | ||
| Line 205: | Line 235: | ||
# Client A: Create client record with status of 'pending' | # Client A: Create client record with status of 'pending' | ||
# Client A: Send ClientAuthRequestMessage to existing authorised clients using 3DHE, i.e. Client B | # Client A: Send ClientAuthRequestMessage to existing authorised clients using 3DHE, i.e. Client B | ||
# Client A: Display authcode generated from the | # Client A: Display authcode generated from the state, i.e. digest(salt, time, authorised client keys) | ||
# Client B: User enters authcode when prompted to approve and verify request. Alternatively reject request. | # Client B: User enters authcode when prompted to approve and verify request. Alternatively reject request. | ||
# Client B: On authorisation approved send ClientAuthResponseMessage with sync key | # Client B: On authorisation approved send ClientAuthResponseMessage with sync key | ||
| Line 212: | Line 242: | ||
# Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved' | # Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved' | ||
# Client A: On authorisation declined no action taken | # Client A: On authorisation declined no action taken | ||
<pre> | |||
Alice (Client A) Eve (Public) Bob (Client B) Charlie (Client C) | |||
t0 AIs AIp, BIp, CIp BIs CIs | |||
BE{1..n}p, BE{1..n}s CE{1..n}s | |||
CE{1..n}p | |||
t1 AIs AIp, BIp, CIp | |||
AEs AEp, BEp | |||
BIp AS, AT | |||
BEp = BE[X]p, X ∈ {1..n} | |||
S = KDF(3DHE(AIs, AEs, BIp, BEp)) | |||
AS = RANDOM() | |||
AT = t1 | |||
CIp | |||
VD = DIGEST(AS, AT, AIp, BIp, CIp...) | |||
VC = TRUNCATE(AD) | |||
t2 BIs | |||
BEs ∈ BE[X]s, X ∈ {1..n} | |||
AIp | |||
AEp | |||
S = KDF(3DHE(BIs, BEs, AIp, AEp) | |||
AS | |||
AT | |||
CIp | |||
VD = DIGEST(AS, AT, AIp, Bip, CIp,...) | |||
VC = <user input> | |||
Verified = (VC == TRUNCATE(VD)) | |||
</pre> | |||
And optionally using TOTP verification | |||
<pre> | |||
tn Td = tn - AT Td = tn - AT | |||
VC = TOTP(VD, Td) VC = <user input> | |||
Verified = (VC == TOTP(VD, Td)) | |||
</pre> | |||
'''Notes:''' | '''Notes:''' | ||
* The authcode is a digest of the | * The authcode (VC) is a digest of the state at the time the ClientAuthRequestMessage was sent. This code needs to be entered on the authorising device to verify the authenticity of the request. If the authcode displayed by Client A matches the digest of the state generated independently on Client B then a man-in-the-middle attack is highly unlikely. | ||
* Optionally a time-based one-time password (TOTP) algorithm could be used to generate the authcode further strengthening against a MITM attack. However this would require the user to be in possession of both devices at the same time, which largely negates the benefits of the key exchange being asynchronous. | * Optionally a time-based one-time password (TOTP) algorithm could be used to generate the authcode further strengthening against a MITM attack. However this would require the user to be in possession of both devices at the same time, which largely negates the benefits of the key exchange being asynchronous. | ||
| Line 221: | Line 290: | ||
{ | { | ||
salt: "Salt value for digest", | salt: "Salt value for digest", | ||
time: "Time value for TOTP | time: "Time value for digest and optionally TOTP" | ||
} | } | ||
</pre> | </pre> | ||
Revision as of 09:33, 18 October 2015
Support secure and intuitive key exchange and key rotation between Weave Sync clients.
Over a number of versions of Weave Sync different key exchange mechanisms have been implemented, however to date they have had significant weaknesses in either security or user experience (UX) or both. This wiki describes (yet another) proposal which attempts to find the balance between (good enough) security and an intuitive UX.
Overview
The objective of the P2P Key Exchange protocol is to securely transfer a secret key to a new weave client during registration. Importantly, as such it is only relevant for Weave Sync versions which utilise a randomly generated secret key, namely Weave Sync v1.1 API/v5 Data and the pairing extension of Weave Sync v1.5 API/v5 Data.
Arguable the J-PAKE based key exchange protocol used in Weave Sync v1.1/v5 already achieves this, however as discussed below a significant weakness is that it requires three round trips to complete and thus requires both the new and an already registered client to be online concurrently and with good connectivity. Also Weave Sync v1.1/v5, as currently implemented, does not support rotation of the secret key.
The P2P Key Exchange Protocol aims to address these issues by implementing a 3DHE based key exchange protocol with pre-generated ephemeral keys, allowing the key exchange to be completed asynchronously and in a single round trip. The same technique can also be leveraged for key rotation, although in this case only a single message needs to be sent by the initiating client, a response is not required but can be used to indicate success. The key exchange is also implemented within Weave Sync storage meaning no changes are required to the Weave Sync registration API to implement.
The P2P Key Exchange protocol is inspired by TextSecure.
'Pros'
- User only needs to know username and password to register device
- Secret key is randomly generated
- Secret key does not leave device
- Key exchange is implemented using Weave Sync storage and thus is compatible with both Weave Sync v1.1/v5 and the Weave Sync v1.5/v5 pairing extension
'Cons'
- Registering additional devices after the first requires access to an already registered device
- Performing key exchange within Weave Sync storage may have security ramifications.
Existing Weave Sync Key Exchange Implementations
Passphrase (v1.1 API/v3 Data)
The Passphrase implementation derives a secret key from a user selected passphrase independent of the account password.
'Pros'
- Registering additional devices does not require access to an already registered device
- Secret key does not leave device
'Cons'
- User needs to know passphrase in addition to username and password to register device
- Secret key is only as secure as passphrase
Easy Setup (v1.1 API/v5 Data)
The Easy Setup implementation generates a secret key on account registration and for additional clients performs key exchange using J-PAKE.
'Pros'
- User only needs to know username and password to register device
- Secret key is randomly generated
- Secret key does not leave device
'Cons'
- Registering additional devices after the first requires access to an already registered device
- J-PAKE key exchange requires three round trips and hence both devices must be connected concurrently and with good connectivity
One Password (v1.5 API/v5 Data)
Like the Passphrase implementation, the One Password (onepw) implementation derives a secret key from a user selected passphrase, however a single password/passphrase is used for both authentication and key derivation to address useability issues with maintaining independent passwords/passphrases.
'Pros'
- User only needs to know username and password to register device
- Registering additional devices does not require access to an already registered device
'Cons'
- Secret key is derived from password which is partially known by authentication server
- Secret key is only as secure as password
- Registration and authentication protocol significantly more complex
Design
User Stories
- Information is secure: As a user I want my data to be secure, hence the secret key must be secure
- Easy to register: As a user I want to be able to register a new device with only the username and password
- Easy to change key: As a user I want to be able to change the secret key and de-register a device in the case that it has become compromised, i.e. device lost or stolen
Desired Behaviour
1) Register a device using only username and password
2) If verification is required this must be no more than one additional step and involve no more than one additional device
3) A registered device can change the sync key and re-distribute it to other selected devices with minimal actions, i.e. see (2) above.
Implementation
Note for the purposes of describing the technical implementation the term client will be used in place of device and similarly authorised/unauthorised will be used in place of registered/unregistered.
What Needs To Be Done
- Implement messaging protocol to support sending of messages between both authorised (registered) and unauthorised (unregistered) clients (devices)
- Implement registration protocol to authorise a new client (device) and exchange the secret key for an existing Weave Sync account
- Implement key rotation protocol to change the secret key and re-distribute to other authorised (registered) clients (devices)
Messaging Protocol
A bonus of using the 3DHE key exchange is that it naturally abstracts in to a generalised messaging protocol that can be used to send an arbitrary messages encrypted with the session key derived during the 3DHE key exchange. In addition perfect forward secrecy can be achieved using axolotl key ratcheting as used in the Text Secure application. Although this is not implemented at this stage it presents an opportunity to extend functionality to include peer to peer key management that can be shared between multiple devices.
Protocol Sequence
- Each client publishes an identity key (AI, BI) and a set of ephemeral keys (AE{1..n}, BE{1..n})
- Client A generates a new ephemeral key (AE) and randomly selects one of client B's ephemeral keys (BE). Using 3DHE and a KDF, client A generates the shared secret (S) then sends message including own ephemeral key (AE) and identifier for client B's ephemeral key (X). Body can be encrypted with shared secret.
- Client B receives client A's ephemeral key (AE) and identifier for own ephemeral key (BE). Using 3DHE and a KDF, client B generates the shared secret (S) and can then decrypt the message body.
- Both client A and client B can now continue to communicate using the shared secret (S) as a session key
Alice (Client A) Eve (Public) Bob (Client B)
t0 AIs AIp, BIp BIs
BE{1..n}p BE{1..n}s
t1 AIs AIp, BIp
AEs AEp, BEp
BIp
BEp = BE[X]p, X ∈ {1..n}
S = KDF(3DHE(AIs, AEs, BIp, BEp))
t2 BIs
BEs ∈ BE[X]s, X ∈ {1..n}
AIp
AEp
S = KDF(3DHE(BIs, BEs, AIp, AEp))
EphemeralKey JSON
{
keyid: "id of ephemeral key",
key: "ephemeral public key"
}
Client JSON
{
version: "version of client record",
clientid: "id of client",
name: "name of client",
key: "identity public key",
ekeys: [EphemeralKey1, EphemeralKey2, ..., EphemeralKeyn],
status: "indicates if client is authorised, i.e. 'authorised' or 'pending'",
authlevel: "will this client accept messages for unauthorised clients, i.e. 'all' indicates all clients, 'authorised' indicates authorised clients only"
hmac: "HMAC of all other client fields"
}
Message JSON
{
version: "version of message record",
srcclientid: "id of sender",
srckeyid: "id of sender's ephemeral key",
srckey: "sender's ephemeral key (optional after first message, i.e. sequence > 1)",
dstclientid: "id of receiver",
srckeyid: "id of receiver's ephemeral key",
sequence: "sequence of this message in session",
type: "message type",
content: "message content"
hmac: "HMAC of all other message fields"
}
Authorisation Protocol
eXfio Peer v1
IMPORTANT: If the attacker has full access to the storage, i.e. a hostile systems administrator, and knows the password a man-in-the-middle (MITM) attack is possible. At this time there is an implicit (and quite possibly incorrect) assumption that the systems administrator does not know the password. See version 2 of protocol for improved handling of this risk.
When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below.
- Client A: Create client record with status of 'pending'
- Client A: Send ClientAuthRequestMessage to existing authorised clients, i.e. Client B, including authcode digest (ClientAuthVerifier)
- Client A: Display authcode to user
- Client B: User enters authcode when prompted to approve and verify request. Alternatively reject request.
- Client B: On authorisation approved send ClientAuthResponseMessage with sync key
- Client B: On authorisation declined send ClientAuthResponseMessage with auth fail code
- Client A: Poll for authorisation response
- Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved'
- Client A: On authorisation declined no action taken
Alice (Client A) Eve (Public) Bob (Client B)
t0 AIs AIp, BIp BIs
BE{1..n}p BE{1..n}s
t1 AIs AIp, BIp
AEs AEp, BEp
BIp AD
BEp = BE[X]p, X ∈ {1..n}
S = KDF(3DHE(AIs, AEs, BIp, BEp))
VC = RANDOM()
AD = DIGEST(VC + DIGEST(password))
t2 BIs
BEs ∈ BE[X]s, X ∈ {1..n}
AIp
AEp
AD
S = KDF(3DHE(BIs, BEs, AIp, AEp))
VC = <user input>
BD = DIGEST(VC + DIGEST(password))
Verified = (AD == BD)
Notes:
- The authcode is a random alphanumeric string which needs to be entered on the authorising device to verify the authenticity of the request. If the authcode is entered correctly then a man-in-the-middle attack is highly unlikely.
ClientAuthVerifier JSON
{
innersalt: "Salt value for inner hash, i.e. hash(password)
salt: "Salt value for outer hash
digest: "hash(authcode + hash(password))
}
ClientAuthRequestMessage JSON
{
clientid: "id of client",
name: "name of client",
auth: ClientAuthVerifier
}
ClientAuthResponseMessage JSON
{
clientid: "id of client",
name: "name of client",
status: "okay|fail",
message: "authorisation approved|authorisation rejected",
synckey: "Master key for Weave Sync account (required if status 'okay')"
}
eXfio Peer v2
Version 2 of the eXfio Peer protocol improves the protection against a man in the middle (MITM) attack, while also simplifying the protocol. Importantly the starting assumption is that an attacker has full access to the storage, i.e. a hostile systems administrator, and knows the password. Fortunately an elegant means to mitigate against this threat is, rather than introducing a random authcode, to instead generate the authcode using a digest of the state, including time and a salt value.
The time needed for an attacker to generate an ECDH key and salt that results in a collision with the authcode can be made prohibitive, by using KDF designed to slow such attacks down. And finally to further protect against this attack a time-based one-time password (TOTP) authcode could optionally be used thus requiring an attacker to generate a series of collisions.
When Alice registers a new device with the Weave Sync server the client first checks if there are other authorised clients, if not it initialises the storage, if so it requests authorisation by following the procedure below.
- Client A: Create client record with status of 'pending'
- Client A: Send ClientAuthRequestMessage to existing authorised clients using 3DHE, i.e. Client B
- Client A: Display authcode generated from the state, i.e. digest(salt, time, authorised client keys)
- Client B: User enters authcode when prompted to approve and verify request. Alternatively reject request.
- Client B: On authorisation approved send ClientAuthResponseMessage with sync key
- Client B: On authorisation declined send ClientAuthResponseMessage with auth fail code
- Client A: Poll for authorisation response
- Client A: On authorisation approved notify user, verify HMAC of Client B record and update client record status to 'approved'
- Client A: On authorisation declined no action taken
Alice (Client A) Eve (Public) Bob (Client B) Charlie (Client C)
t0 AIs AIp, BIp, CIp BIs CIs
BE{1..n}p, BE{1..n}s CE{1..n}s
CE{1..n}p
t1 AIs AIp, BIp, CIp
AEs AEp, BEp
BIp AS, AT
BEp = BE[X]p, X ∈ {1..n}
S = KDF(3DHE(AIs, AEs, BIp, BEp))
AS = RANDOM()
AT = t1
CIp
VD = DIGEST(AS, AT, AIp, BIp, CIp...)
VC = TRUNCATE(AD)
t2 BIs
BEs ∈ BE[X]s, X ∈ {1..n}
AIp
AEp
S = KDF(3DHE(BIs, BEs, AIp, AEp)
AS
AT
CIp
VD = DIGEST(AS, AT, AIp, Bip, CIp,...)
VC = <user input>
Verified = (VC == TRUNCATE(VD))
And optionally using TOTP verification
tn Td = tn - AT Td = tn - AT
VC = TOTP(VD, Td) VC = <user input>
Verified = (VC == TOTP(VD, Td))
Notes:
- The authcode (VC) is a digest of the state at the time the ClientAuthRequestMessage was sent. This code needs to be entered on the authorising device to verify the authenticity of the request. If the authcode displayed by Client A matches the digest of the state generated independently on Client B then a man-in-the-middle attack is highly unlikely.
- Optionally a time-based one-time password (TOTP) algorithm could be used to generate the authcode further strengthening against a MITM attack. However this would require the user to be in possession of both devices at the same time, which largely negates the benefits of the key exchange being asynchronous.
ClientAuthVerifierV2 JSON
{
salt: "Salt value for digest",
time: "Time value for digest and optionally TOTP"
}
ClientAuthRequestMessage JSON
No change from V1
ClientAuthResponseMessage JSON
No change from V1
Key Rotation Protocol
TODO