profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/mvgorcum/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Mathijs van Gorcum mvgorcum Physics of Fluids / University of Twente Enschede - The Netherlands https://mathijs.vgorcum.com

mvgorcum/Sessile.drop.analysis 8

Python script to analyse sessile drops by measuring contact angle, drop volume and contact line speed

mvgorcum/awesome-FOSS-apps 7

Collection of Free and Open Source Android apps.

mvgorcum/tt-rss_feeds_to_conky 2

Use the tt-rss api to read feeds and display the unread article titles in conky

mvgorcum/solarread 1

Read and display sofar solar SH1ES136 data

MatrixDoctors/Riot-web-electron-builder 0

Docker image to build riot-web-electron

mvgorcum/docker-matrix 0

docker image for matrix.org

mvgorcum/docker-nginx-ts 0

Docker Image for MPEG-TS streams using Nginx

mvgorcum/dumb-password-rules 0

Shaming sites with dumb password rules.

mvgorcum/friggeri-letter 0

A LaTeX template for a cover letter to go with the Friggeri Resume

mvgorcum/friggeri-website 0

A website to go with the friggeri CV

push eventmvgorcum/matrix-doc

mvgorcum

commit sha f9d17d6ff4e8172cb38b8a8a02e484b0794d13a3

differentiate between password hash and hash

view details

push time in 20 days

push eventmvgorcum/matrix-doc

Mathijs van Gorcum

commit sha 0da7675edc63bb39e17f06efd301b2d739cbdc4d

more UIA fixes

view details

push time in 23 days

push eventmvgorcum/matrix-doc

Mathijs van Gorcum

commit sha 6765a68ad85ee43cca2839dbb118cdb0158a727b

more UIA additions

view details

push time in 23 days

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "device_id": "GHTYAJCE",+  "initial_device_display_name": "Jungle Phone",+  "inhibit_login": false+}+```++The server stores the verifier, salt, and group next to the username.  ++### Convert from password to SRP++Mimicking the flow of register above, first a GET request is sent to check if SRP is +supported and find the supported groups, here we'll reuse the register endpoint +`GET /_matrix/client/r0/register`. *Or we could add a GET endpoint for /_matrix/client/r0/account/password*++To convert to SRP we'll use the [change password endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-password) with the +`"auth_type": "srp6a"` added, and the required `verifier`, `group`, and `salt`.++`POST /_matrix/client/r0/account/password HTTP/1.1`++```+{+  "auth_type": "srp6a",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "logout_devices": false,+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  }+}+```++The server then removes the old password (or old verifier, group, and salt) and stores the new values.++### Login flow++To start the login flow the client sends a GET request to `/_matrix/client/r0/login`, the server responds with:++```+{+  "flows": [+    {+      "type": "m.login.srp6a"+    }+  ]+}+```+(and any other supported login flows)++Next the client sends it's username to obtain the salt and SRP group as:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.init",+  "username": "cheeky_monkey"+}+```++If the user hasn't registered with SRP the server responds with:++`Status code: 403`++```+{+  "errcode": "M_UNAUTHORIZED",+  "error": "User has not registered with SRP."+}+```++The server responds with the salt and SRP group (looked up from the database), and public value `B`:++```+{+  "prime": N,+  "generator": g,+  "salt": s,+  "server_value": B,+  "auth_id": "12345"+}+```+Here N is the prime and g is the generator of the SRP group. s is the stored salt for the user+as supplied in the `POST`, B is the public server value, and auth_id is the id of this authentication flow,+can by any unique random string, used for the server to keep track of the authentication flow.++the server calculates B as:++	B = kv + g^b ++where b is a private randomly generated value for this session (server side) and k is given as:++	k = H(N, g) ++The client then calculates:++	A = g^a +where a is a private randomly generated value for this session (client side).++Both then calculate:++	u = H(A, B) ++Next the client calculates:++	x = H(s, p)  +	S = (B - kg^x) ^ (a + ux)  +	K = H(S)++The server calculates:++	S = (Av^u) ^ b  +	K = H(S)++Resulting in the shared session key K.++To complete the authentication we need to prove to the server that the session key K is the same.+*note that this proof is directly lifted from the [SRP spec](http://srp.stanford.edu/design.html),+another proof can be possible as well.*++The client calculates:++	M1 = H(H(N) xor H(g), H(I), s, A, B, K)++The client will then respond with:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.verify",

Of course this MSC actually needs to support UIA, because authentication doesn't only happen at /login so this is added now. It's more or less a duplicate of /login except all SRP json stuff in put inside an auth object.

mvgorcum

comment created time in 23 days

PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"],+	"srp": {+	    "groups": [supported groups],+	    "hash": [supported hashes] +	}+}+```  +Here the server sends it's supported authentication types (in this example only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526). The supported hashes are a list of supported hashes+by the server. Initially for this MSC we suggest supporting pbkdf2 and bcrypt, though this may change over time.++The client then chooses a supported srp group from the SRP specification,+and a hash function from the supported list and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is the chosen secure hash function, p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "m.login.srp6a",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": "selected group",+  "hash": "H",+  "hash_iterations": i,+  "salt": s,+  "device_id": "GHTYAJCE",+  "initial_device_display_name": "Jungle Phone",+  "inhibit_login": false+}+```++The server stores the verifier, salt, hash function, hash iterations, and group next to the username.++### Convert from password to SRP++Mimicking the flow of register above, first a GET request is sent to check if SRP is +supported and find the supported groups, and hash functions here we'll reuse the register endpoint +`GET /_matrix/client/r0/register`.++To convert to SRP we'll use the [change password endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-password) with the +`"auth_type": "srp6a"` added, and the required `verifier`, `group`, and `salt`.++`POST /_matrix/client/r0/account/password HTTP/1.1`++```+{+  "auth_type": "srp6a",+  "verifier": v,+  "group": "selected group",+  "hash": "H",+  "hash_iterations": i,+  "salt": s,+  "logout_devices": false,+  "auth": {+    "type": "m.login.srp6a",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  }+}+```++The server then removes the old password (or old verifier, hash function, hash iterations, group, and salt) and stores the new values.++### Login flow++To start the login flow the client sends a GET request to `/_matrix/client/r0/login`, the server responds with:++```+{+  "flows": [+    {+      "type": "m.login.srp6a"+    }+  ]+}+```+(and any other supported login flows)++Next the client sends it's username to obtain the salt and SRP group as:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.init",+  "username": "cheeky_monkey"+}+```++If the user hasn't registered with SRP the server responds with:++`Status code: 403`++```+{+  "errcode": "M_UNAUTHORIZED",+  "error": "User has not registered with SRP."+}+```++The server responds with the salt and SRP group (looked up from the database), and public value `B`:++```+{+  "group": "selected group",+  "hash": "H",+  "hash_iterations": i,+  "salt": s,+  "server_value": B,+  "auth_id": "12345"+}+```+The client looks up N (the prime) and g (the generator) of the selected SRP group as sent by the server,+`H` is the has algorithm used with `i` iterations.+s is the stored salt for the user as supplied during registration, B is the public server value,+and auth_id is the id of this authentication flow, can be any unique random string,+used for the server to keep track of the authentication flow.++the server calculates B as:++	B = kv + g^b ++where b is a private randomly generated value for this session (server side) and k is given as:++	k = H(N, g) ++The client then calculates:++	A = g^a +where a is a private randomly generated value for this session (client side).++Both then calculate:++	u = H(A, B) ++Next the client calculates:++	x = H(s, p)  +	S = (B - kg^x) ^ (a + ux)  +	K = H(S)++The server calculates:++	S = (Av^u) ^ b  +	K = H(S)++Resulting in the shared session key K.++To complete the authentication we need to prove to the server that the session key K is the same.++The client calculates:++	M1 = H(H(N) xor H(g), H(I), s, A, B, K)

I did add that this is base64 encoded, in case that wasn't clear.

mvgorcum

comment created time in 23 days

PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"],+	"srp": {+	    "groups": [supported groups],+	    "hash": [supported hashes] +	}+}+```  +Here the server sends it's supported authentication types (in this example only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or 

There are a few duplicate bit groups, so we have to name them by string. Otherwise I adopted this suggestion wholesale.

mvgorcum

comment created time in 23 days

PullRequestReviewEvent

push eventmvgorcum/matrix-doc

Mathijs van Gorcum

commit sha eab94a10d1c8f6a6300111513fb37c6ceb221654

add UIA flow, define names for SRP groups

view details

push time in 23 days

push eventmvgorcum/matrix-doc

mvgorcum

commit sha df2180347911b4cdbcd19ca8f5c41d9cc0faafe0

cleanups to prepare for review

view details

push time in 24 days

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "device_id": "GHTYAJCE",+  "initial_device_display_name": "Jungle Phone",+  "inhibit_login": false+}+```++The server stores the verifier, salt, and group next to the username.  ++### Convert from password to SRP++Mimicking the flow of register above, first a GET request is sent to check if SRP is +supported and find the supported groups, here we'll reuse the register endpoint +`GET /_matrix/client/r0/register`. *Or we could add a GET endpoint for /_matrix/client/r0/account/password*++To convert to SRP we'll use the [change password endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-password) with the +`"auth_type": "srp6a"` added, and the required `verifier`, `group`, and `salt`.++`POST /_matrix/client/r0/account/password HTTP/1.1`++```+{+  "auth_type": "srp6a",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "logout_devices": false,+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  }+}+```++The server then removes the old password (or old verifier, group, and salt) and stores the new values.++### Login flow++To start the login flow the client sends a GET request to `/_matrix/client/r0/login`, the server responds with:++```+{+  "flows": [+    {+      "type": "m.login.srp6a"+    }+  ]+}+```+(and any other supported login flows)++Next the client sends it's username to obtain the salt and SRP group as:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.init",+  "username": "cheeky_monkey"+}+```++If the user hasn't registered with SRP the server responds with:++`Status code: 403`++```+{+  "errcode": "M_UNAUTHORIZED",+  "error": "User has not registered with SRP."+}+```++The server responds with the salt and SRP group (looked up from the database), and public value `B`:++```+{+  "prime": N,+  "generator": g,+  "salt": s,+  "server_value": B,+  "auth_id": "12345"+}+```+Here N is the prime and g is the generator of the SRP group. s is the stored salt for the user+as supplied in the `POST`, B is the public server value, and auth_id is the id of this authentication flow,+can by any unique random string, used for the server to keep track of the authentication flow.++the server calculates B as:++	B = kv + g^b ++where b is a private randomly generated value for this session (server side) and k is given as:++	k = H(N, g) ++The client then calculates:++	A = g^a +where a is a private randomly generated value for this session (client side).++Both then calculate:++	u = H(A, B) ++Next the client calculates:++	x = H(s, p)  +	S = (B - kg^x) ^ (a + ux)  +	K = H(S)++The server calculates:++	S = (Av^u) ^ b  +	K = H(S)++Resulting in the shared session key K.++To complete the authentication we need to prove to the server that the session key K is the same.+*note that this proof is directly lifted from the [SRP spec](http://srp.stanford.edu/design.html),+another proof can be possible as well.*++The client calculates:++	M1 = H(H(N) xor H(g), H(I), s, A, B, K)++The client will then respond with:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.verify",

I think so too, I may have missed that the proposal got merged?

mvgorcum

comment created time in 25 days

PullRequestReviewEvent

push eventmvgorcum/matrix-doc

Mathijs van Gorcum

commit sha decfda053a44c2fbb5ab3cd982aaf169a55d8cde

fixed example.foo

view details

push time in 25 days

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",

fixed

mvgorcum

comment created time in 25 days

PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": [g,N],

I realized that passing the group back and forth is not a good plan and replaced the raw g and N values by the selected group, since we need to use one of the supported (and specified) groups for SRP. Referring to them by name saves a lot of bandwidth, and the client and server probably want to check if the selected group is indeed one of the available ones anyway.

mvgorcum

comment created time in 25 days

PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, 

I have added a configurable hash (and iteration number) to the MSC. Does this make sense?

mvgorcum

comment created time in 25 days

PullRequestReviewEvent

push eventmvgorcum/matrix-doc

Mathijs van Gorcum

commit sha 8aabf4cd6c352fefe8f252e8f01b31facf9d0e45

add configurable hash function

view details

push time in 25 days

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, 

Yeah, that's basically the direction I was thinking about as well. Of course we'll also need to pass the used hash functions and iterations back to the client on login.

mvgorcum

comment created time in a month

PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, 

I've looked through the srp spec again, and no specific hash is defined there. In that case there's no real harm in speccing something along those lines here. What are your thoughts, should we specify a hash function in this MSC, or add a way to negotiate the hash function in the flow, and merely suggest a few secure hashes that could be used?

mvgorcum

comment created time in a month

PullRequestReviewEvent

push eventmvgorcum/matrix-doc

mvgorcum

commit sha 3ba3262aff66c11cc0e41746f587c482141848e6

add reference to SCRAM

view details

push time in a month

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "device_id": "GHTYAJCE",+  "initial_device_display_name": "Jungle Phone",+  "inhibit_login": false+}+```++The server stores the verifier, salt, and group next to the username.  ++### Convert from password to SRP++Mimicking the flow of register above, first a GET request is sent to check if SRP is +supported and find the supported groups, here we'll reuse the register endpoint +`GET /_matrix/client/r0/register`. *Or we could add a GET endpoint for /_matrix/client/r0/account/password*++To convert to SRP we'll use the [change password endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-password) with the +`"auth_type": "srp6a"` added, and the required `verifier`, `group`, and `salt`.++`POST /_matrix/client/r0/account/password HTTP/1.1`++```+{+  "auth_type": "srp6a",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "logout_devices": false,+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  }+}+```++The server then removes the old password (or old verifier, group, and salt) and stores the new values.++### Login flow++To start the login flow the client sends a GET request to `/_matrix/client/r0/login`, the server responds with:++```+{+  "flows": [+    {+      "type": "m.login.srp6a"+    }+  ]+}+```+(and any other supported login flows)++Next the client sends it's username to obtain the salt and SRP group as:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.init",+  "username": "cheeky_monkey"+}+```++If the user hasn't registered with SRP the server responds with:++`Status code: 403`++```+{+  "errcode": "M_UNAUTHORIZED",+  "error": "User has not registered with SRP."+}+```++The server responds with the salt and SRP group (looked up from the database), and public value `B`:++```+{+  "prime": N,+  "generator": g,+  "salt": s,+  "server_value": B,+  "auth_id": "12345"+}+```+Here N is the prime and g is the generator of the SRP group. s is the stored salt for the user+as supplied in the `POST`, B is the public server value, and auth_id is the id of this authentication flow,+can by any unique random string, used for the server to keep track of the authentication flow.++the server calculates B as:++	B = kv + g^b ++where b is a private randomly generated value for this session (server side) and k is given as:++	k = H(N, g) ++The client then calculates:++	A = g^a +where a is a private randomly generated value for this session (client side).++Both then calculate:++	u = H(A, B) ++Next the client calculates:++	x = H(s, p)  +	S = (B - kg^x) ^ (a + ux)  +	K = H(S)++The server calculates:++	S = (Av^u) ^ b  +	K = H(S)++Resulting in the shared session key K.++To complete the authentication we need to prove to the server that the session key K is the same.+*note that this proof is directly lifted from the [SRP spec](http://srp.stanford.edu/design.html),+another proof can be possible as well.*++The client calculates:++	M1 = H(H(N) xor H(g), H(I), s, A, B, K)++The client will then respond with:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.verify",+  "evidence_message": M1,+  "client_value": A,+  "auth_id": "12345"+}+```+Here `M1` is the client evidence message, and A is the public client value.+Upon successful authentication (ie M1 matches) the server will respond with the regular login success status code 200:++To prove the identity of the server to the client we can send back M2 as:++	M2 = H(A, M, K)++```+{+  "user_id": "@cheeky_monkey:matrix.org",+  "access_token": "abc123",+  "device_id": "GHTYAJCE",+  "evidence_message": M2+  "well_known": {+    "m.homeserver": {+      "base_url": "https://example.org"+    },+    "m.identity_server": {+      "base_url": "https://id.example.org"+    }+  }+}+```++The client verifies that M2 matches, and is subsequently logged in.+++## Potential issues++Adding this authentication method requires client developers to implement this in all matrix clients.++As long as the plain password login remains available it is not trivial to allow clients to+assume the server never learns the password, since an evil server can say to a new client that it+doesn't support SRP and learn the password that way. And with the client not being authenticated+before login there's no easy way for the client to know whether the user expects SRP to be used.+The long-term solution to this is to declare the old password authentication as deprecated and+have all matrix clients refuse to login with `m.password`. This may take a long time; "the best+moment to plant a tree is 10 years ago, the second best is today."+The short term solution requires a good UX in clients to notify the user that they expect to+login with SRP but the server doesn't support this.+*My initial thought was to look at whether SSSS is set for the user, or even try to decrypt it*+*with the given password and give a warning if this works, but the server can just lie to the*+*client about that, leaving the user none the wiser.*++SRP is vulnerable to precomputation attacks and it is incompatible with elliptic-curve cryptography.+Matthew Green judges it as +["It’s not ideal, but it’s real." and "not obviously broken"](https://blog.cryptographyengineering.com/2018/10/19/lets-talk-about-pake/)+and it's a fairly old protocol.++## Alternatives

I agree that bears a mention here.

mvgorcum

comment created time in a month

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentmatrix-org/matrix-doc

[WIP] MSC3262 aPAKE authentication

+# \[WIP]MSC3262: aPAKE authentication++Like most password authentication, matrix's +[login](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-login) +requires sending the password in plain text (though usually encrypted in transit with https). +This requirement has as (obvious) downside that a man in the middle attack would allow reading the password,+but also requires that the server has temporary access to the plaintext password +(which will subsequently be hashed before storage).++A Password Authenticated Key Exchange (PAKE) can prevent the need for sending the password in plaintext for login,+and an aPAKE (asymmetric or augmented) allows for safe authentication without the server ever needing+access to the plaintext password. OPAQUE is a modern implementation of an aPAKE that is+[currently an ietf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-05), +but as it's still pending and doesn't have many open source implementations using it would +require implementing it ourselves. As such choosing to use SRP +([rfc2945](https://datatracker.ietf.org/doc/html/rfc2945)) makes more sense. +SRP has as downside that the salt is transmitted to the client before authentication, +allowing a precomputation attack which would speed up a followup attack after a server compromise.+However, should a server be compromised, +it is probably simpler to generate an access token and impersonate the target that way.++## Proposal++Add support for the SRP 6a login flow, as `"type": "m.login.srp6a"`.++### Registration flow++To allow clients to discover the supported groups (and whether srp6a is supported)+the client sends a GET request.++`GET /_matrix/client/r0/register`++```+{+	"auth_types": ["password", "srp6a"]+	"srp_groups": [supported groups]+}+```  +Here the server sends it's supported authentication types (in this case only password and srp6a)+and if applicable it sends the supported SRP groups, as specified by the +[SRP specification](https://datatracker.ietf.org/doc/html/rfc5054#page-16) or +[rfc3526](https://datatracker.ietf.org/doc/html/rfc3526).++The client then chooses an srp group and generates a random salt `s`.+The client then calculates the verifier `v` as:++	x = H(s, p)  +	v = g^x++Here H() is a secure hash function, and p is the user specified password, +and `g` is the generator of the selected srp group.  +Note that all values are calculated modulo N (of the selected srp group).++This is then sent to the server, otherwise mimicking the password registration, through:++`POST /_matrix/client/r0/register?kind=user`++```+{+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  },+  "auth_type": "srp6a",+  "username": "cheeky_monkey",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "device_id": "GHTYAJCE",+  "initial_device_display_name": "Jungle Phone",+  "inhibit_login": false+}+```++The server stores the verifier, salt, and group next to the username.  ++### Convert from password to SRP++Mimicking the flow of register above, first a GET request is sent to check if SRP is +supported and find the supported groups, here we'll reuse the register endpoint +`GET /_matrix/client/r0/register`. *Or we could add a GET endpoint for /_matrix/client/r0/account/password*++To convert to SRP we'll use the [change password endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-password) with the +`"auth_type": "srp6a"` added, and the required `verifier`, `group`, and `salt`.++`POST /_matrix/client/r0/account/password HTTP/1.1`++```+{+  "auth_type": "srp6a",+  "verifier": v,+  "group": [g,N],+  "salt": s,+  "logout_devices": false,+  "auth": {+    "type": "example.type.foo",+    "session": "xxxxx",+    "example_credential": "verypoorsharedsecret"+  }+}+```++The server then removes the old password (or old verifier, group, and salt) and stores the new values.++### Login flow++To start the login flow the client sends a GET request to `/_matrix/client/r0/login`, the server responds with:++```+{+  "flows": [+    {+      "type": "m.login.srp6a"+    }+  ]+}+```+(and any other supported login flows)++Next the client sends it's username to obtain the salt and SRP group as:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.init",+  "username": "cheeky_monkey"+}+```++If the user hasn't registered with SRP the server responds with:++`Status code: 403`++```+{+  "errcode": "M_UNAUTHORIZED",+  "error": "User has not registered with SRP."+}+```++The server responds with the salt and SRP group (looked up from the database), and public value `B`:++```+{+  "prime": N,+  "generator": g,+  "salt": s,+  "server_value": B,+  "auth_id": "12345"+}+```+Here N is the prime and g is the generator of the SRP group. s is the stored salt for the user+as supplied in the `POST`, B is the public server value, and auth_id is the id of this authentication flow,+can by any unique random string, used for the server to keep track of the authentication flow.++the server calculates B as:++	B = kv + g^b ++where b is a private randomly generated value for this session (server side) and k is given as:++	k = H(N, g) ++The client then calculates:++	A = g^a +where a is a private randomly generated value for this session (client side).++Both then calculate:++	u = H(A, B) ++Next the client calculates:++	x = H(s, p)  +	S = (B - kg^x) ^ (a + ux)  +	K = H(S)++The server calculates:++	S = (Av^u) ^ b  +	K = H(S)++Resulting in the shared session key K.++To complete the authentication we need to prove to the server that the session key K is the same.+*note that this proof is directly lifted from the [SRP spec](http://srp.stanford.edu/design.html),+another proof can be possible as well.*++The client calculates:++	M1 = H(H(N) xor H(g), H(I), s, A, B, K)++The client will then respond with:++`POST /_matrix/client/r0/login`++```+{+  "type": "m.login.srp6a.verify",

The flow only has one GET request at the very start, so returning just m.login.srp6a seems like it's sufficient to me, supporting just init or just verify makes little sense so I would argue that's implied.

If we compare against the webrtc spec (which also has multiple stages) I think using m.login.srp6a.init and m.login.srp6a.verify in POST to /login makes sense. (webRTC in matrix use m.call.invite, m.call.candidates, m.call.answer and m.call.hangup). We defined an auth_id in this MSC because we do need to keep track of the flows, you can't verify before having done the init.

Then again: srp can map fairly well on the UIA, but that's a seperate MSC and I kept that out of scope here because there's no reason either this msc or the UIA msc needs to depend one another.

mvgorcum

comment created time in a month