Skip to content
This repository was archived by the owner on Jan 31, 2025. It is now read-only.

Commit 7692249

Browse files
committed
[fix] enforce that alpha!=beta in final step of the oprf.\n\nthis would allow an attacker having access to the output of the OPRF to reduce the effort to bruteforce the master password to two hashes, eliminating the scalarmultiplication.
1 parent d9cd6a3 commit 7692249

File tree

6 files changed

+39
-8
lines changed

6 files changed

+39
-8
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ Pass the challenge from step 1 on standard input like:
119119
The response is sent to standard output.
120120

121121
### step 3 - derive password
122-
To derive a (currently hex) password, pass the response from step 2 on
123-
standard input and the filename of the tempfile from step 1 like:
122+
To derive a (currently hex) password, pass the response from step 2 on standard
123+
input and the filename of the tempfile and the challenge from step 1 like:
124124

125125
```
126-
fname=$(cat b) ./derive $fname <r0 >pwd0
126+
fname=$(cat b) ./derive $fname c <r0 >pwd0
127127
```
128128

129129
The derived password is sent to standard output and currently is a 32

src/bin/derive.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
#include <unistd.h>
2424
#include <stdint.h>
2525
#include <sodium.h>
26+
#include <string.h>
2627

2728
int main(int argc, char **argv) {
2829
(void) argc;
2930
uint8_t blind[crypto_core_ristretto255_SCALARBYTES],
31+
chal[crypto_core_ristretto255_BYTES],
3032
resp[crypto_core_ristretto255_BYTES];
3133

3234
// read response from stdin
@@ -47,6 +49,23 @@ int main(int argc, char **argv) {
4749
}
4850
fclose(f);
4951

52+
// read original challenge from file passed in argv[2]
53+
f = fopen(argv[2], "r");
54+
if(f==NULL) {
55+
fprintf(stderr,"could not open %s\n", argv[2]);
56+
return 1;
57+
}
58+
if(fread(chal, sizeof chal, 1, f)!=1) {
59+
fprintf(stderr, "expected 32B challenge in %s\n", argv[2]);
60+
return 1;
61+
}
62+
fclose(f);
63+
64+
if(memcmp(chal,resp,sizeof resp)==0) {
65+
fprintf(stderr, "challenge and response are equal\n");
66+
return 1;
67+
}
68+
5069
// invert r = 1/r
5170
unsigned char ir[crypto_core_ristretto255_SCALARBYTES];
5271
if (crypto_core_ristretto255_scalar_invert(ir, blind) != 0) {

src/bin/tests/test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ echo "run 1 respond to challenge"
1818

1919
fname=$(cat b)
2020
echo "run 1 derive password from response"
21-
{ cat r0; echo -n "shitty master password"; } | ../derive $fname >pwd0
21+
{ cat r0; echo -n "shitty master password"; } | ../derive $fname c >pwd0
2222

2323
echo "second run"
2424
echo "run 2 create challenge"
@@ -27,7 +27,7 @@ echo "run 2 respond to challenge"
2727
../respond secret <c >r1
2828
fname=$(cat b)
2929
echo "run 2 derive password from response"
30-
{ cat r1; echo -n "shitty master password"; } | ../derive $fname >pwd1
30+
{ cat r1; echo -n "shitty master password"; } | ../derive $fname c >pwd1
3131

3232
rm c b
3333

src/sphinx.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <stdint.h>
2323
#include <sodium.h>
2424
#include "sphinx.h"
25+
#include <string.h>
2526
#ifdef TRACE
2627
#include "common.h"
2728
#endif
@@ -105,20 +106,30 @@ int sphinx_respond(const uint8_t chal[crypto_core_ristretto255_BYTES], const uin
105106
* pwd: (input) the password
106107
* p_len: (input) the password length
107108
* bfac: (input) bfac from challenge(), array of crypto_core_ristretto255_SCALARBYTES (32) bytes
109+
* chal: (input) the challenge generated in sphinx_challenge, crypto_core_ristretto255_BYTES(32) bytes array
108110
* resp: (input) the response from respond(), crypto_core_ristretto255_BYTES (32) bytes array
109111
* salt: (input) salt for the final password hashing, crypto_pwhash_SALTBYTES bytes array
110112
* rwd: (output) the derived password, crypto_core_ristretto255_BYTES (32) bytes array
111113
* returns -1 on error, 0 on success
112114
*/
113-
int sphinx_finish(const uint8_t *pwd, const size_t p_len, const uint8_t bfac[crypto_core_ristretto255_SCALARBYTES], const uint8_t resp[crypto_core_ristretto255_BYTES], const uint8_t salt[crypto_pwhash_SALTBYTES], uint8_t rwd[crypto_core_ristretto255_BYTES]) {
115+
int sphinx_finish(const uint8_t *pwd, const size_t p_len,
116+
const uint8_t bfac[crypto_core_ristretto255_SCALARBYTES],
117+
const uint8_t chal[crypto_core_ristretto255_BYTES],
118+
const uint8_t resp[crypto_core_ristretto255_BYTES],
119+
const uint8_t salt[crypto_pwhash_SALTBYTES],
120+
uint8_t rwd[crypto_core_ristretto255_BYTES]) {
114121
#ifdef TRACE
115122
dump(bfac, crypto_core_ristretto255_SCALARBYTES, "r");
123+
dump(chal, crypto_core_ristretto255_BYTES, "alpha");
116124
dump(resp, crypto_core_ristretto255_BYTES, "beta");
117125
dump(pwd, p_len, "pwd");
118126
dump(salt, crypto_pwhash_SALTBYTES, "salt");
119127
#endif
120128
// Checks that resp ∈ G^∗ . If not, abort;
121129
if(crypto_core_ristretto255_is_valid_point(resp)!=1) return -1;
130+
if(memcmp(chal,resp,crypto_core_ristretto255_BYTES)==0) {
131+
return -1;
132+
}
122133

123134
// invert bfac = 1/bfac
124135
unsigned char ir[crypto_core_ristretto255_SCALARBYTES];

src/sphinx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ int sphinx_respond(const uint8_t chal[crypto_core_ristretto255_BYTES],
3838
uint8_t resp[crypto_core_ristretto255_BYTES]);
3939
int sphinx_finish(const uint8_t *pwd, const size_t p_len,
4040
const uint8_t bfac[crypto_core_ristretto255_SCALARBYTES],
41+
const uint8_t chal[crypto_core_ristretto255_BYTES],
4142
const uint8_t resp[crypto_core_ristretto255_BYTES],
4243
const uint8_t salt[crypto_pwhash_SALTBYTES],
4344
uint8_t rwd[crypto_core_ristretto255_BYTES]);

src/tests/test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
int main(void) {
88
const uint8_t pwd[]="shitty password";
9-
const uint8_t secret[SPHINX_255_SCALAR_BYTES]={1};
9+
const uint8_t secret[SPHINX_255_SCALAR_BYTES]={2};
1010
const uint8_t salt[crypto_pwhash_SALTBYTES]={1};
1111
uint8_t bfac[SPHINX_255_SCALAR_BYTES],
1212
chal[SPHINX_255_SER_BYTES],
@@ -17,7 +17,7 @@ int main(void) {
1717
if(0!=sphinx_respond(chal, secret, resp)) {
1818
return 1;
1919
}
20-
if(0!=sphinx_finish(pwd, strlen((char*) pwd), bfac, resp, salt, rwd)) {
20+
if(0!=sphinx_finish(pwd, strlen((char*) pwd), bfac, chal, resp, salt, rwd)) {
2121
return 1;
2222
}
2323

0 commit comments

Comments
 (0)