How are the passwords hashed in auth.txt?

CalumMc
Member
 
Posts: 58
Joined: Mon Dec 12, 2011 16:50

How are the passwords hashed in auth.txt?

by CalumMc » Tue Aug 06, 2013 16:03

I have searched the forum and the IRC log but I can't find any mention of the type of hashing used in this file. I am trying to find out because I would like to use this file as a way of authenticating server users for a web based script.

Thank you.
Last edited by CalumMc on Tue Aug 06, 2013 16:03, edited 1 time in total.
 

User avatar
xyz
Member
 
Posts: 449
Joined: Thu Nov 10, 2011 14:25

by xyz » Tue Aug 06, 2013 16:42

You should (probably) use custom auth handler.

Here's the code which hashes login, password pair:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
std::string translatePassword(std::string playername, std::wstring password)
{
    if(password.length() == 0)
        return "";

    std::string slt = playername + wide_to_narrow(password);
    SHA1 sha1;
    sha1.addBytes(slt.c_str(), slt.length());
    unsigned char *digest = sha1.getDigest();
    std::string pwd = base64_encode(digest, 20);
    free(digest);
    return pwd;
}


Be aware that server doesn't know client's raw password, it's transferred in hashed state.

Edit: Here's Python code
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
hashed = base64.b64encode(hashlib.sha1("%s%s" % (name, password)).digest())[:-1]
 

CalumMc
Member
 
Posts: 58
Joined: Mon Dec 12, 2011 16:50

by CalumMc » Tue Aug 06, 2013 16:52

Perfect! Thanks.
 

User avatar
BrandonReese
Member
 
Posts: 836
Joined: Wed Sep 12, 2012 00:44
GitHub: bremaweb
IRC: BrandonReese
In-game: BrandonReese

by BrandonReese » Tue Aug 06, 2013 18:28

CalumMc wrote:I have searched the forum and the IRC log but I can't find any mention of the type of hashing used in this file. I am trying to find out because I would like to use this file as a way of authenticating server users for a web based script.

Thank you.


I wrote about 80% of a web authentication mod (sign up on a website, minetest uses the REST api to authenticate with the website & retrieve permissions) and this is the PHP I used to generate the password hash from the information received from the user to check against the auth.txt file

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$hash = rtrim(base64_encode(sha1($username . $password,true)),"=")
Last edited by BrandonReese on Tue Aug 06, 2013 18:37, edited 1 time in total.
 

CalumMc
Member
 
Posts: 58
Joined: Mon Dec 12, 2011 16:50

by CalumMc » Tue Aug 06, 2013 20:45

Thanks xyz and BrandonReese for your code snippets.
 

Exilyth
Member
 
Posts: 60
Joined: Sun Jul 28, 2013 18:46

by Exilyth » Wed Aug 07, 2013 23:39

Imho, that hash function is lacking taste. Could use a bit more salt... ;)
I'm running 0.4.13 stable with [technic][carts][farming_plus][biome_lib][unified_inventory] and a few other mods.
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Wed Apr 06, 2016 16:11

With the new minetest versions (I am using minetest 0.4.13), this is not anymore true.
Indeed, if I call core.get_password_hash(player_name, player_password), the returned value is not the one stored in the auth.txt file.
Can you explain me how I can get the real stored value please?
 

User avatar
sfan5
Member
 
Posts: 3636
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5

Re: How are the passwords hashed in auth.txt?

by sfan5 » Sat Apr 09, 2016 18:38

Newer Minetest versions use SRP for password storage if the client supports it.
The only thing you can do now is check stuff stored in the auth.txt against a plaintext password (or during login while interacting with the client).
Mods: Mesecons | WorldEdit | Nuke
Minetest builds for Windows (32-bit & 64-bit)
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Sun Apr 10, 2016 00:46

OK so how I can do this check in the C++ source code of Minetest please?
What's the name of the function that can check the SRP password (stored in auth.txt) against a plaintext password (given by the user)?
 

User avatar
rubenwardy
Member
 
Posts: 4500
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: How are the passwords hashed in auth.txt?

by rubenwardy » Sun Apr 10, 2016 01:45

It's a whole protocol exchange, not a hashing function. If you're trying to make IRC work, don't bother. Just use /setpassword for not to use the old hashing function.
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Sun Apr 10, 2016 07:56

In fact, I am writing in C an utility to manage Minetest worlds.
It reads the content of the auth.txt file and checks if the provided nickname and password matches with a user in the auth.txt file.
It works well with old passwords because I have understood how the old passwords are hashed looking at the Minetest source code.
But with new passwords, I don't understand well.
I am not familiar with SRP and reading the Minetest C++ source code does not help me to understood better.
I would like that my utility supports the new passwords too.
Is it technically possible?
 

User avatar
sfan5
Member
 
Posts: 3636
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5

Re: How are the passwords hashed in auth.txt?

by sfan5 » Sun Apr 10, 2016 09:00

It is technically possible to check the SRP values from auth.txt against a plaintext password. SRP is not meant to be used that way though, the whole point of SRP is that you don't need to know your users password to check them.
If you absolutely need to do this I suggest you to read up on an SRP implementation for C (you need to pick one with strict RFC 5054 compatibility as Minetest uses a library with this special thing).
Mods: Mesecons | WorldEdit | Nuke
Minetest builds for Windows (32-bit & 64-bit)
 

User avatar
rubenwardy
Member
 
Posts: 4500
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: How are the passwords hashed in auth.txt?

by rubenwardy » Sun Apr 10, 2016 13:18

This is the library MT uses: https://github.com/est31/csrp-gmp
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Wed Apr 20, 2016 13:22

OK I have written a minimal C code using this SRP library in order to authenticate a MT user.
Unfortunately, it does not work.

This is the code:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include <ctype.h> /* for tolower */
#include "srp.h" /* for srp_create_salted_verification_key */
char *minetest_test_srp_string_tolower(const char *string)
{
   int index = 0;
   int len = strlen(string);
   char *result = NULL;
   result = malloc(sizeof(char) * (len + 1));
   if(result == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the string containing lower case letters.\n");
      return NULL;
   }
   for(; index < len; index++)
      result += tolower(string[index]);
   result[len] = '\0';
   return result;
}
int minetest_test_srp(const char *name, const char *password)
{
   char *name_lower = minetest_test_srp_string_tolower(name);
   struct SRPUser *usr = NULL;
   struct SRPVerifier *ver = NULL;
   unsigned char *bytes_s = NULL;
   unsigned char *bytes_v = NULL;
   unsigned char *bytes_A = 0;
   unsigned char *bytes_B = 0;
   unsigned char *bytes_M = 0;
   unsigned char *bytes_HAMK = 0;
   const unsigned char *bytes_S = 0;
   size_t len_s = 0;
   size_t len_v = 0;
   size_t len_A = 0;
   size_t len_B = 0;
   size_t len_M = 0;
   size_t len_S = 0;
   srp_create_salted_verification_key(SRP_SHA256,
         SRP_NG_2048,
         name_lower,
         (const unsigned char *) password,
         strlen(password),
         &bytes_s,
         &len_s,
         &bytes_v,
         &len_v,
         NULL,
         NULL);
   if(bytes_s == NULL || bytes_v == NULL)
   {
      fprintf(stderr, "Unable to create the SRP salted verification key.\n");
      return -1;
   }
   usr = srp_user_new(SRP_SHA256,
         SRP_NG_2048,
         name,
         name,
         (const unsigned char *) password,
         strlen(password),
         NULL,
         NULL);
   if(usr == NULL)
   {
      fprintf(stderr, "Unable to create the SRP user.\n");
      return -1;
   }
   srp_user_start_authentication(usr,
         NULL,
         NULL,
         0,
         &bytes_A,
         &len_A);
   if(bytes_A == NULL)
   {
      fprintf(stderr, "Unable to start the SRP user authentification.\n");
      return -1;
   }
   ver = srp_verifier_new(SRP_SHA256,
         SRP_NG_2048,
         name,
         bytes_s,
         len_s,
         bytes_v,
         len_v,
         bytes_A,
         len_A,
         NULL,
         0,
         &bytes_B,
         &len_B,
         NULL,
         NULL);
   if(ver == NULL || bytes_B == NULL)
   {
      fprintf(stderr, "Unable to create the SRP verifier.\n");
      return -1;
   }
   srp_user_process_challenge(usr,
         NULL,
         len_s,
         bytes_B,
         len_B,
         &bytes_M,
         &len_M);
   if(bytes_M == NULL)
   {
      fprintf(stderr, "Unable to process the SRP user challenge.\n");
      return -1;
   }
   srp_verifier_verify_session(ver,
         bytes_M,
         &bytes_HAMK);
   if(bytes_HAMK == NULL)
   {
      fprintf(stderr, "Unable to verify the SRP verifier session.\n");
      return -1;
   }
   if(!srp_user_is_authenticated(usr))
      return 0;
   bytes_S = srp_verifier_get_session_key(ver, &len_S);
   if(bytes_S == NULL)
   {
      fprintf(stderr, "Unable to get the SRP session key.\n");
      return -1;
   }
   return 1;
}
int main(int argc, char **argv)
{
   if(argc != 3)
   {
      fprintf(stderr, "Usage: %s NAME PASSWORD\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   int result = minetest_test_srp(argv[1], argv[2]);
   if(result == -1)
   {
      fprintf(stderr, "Unable to authenticate through the SRP protocol.\n");
      exit(EXIT_FAILURE);
   }
   if(result == 1)
      printf("Authentification: Success!\n");
   else
      printf("Authentification: Failure!\n");
   exit(EXIT_SUCCESS);
}


This is how to run it:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out
Usage: ./minetest_test_srp.out NAME PASSWORD


The gdb backtrace is:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ gdb --args ./minetest_test_srp.out MyName MyPassword
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-slackware-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/yugiohjcj/documents/projects/software/minetest-test-srp/minetest-test-srp-current/minetest_test_srp.out...done.
(gdb) run
Starting program: /home/yugiohjcj/documents/projects/software/minetest-test-srp/minetest-test-srp-current/./minetest_test_srp.out MyName MyPassword

Program received signal SIGSEGV, Segmentation fault.
0xb7e2c097 in memcpy () from /lib/libc.so.6
(gdb) bt
#0  0xb7e2c097 in memcpy () from /lib/libc.so.6
#1  0x0804941a in H_ns (result=0xbfffec6c, alg=SRP_SHA256, n=0x0, len_n=16,
    bytes=0xbfffebb0 "g\347\370\331\326\322:\265\372\t\377\234#\233\331\336r\027_o\260x\327\fE\370\253ڐ\001\344\341\004", len_bytes=32) at srp.c:419
#2  0x08049537 in calculate_x (result=0xbfffec6c, alg=SRP_SHA256, salt=0x0, salt_len=16, username=0x8053418 "MyName", password=0x8053428 "MyPassword", password_len=10)
    at srp.c:443
#3  0x0804a754 in srp_user_process_challenge (usr=0x8053078, bytes_s=0x0, len_s=16,
    bytes_B=0x8054148 "b\273\060\311Z=\311\023\251\321\067\225]Ҽ\355\332aHN\034\227\a')$\240\331\377k\204\066\256C\016\262\061\271.\024:D\354\221\fa\275\377i\344ə1\323v%\362A\217\275\220\255\256\302\315n\306\003\336\334\344\066\060\367 \027\226\237]\202Ki%\236\006}\216,\325\335^\234&\032+\224\326@\325m\361\201r|h\t֛:wsN&\360½<S\246\325\067\371\032bl\004\257\256cy\226\261\330\034\271\215fPA\326RaU\242\361f\274\033*\272#c`C\322J\251\276", len_B=256, bytes_M=0xbfffecfc, len_M=0xbfffece4)
    at srp.c:972
#4  0x08048de5 in minetest_test_srp (name=0xbffff012 "MyName", password=0xbffff019 "MyPassword") at minetest_test_srp.c:100
#5  0x08048f02 in main (argc=3, argv=0xbfffee14) at minetest_test_srp.c:137
(gdb) quit
A debugging session is active.

   Inferior 1 [process 2610] will be killed.

Quit anyway? (y or n) y


If you see where are the mistakes in my code please tell me.
I provide the full source code archive [1] containing the Makefile, the SRP library and my code.

[1] http://yugiohjcj.free.fr/minetest-test- ... 420.tar.xz
 

est31
Member
 
Posts: 172
Joined: Mon Dec 29, 2014 01:49

Re: How are the passwords hashed in auth.txt?

by est31 » Wed Apr 20, 2016 17:40

YuGiOhJCJ your code is failing in srp_user_process_challenge because you set a salt param of NULL. The salt needs to be known by that function. It doesn't crash anymore if the salt gets used from above. I have no idea however why it then still doesn't work. I see some confusion around name/name_for_verifier, but otherwise I haven't looked closely what may be wrong too.

But what do you generally want to achieve? Verify that a user auth.txt entry matches the given password? Then your approach is wrong, you will only need srp_create_salted_verification_key for that.

You can look at test_srp.c for an example for how to use csrp-gmp.
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Thu Apr 21, 2016 08:19

Indeed, I gave the NULL value for the 2nd parameter of the srp_user_process_challenge function.
It means that I gave a NULL salt to this function and that's why my program crashes.
I am wondering what salt value I should use.

Anyway, like you said, as my objective is to check that a given name/password matches with a player in my auth.txt file, then I only need the srp_create_salted_verification_key function for that.
That should reduce the lines of my code :)

So, after I call srp_create_salted_verification_key, what should I do to check if the provided name/password matches with a player in my auth.txt file?
In other words, how to do the comparison between bytes_s, bytes_v and the value stored in my auth.txt file?

In fact, I am already using the test_srp.c file as example to create my code.
If you watch the code in test_srp.c, you will see that I am using the same variable names and the same order of function calls.
I have just done some modifications in order to match with what MT is doing in its source code (for example: I am using SRP_SHA256 instead of SRP_SHA1).

This is the new code:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include <ctype.h> /* for tolower */
#include "srp.h" /* for srp_create_salted_verification_key */
char *minetest_test_srp_string_tolower(const char *string)
{
   int index = 0;
   int len = strlen(string);
   char *result = NULL;
   result = malloc(sizeof(char) * (len + 1));
   if(result == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the string containing lower case letters.\n");
      return NULL;
   }
   for(; index < len; index++)
      result += tolower(string[index]);
   result[len] = '\0';
   return result;
}
int minetest_test_srp(const char *name, const char *password, const char *verification_key)
{
   char *name_lower = minetest_test_srp_string_tolower(name);
   unsigned char *bytes_s = NULL;
   unsigned char *bytes_v = NULL;
   size_t len_s = 0;
   size_t len_v = 0;
   unsigned char *bytes_verification_key = (unsigned char *) verification_key;
   int index = 0;
   srp_create_salted_verification_key(SRP_SHA256,
         SRP_NG_2048,
         name_lower,
         (const unsigned char *) password,
         strlen(password),
         &bytes_s,
         &len_s,
         &bytes_v,
         &len_v,
         NULL,
         NULL);
   if(bytes_s == NULL || bytes_v == NULL)
   {
      fprintf(stderr, "Unable to create the SRP salted verification key.\n");
      return -1;
   }
   for(; index < len_s; index++)
      if(bytes_s[index] != bytes_verification_key[index])
         return 1;
   return 0;
}
int main(int argc, char **argv)
{
   if(argc != 4)
   {
      fprintf(stderr, "Usage: %s NAME PASSWORD VERIFICATION_KEY\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   int result = minetest_test_srp(argv[1], argv[2], argv[3]);
   switch(result)
   {
      case -1:
         fprintf(stderr, "Unable to authenticate through the SRP protocol.\n");
         exit(EXIT_FAILURE);
         break;
      case 0:
         printf("Authentication: Success!\n");
         break;
      default:
         printf("Authentication: Failure!\n");
         break;
   }
   exit(EXIT_SUCCESS);
}


This is how to run it now:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out
Usage: ./minetest_test_srp.out NAME PASSWORD VERIFICATION_KEY


The authentication is a failure:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "MyName" "MyPassword" "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
Authentication: Failure!


I provide the new source code archive [1] containing the Makefile, the SRP library and my code.

[1] http://yugiohjcj.free.fr/minetest-test-srp-20160421.tar.xz
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Wed May 04, 2016 05:44

OK I am not yet able to authenticate a user through SRP but I have enhanced my code.
Now, I create a verification key from the given name and password that has the same size than the one in the auth.txt file.
In fact, I have checked again the MT source code and I have remarked that the verification key stored in the auth.txt file is the concatenation of "#1#" + the salt encoded with base64 + "#" + the verifier encoded with base64 [1].

Based on this new information, I have rewritten my source code:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include <ctype.h> /* for tolower */
#include "base64.h" /* for base64_encode */
#include "srp.h" /* for srp_create_salted_verification_key */
char *minetest_test_srp_string_tolower(const char *string)
{
   int index = 0;
   int len = strlen(string);
   char *result = NULL;
   result = malloc(sizeof(char) * (len + 1));
   if(result == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the string containing lower case letters.\n");
      return NULL;
   }
   for(; index < len; index++)
      result[index] = tolower(string[index]);
   result[len] = '\0';
   return result;
}
int minetest_test_srp(const char *name, const char *password, const char *verification_key)
{
   char *name_lower = minetest_test_srp_string_tolower(name);
   char *base64_bytes_s = NULL;
   char *base64_bytes_v = NULL;
   char *verification_key_to_check = NULL;
   unsigned char *bytes_s = NULL;
   unsigned char *bytes_v = NULL;
   size_t len_s = 0;
   size_t len_v = 0;
   srp_create_salted_verification_key(SRP_SHA256,
         SRP_NG_2048,
         name_lower,
         (const unsigned char *) password,
         strlen(password),
         &bytes_s,
         &len_s,
         &bytes_v,
         &len_v,
         NULL,
         NULL);
   free(name_lower);
   if(bytes_s == NULL)
   {
      fprintf(stderr, "Unable to create the SRP salt.\n");
      return -1;
   }
   if(bytes_v == NULL)
   {
      fprintf(stderr, "Unable to create the SRP verifier.\n");
      return -1;
   }
   base64_bytes_s = base64_encode(bytes_s, len_s);
   if(base64_bytes_s == NULL)
   {
      fprintf(stderr, "Unable to encode with base64 the SRP salt.\n");
      return -1;
   }
   base64_bytes_v = base64_encode(bytes_v, len_v);
   if(base64_bytes_v == NULL)
   {
      fprintf(stderr, "Unable to encode with base64 the SRP verifier.\n");
      return -1;
   }
   verification_key_to_check = malloc(sizeof(char) * (3 + strlen(base64_bytes_s) + 1 + strlen(base64_bytes_v) + 1));
   if(verification_key_to_check == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the SRP verification key to check.\n");
      return -1;
   }
   sprintf(verification_key_to_check, "#1#%s#%s", base64_bytes_s, base64_bytes_v);
   printf("verification_key = \"%s\"\n", verification_key);
   printf("strlen(verification_key) = \"%d\"\n", strlen(verification_key));
   printf("verification_key_to_check = \"%s\"\n", verification_key_to_check);
   printf("strlen(verification_key_to_check) = \"%d\"\n", strlen(verification_key_to_check));
   free(base64_bytes_s);
   free(base64_bytes_v);
   free(bytes_s);
   free(bytes_v);
   if(strcmp(verification_key, verification_key_to_check) != 0)
   {
      free(verification_key_to_check);
      return 1;
   }
   free(verification_key_to_check);
   return 0;
}
int main(int argc, char **argv)
{
   int result = -1;
   if(argc != 4)
   {
      fprintf(stderr, "Usage: %s NAME PASSWORD VERIFICATION_KEY\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   result = minetest_test_srp(argv[1], argv[2], argv[3]);
   switch(result)
   {
      case -1:
         fprintf(stderr, "Unable to authenticate through the SRP protocol.\n");
         exit(EXIT_FAILURE);
         break;
      case 0:
         printf("Authentication: Success!\n");
         break;
      default:
         printf("Authentication: Failure!\n");
         break;
   }
   exit(EXIT_SUCCESS);
}


But the authentication is still a failure because the two verification keys (the one computed from the given name/password and the one directly given by the user) are not equal:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "MyName" "MyPassword" "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key = "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
strlen(verification_key) = "368"
verification_key_to_check = "#1#7jYZpHTZUAvHSfJx+fLcsQ#U/wWqrAx08CcnCu620WkmH9VNKbtLxXx0sVzCBxV9OLVej2c+sOK12loGeef4AI7l2OuOgtiUWlqXrJ5w/JZLUG31XOfu/musva95RemjoBv/7EbvLZyHY1LohQt19QECbEfCw59JcEcM+NspjO3h18EC3LeN36ch9Q42o3ujss13kUxbtR7ZSvZVy1X091bw9F6rCe1k46J0vULq2WEVllFzGMSMeSfphtnQg16RUU1JvvRyDEgq5tneNpm2ioGxh/UXGkszlOxSNPPCo965EDbiFEYLJEB6Af4sdiYo9WpeRGpAIvoZ7CGkQkNeVjkm3wtKGYIhYbhC7SF51qogQ"
strlen(verification_key_to_check) = "368"
Authentication: Failure!


What is fun (but it is probably part of the SRP protocol) is that every time I create a verification key from the given name and password, I get a totally new different verification key:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "MyName" "MyPassword" "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key = "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
strlen(verification_key) = "368"
verification_key_to_check = "#1#0vgyjGL+wn9SGJOXiuq6xA#fFbFFZg1T+y8Pp5jgISonYw32u2nsK0rXrJpXg7WFQIbMHgKbSVjetc3erG/P6P4XjixMKS0FgUEfbUJejtzdyXo1p90dKGxnkEaPqjEBtX06MTDDaVXLQVXG3Eafi7dxx41gFfrx4/j0Vo/ckQ5nE2AQyiLYfKx6fBXuQD315VPdSC7BWZGdk4tDtClIRJjtAqG98XfvhJnOrqUDUimJO57IPj+DR0RgNvkPQE6clZHzYBUrw5VZBDfzJGziJckyF9JUErU5MKxcXU76/tki5uw8TY0JahUvoLrhMoU4+l8gza2dwU18j2W+t+Nw28o/qnsdaUP1UdhZ2CRzm/vJw"
strlen(verification_key_to_check) = "368"
Authentication: Failure!


So, comparing the two verification keys is probably not the correct way to authenticate an user with SRP.
Well, if you know what I should do after calling the srp_create_salted_verification_key function, please tell me.

I provide the new source code archive [2] containing the Makefile, the SRP library, the base64 library and my code.

[1] https://github.com/minetest/minetest/bl ... h.cpp#L103
[2] http://yugiohjcj.free.fr/minetest-test- ... 504.tar.xz
 

est31
Member
 
Posts: 172
Joined: Mon Dec 29, 2014 01:49

Re: How are the passwords hashed in auth.txt?

by est31 » Wed May 04, 2016 13:41

No, you have to compare the verification keys, but you must not let it autogenerate the salt, but use the salt provided to the program. That's your problem I think.
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Wed May 04, 2016 16:07

OK, so I need to provide a non-NULL value to the 6th parameter of the srp_create_salted_verification_key function in order to give a fixed salt that will not be auto-generated.
I am wondering what value I need to give.
As I already have the verification key in the auth.txt file, I guess I need to extract from this string the part corresponding to the salt (from the 4th character to the 25th character of this string).
As it is encoded with base64, I guess I need to decode this sub-string corresponding to the salt before giving it to the srp_create_salted_verification_key function.
Is it correct?
 

est31
Member
 
Posts: 172
Joined: Mon Dec 29, 2014 01:49

Re: How are the passwords hashed in auth.txt?

by est31 » Thu May 05, 2016 00:12

Yes, that's precisely what you need to do.
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Sun May 08, 2016 02:44

Thank you it works :)

Here is the new code:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include <ctype.h> /* for tolower */
#include "base64.h" /* for base64_encode */
#include "srp.h" /* for srp_create_salted_verification_key */
char *minetest_test_srp_string_tolower(const char *string)
{
   int index = 0;
   int len = strlen(string);
   char *result = NULL;
   result = malloc(sizeof(char) * (len + 1));
   if(result == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the string containing lower case letters.\n");
      return NULL;
   }
   for(; index < len; index++)
      result[index] = tolower(string[index]);
   result[len] = '\0';
   return result;
}
int minetest_test_srp(const char *name, const char *password, const char *base64_salt, const char *base64_verifier)
{
   char *verification_key = NULL;
   char *salt = NULL;
   char *name_lower = minetest_test_srp_string_tolower(name);
   char *base64_bytes_s = NULL;
   char *base64_bytes_v = NULL;
   char *verification_key_to_check = NULL;
   unsigned char *bytes_s = NULL;
   unsigned char *bytes_v = NULL;
   size_t len_s = 0;
   size_t len_v = 0;
   verification_key = malloc(sizeof(char) * (3 + strlen(base64_salt) + 1 + strlen(base64_verifier) + 1));
   if(verification_key == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the SRP verification key.\n");
      free(name_lower);
      return -1;
   }
   sprintf(verification_key, "#1#%s#%s", base64_salt, base64_verifier);
   salt = base64_decode(base64_salt);
   if(salt == NULL)
   {
      fprintf(stderr, "Unable to decode with base64 the SRP salt.\n");
      free(name_lower);
      free(verification_key);
      return -1;
   }
   bytes_s = (unsigned char *) salt;
   len_s = strlen(bytes_s);
   srp_create_salted_verification_key(SRP_SHA256,
         SRP_NG_2048,
         name_lower,
         (const unsigned char *) password,
         strlen(password),
         &bytes_s,
         &len_s,
         &bytes_v,
         &len_v,
         NULL,
         NULL);
   free(name_lower);
   if(bytes_s == NULL)
   {
      fprintf(stderr, "Unable to create the SRP salt.\n");
      free(verification_key);
      return -1;
   }
   base64_bytes_s = base64_encode(bytes_s, len_s);
   if(base64_bytes_s == NULL)
   {
      fprintf(stderr, "Unable to encode with base64 the SRP salt.\n");
      free(verification_key);
      return -1;
   }
   if(bytes_v == NULL)
   {
      fprintf(stderr, "Unable to create the SRP verifier.\n");
      free(verification_key);
      return -1;
   }
   base64_bytes_v = base64_encode(bytes_v, len_v);
   if(base64_bytes_v == NULL)
   {
      fprintf(stderr, "Unable to encode with base64 the SRP verifier.\n");
      free(verification_key);
      return -1;
   }
   verification_key_to_check = malloc(sizeof(char) * (3 + strlen(base64_bytes_s) + 1 + strlen(base64_bytes_v) + 1));
   if(verification_key_to_check == NULL)
   {
      fprintf(stderr, "Unable to allocate memory for the SRP verification key to check.\n");
      free(verification_key);
      return -1;
   }
   sprintf(verification_key_to_check, "#1#%s#%s", base64_bytes_s, base64_bytes_v);
   printf("verification_key = \"#1#%s#%s\"\n", base64_salt, base64_verifier);
   printf("verification_key_to_check = \"%s\"\n", verification_key_to_check);
   free(base64_bytes_s);
   free(base64_bytes_v);
   free(bytes_s);
   free(bytes_v);
   if(strcmp(verification_key, verification_key_to_check) != 0)
   {
      free(verification_key);
      free(verification_key_to_check);
      return 1;
   }
   free(verification_key);
   free(verification_key_to_check);
   return 0;
}
int main(int argc, char **argv)
{
   int result = -1;
   if(argc != 5)
   {
      fprintf(stderr, "Usage: %s NAME PASSWORD BASE64_SALT BASE64_VERIFIER\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   result = minetest_test_srp(argv[1], argv[2], argv[3], argv[4]);
   switch(result)
   {
      case -1:
         fprintf(stderr, "Unable to authenticate through the SRP protocol.\n");
         exit(EXIT_FAILURE);
         break;
      case 0:
         printf("Authentication: Success!\n");
         break;
      default:
         printf("Authentication: Failure!\n");
         break;
   }
   exit(EXIT_SUCCESS);
}


Here is how to use it:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out
Usage: ./minetest_test_srp.out NAME PASSWORD BASE64_SALT BASE64_VERIFIER


NAME is the name that you can find in the auth.txt file. It is the first field of a line delimited with the ":" character.
PASSWORD is the password that you must know.
BASE64_SALT is the salt encoded with base64 that you can find in the auth.txt file. It is a part of the second field of a line delimited with the ":" character. It can be found between the "#1#" characters and the "#" character.
BASE64_VERIFIER is the verifier encoded with base64 that you can find in the auth.txt file. It is a part of the second field of a line delimited with the ":" character. It can be found after the 3rd "#" character.

Here is how it works with a successful authentication:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
./minetest_test_srp.out "MyName" "MyPassword" "2VEDb5dBstV5FAGoISg4tw" "L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key = "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key_to_check = "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
Authentication: Success!


Here is how it works with an authentication failure:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "MyName" "MyWrongPassword" "2VEDb5dBstV5FAGoISg4tw" "L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key = "#1#2VEDb5dBstV5FAGoISg4tw#L53b5qo+8YOCtijt5918ps38vxZFxp2aS9YvRBvc2zTXOj+r9zzFuregY5SzxJOr0ARp6CmWPpG9y1a51sFEh3EvdmupH08/3UtTAM9MmwW/6eOrXp2PgWooercXzZbyzDU91tqFXhTv9xtew8JD84MhJeqnOWL4nFe7yDuQrU2rN71NMhIuFtMubpRCTpTvHjKqnLKqJ0cBGls7/cAcQArvzTuHNLwuTXi0aDU4D2Pf4VxTOlsM16HY/Z36rAi3SbCg2fkCMm7qo9h5LVYUeq08/UlUdBXPV9I4m2xwOEWF49ctfFcqd8d/l3EJLPca+gGWYCyqOzt0ty/kjui5xQ"
verification_key_to_check = "#1#2VEDb5dBstV5FAGoISg4tw#O/u4C6lKWYWeFwEiYunXjOj9FwZTXaEcNbsBuEqb1e0scJ3vPh0jCI24DT2zbFl+HYiZIzoNeCCrDUKoxshy2jVocqqulDmWD8zXfNjDU4tZ2c1bcQGt9QZqIK114F8Lyw/L62jv6aDdkFLzSbqwQhjGUzc8eNSwrOF6TZrQ+MLowgnUjHt5WKKeTXpomerPW7gOp3a7QZqeiV3jhK8ATwJCKHnHWWw3BvAWuqzkEItjXf1BF+ppSnbvMvFXWmLYqRvwPkSpM/9xUu6AJ8queg2XYXEa9t813LvqCwFQe//cTC9QrSudrvKvMAErdh82fJPnxGUNzHyyykkUTxnJUQ"
Authentication: Failure!


I provide the new source code archive [1] containing the Makefile, the SRP library, the base64 library and my code.

[1] http://yugiohjcj.free.fr/minetest-test- ... 508.tar.xz
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Fri Jun 03, 2016 02:19

I found a case where it does not work :(

Here is the content of my auth.txt file:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ cat ~/.minetest/worlds/myworld/auth.txt
MyName:#1#IFrOhR2wlVmgEUYWreUArA#OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A:interact,home,teleport,give,shout,interaction_areas_user:1464919128


Here is the call to my program:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out MyName MyPassword "IFrOhR2wlVmgEUYWreUArA" "OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A"
verification_key = "#1#IFrOhR2wlVmgEUYWreUArA#OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A"
verification_key_to_check = "#1#IFrOhR2wlVmgEUYWreU#BHdKeqysUwHyYM0L+1kddDVKnA1cl1PAaDff3HtQ2g6AICNJfbx98igyeFiJ7hkFTwBHssjlaGmNTrLeVibzPrgFsWVnapYyu1L5pQ9jWU4nG5b9ZYR4vtfFnlOZ6egHbblE6nv2U/sXTqX5oVcp1QXmvPr+7IxwUIVGaC640fhgFBBfsbbe+gJz8oNNmmtcfh2d018ZTz5ugZ1jtYpWFY34J3qqwaeNtdH+UsRN9Y4QslQJKHgzPdf0TJq1qOAB3E6rOdpTjCsvDto4YWd0V8NG/QZV1IriRlCHsfFZsWUCOoF0aIlyur3cRUr1pPbAy+UHkhkIsR1fIcKMHdp28g"
Authentication: Failure!


We can see that the salt that I give is: "IFrOhR2wlVmgEUYWreUArA" (size is 22 characters).
However, if you check the salt after the call to the srp_create_salted_verification_key function, the value is: "IFrOhR2wlVmgEUYWreU" (size is 19 characters).
Yes, you guessed it: Three characters are missing in this salt (these characters are: "ArA").
As the salt has been changed, the generated key is also different.

Do you know why my program fails in this case please?
 

est31
Member
 
Posts: 172
Joined: Mon Dec 29, 2014 01:49

Re: How are the passwords hashed in auth.txt?

by est31 » Sat Jun 04, 2016 00:37

No idea, maybe check with valgrind that no writes happen outside of ranges where they shouldn't happen?
 

User avatar
YuGiOhJCJ
Member
 
Posts: 34
Joined: Sat Jan 23, 2016 07:41
GitHub: YuGiOhJCJ
IRC: YuGiOhJCJ
In-game: YuGiOhJCJ

Re: How are the passwords hashed in auth.txt?

by YuGiOhJCJ » Sat Jun 04, 2016 06:18

It seems that valgrind does not detect any error:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ valgrind ./minetest_test_srp.out MyName MyPassword "IFrOhR2wlVmgEUYWreUArA" "OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A"
==975== Memcheck, a memory error detector
==975== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==975== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==975== Command: ./minetest_test_srp.out MyName MyPassword IFrOhR2wlVmgEUYWreUArA OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A
==975==
verification_key = "#1#IFrOhR2wlVmgEUYWreUArA#OdnUTPArLAGNlsqXz1GB4lAosMTZQKS04XwrPpAq+j++EZabl5OIHbwhqwkFT16ijAcT0ziqQsvven34HaDwoitLlE1nAtIT82mT7SC5IVsnCF8J1/SlQ2dMIm4+tmpVe4A4tHlHyQVHjEuOlNaTnat7QykLNZFZbF9BrK1jqnkvHH8zMoGsf7ClOTYejPWWe2j+jLm6xz5h6nASQdSxY34smGDhYKhcok0asSAgDLJILMuA0FTV6U4dY7gjKWbZCiTt5ueLje9fcB1OMS/1t9NCxvylp1p7R9u9PqLhjBnMlDtzy0uyj6kcvS2C0kWg67/PNYRVcmtjGxGGYRGU/A"
verification_key_to_check = "#1#IFrOhR2wlVmgEUYWreU#BHdKeqysUwHyYM0L+1kddDVKnA1cl1PAaDff3HtQ2g6AICNJfbx98igyeFiJ7hkFTwBHssjlaGmNTrLeVibzPrgFsWVnapYyu1L5pQ9jWU4nG5b9ZYR4vtfFnlOZ6egHbblE6nv2U/sXTqX5oVcp1QXmvPr+7IxwUIVGaC640fhgFBBfsbbe+gJz8oNNmmtcfh2d018ZTz5ugZ1jtYpWFY34J3qqwaeNtdH+UsRN9Y4QslQJKHgzPdf0TJq1qOAB3E6rOdpTjCsvDto4YWd0V8NG/QZV1IriRlCHsfFZsWUCOoF0aIlyur3cRUr1pPbAy+UHkhkIsR1fIcKMHdp28g"
Authentication: Failure!
==975==
==975== HEAP SUMMARY:
==975==     in use at exit: 0 bytes in 0 blocks
==975==   total heap usage: 392 allocs, 392 frees, 61,348 bytes allocated
==975==
==975== All heap blocks were freed -- no leaks are possible
==975==
==975== For counts of detected and suppressed errors, rerun with: -v
==975== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


However, I think I found something interesting.

I have rewritten the code in order to focus on the salt, the base64_decode function and the base64_encode function:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include "base64.h" /* for base64_encode */
int main(int argc, char **argv)
{
   char *salt = NULL;
   int len_salt = 0;
   char *base64_salt = NULL;
   if(argc != 2)
   {
      fprintf(stderr, "Usage: %s BASE64_SALT\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   salt = base64_decode(argv[1]);
   len_salt = strlen(salt);
   base64_salt = base64_encode((unsigned char *) salt, len_salt);
   printf("argv[1] = \"%s\"\n", argv[1]);
   printf("salt = \"%s\"\n", salt);
   printf("len_salt = \"%d\"\n", len_salt);
   printf("base64_salt = \"%s\"\n", base64_salt);
   free(salt);
   free(base64_salt);
   exit(EXIT_SUCCESS);
}


Here is how to use it:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out
Usage: ./minetest_test_srp.out BASE64_SALT


Here is an example:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "IFrOhR2wlVmgEUYWreUArA"
argv[1] = "IFrOhR2wlVmgEUYWreUArA"
salt = " Z΅°Y F­å"
len_salt = "14"
base64_salt = "IFrOhR2wlVmgEUYWreU"


As you can see, I give an encoded base64 salt, then I decode it, then I encode it again and the result is that I don't get the same encoded base64 salt.
I provide the new source code archive [1] containing the Makefile, the base64 library and my code.

I have also rewritten the code in C++:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include "base64.h" /* for base64_encode */
int main(int argc, char **argv)
{
   std::string salt;
   int len_salt = 0;
   std::string base64_salt;
   if(argc != 2)
   {
      fprintf(stderr, "Usage: %s BASE64_SALT\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   salt = base64_decode(argv[1]);
   len_salt = salt.size();
   base64_salt = base64_encode((unsigned char *) salt.c_str(), len_salt);
   printf("argv[1] = \"%s\"\n", argv[1]);
   printf("salt = \"%s\"\n", salt.c_str());
   printf("len_salt = \"%d\"\n", len_salt);
   printf("len_salt = \"%d\"\n", strlen(salt.c_str()));
   printf("base64_salt = \"%s\"\n", base64_salt.c_str());
   for(int index = 0; index < len_salt; index++)
      printf("salt[%d] = \"%c\" (is null character? \"%d\")\n", index, salt[index], salt[index] == '\0');
   printf("sizeof(char) = \"%d\"\n", sizeof(char));
   exit(EXIT_SUCCESS);
}


The usage is the same:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp_cpp.out
Usage: ./minetest_test_srp_cpp.out BASE64_SALT


Here is an example:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp_cpp.out "IFrOhR2wlVmgEUYWreUArA"
argv[1] = "IFrOhR2wlVmgEUYWreUArA"
salt = " Z΅°Y F­å"
len_salt = "16"
len_salt = "14"
base64_salt = "IFrOhR2wlVmgEUYWreUArA"
salt[0] = " " (is null character? "0")
salt[1] = "Z" (is null character? "0")
salt[2] = "Î" (is null character? "0")
salt[3] = "" (is null character? "0")
salt[4] = "" (is null character? "0")
salt[5] = "°" (is null character? "0")
salt[6] = "" (is null character? "0")
salt[7] = "Y" (is null character? "0")
salt[8] = " " (is null character? "0")
salt[9] = "" (is null character? "0")
salt[10] = "F" (is null character? "0")
salt[11] = "" (is null character? "0")
salt[12] = "­" (is null character? "0")
salt[13] = "å" (is null character? "0")
salt[14] = "" (is null character? "1")
salt[15] = "¬" (is null character? "0")
sizeof(char) = "1"


As you can see, in this C++ version it works!
I give an encoded base64 salt, then I decode it, then I encode it again and the result is that I get the same encoded base64 salt.

Why it works here?
The reason is that instead of using the strlen function (the one we use with C strings), I am using here the size member function (the one we use with C++ strings).
There is a difference between these two functions.
The one from C is computing the size of the string by looking for the first occurrence of the '\0' character in the string.
The one from C++ does not do that, which means that C++ strings can contain a '\0' character.
Unfortunately, the base64_decode function can return a string containing a '\0' character, so the strlen function is not able to compute correctly the size of the string.
As you can see the character at index 14 of the returned string is a '\0', so the length computed is 14 instead of 16.

I provide the C++ source code archive [2] containing the Makefile, the base64 library and my code.

The solution in C is to return the string and the real size of the string (not the one computed with strlen):
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h> /* for strlen */
#include "base64.h" /* for base64_encode */
int main(int argc, char **argv)
{
   char *salt = NULL;
   int len_salt = 0;
   char *base64_salt = NULL;
   if(argc != 2)
   {
      fprintf(stderr, "Usage: %s BASE64_SALT\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   salt = base64_decode(argv[1], &len_salt);
   base64_salt = base64_encode((unsigned char *) salt, len_salt);
   printf("argv[1] = \"%s\"\n", argv[1]);
   printf("salt = \"%s\"\n", salt);
   printf("len_salt = \"%d\"\n", len_salt);
   printf("base64_salt = \"%s\"\n", base64_salt);
   free(salt);
   free(base64_salt);
   exit(EXIT_SUCCESS);
}


Here is the result:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$ ./minetest_test_srp.out "IFrOhR2wlVmgEUYWreUArA"
argv[1] = "IFrOhR2wlVmgEUYWreUArA"
salt = " Z΅°Y F­å"
len_salt = "16"
base64_salt = "IFrOhR2wlVmgEUYWreUArA"


It works in C too!

I provide the new C source code archive [3] containing the Makefile, the base64 library and my code.

[1] http://yugiohjcj.free.fr/minetest-test- ... 604.tar.xz
[2] http://yugiohjcj.free.fr/minetest-test- ... 605.tar.xz
[3] http://yugiohjcj.free.fr/minetest-test- ... 605.tar.xz
 


Return to Minetest General

Who is online

Users browsing this forum: No registered users and 12 guests

cron