kyngs / LibreLogin

Open-source, multiplatform, and highly customizable authentication plugin with outstanding features and API.
Mozilla Public License 2.0
164 stars 53 forks source link

NexAuth Migration #261

Closed exwtsaikaimemes closed 2 months ago

exwtsaikaimemes commented 2 months ago

Hello, I've been trying to write a migration module for this plugin NexAuth

Although, it seems they don't use salt? I've been digging through their code and can't find what they use for salt. (I am a a bit of a java newbie, I've been programming though for quite a while in Nodejs and Vue)

This is the module I wrote, I will also attach a pictures of the DB schema.

I had to transform the big int from the row set to timestamps since for some reason NexAuth stores it as a big int.

Everything is properly connected an I've created the readProvider in AuthenticLibreLogin to trigger in the config when using nexauth-mysql. So that triggers the migration normally.

        registerReadProvider(new ReadDatabaseProviderRegistration<>(
                connector -> new NexAuthSQLMigrateReadProvider("nexauth_users", logger, connector),
                "nexauth-mysql",
                MySQLDatabaseConnector.class
        ));

PS: All uuids are in offline mode


 package xyz.kyngs.librelogin.common.migrate;

 import xyz.kyngs.librelogin.api.Logger;
 import xyz.kyngs.librelogin.api.crypto.HashedPassword;
 import xyz.kyngs.librelogin.api.database.User;
 import xyz.kyngs.librelogin.api.database.connector.SQLDatabaseConnector;
 import xyz.kyngs.librelogin.common.database.AuthenticUser;
 import xyz.kyngs.librelogin.common.util.CryptoUtil;
 import xyz.kyngs.librelogin.common.util.GeneralUtil;
 import java.sql.Timestamp;

 import java.sql.PreparedStatement;
 import java.util.Collection;
 import java.util.HashSet;

 public class NexAuthSQLMigrateReadProvider extends SQLMigrateReadProvider {

     public NexAuthSQLMigrateReadProvider(String tableName, Logger logger, SQLDatabaseConnector connector) {
         super(tableName, logger, connector);
     }

     @Override
     public Collection<User> getAllUsers() {
         return connector.runQuery(connection -> {
             PreparedStatement ps = connection.prepareStatement("SELECT * FROM `%s`".formatted(tableName));

             var rs = ps.executeQuery();

             var users = new HashSet<User>();

             while (rs.next()) {
                 try {
                     var uniqueIdString = rs.getString("uuid");
                     var premiumIdString = rs.getString("uuid");
                     var lastNickname = rs.getString("name");
                     long lastSeenMillis = rs.getLong("last_online");
                     long firstSeenMillis = rs.getLong("dateCreated");
                     var nexAuthRawPassword = rs.getString("password");
                     var encrypt = rs.getString("encrypt");

                     Timestamp lastSeen = new Timestamp(lastSeenMillis);
                     Timestamp firstSeen = new Timestamp(firstSeenMillis);

                     if (lastNickname == null) continue; //Yes this may happen

                    logger.error("User %s password fail: %s, omitting".formatted(lastNickname, nexAuthRawPassword));
                     HashedPassword password = new HashedPassword(
                        nexAuthRawPassword,
                        null,
                        "SHA-512"
                );
                logger.error("User %s hash password fail: %s, omitting".formatted(lastNickname, password));

                     users.add(new AuthenticUser(
                             GeneralUtil.fromUnDashedUUID(uniqueIdString),
                             null,
                             password,
                             lastNickname,
                             firstSeen,
                             lastSeen,
                             null,
                             null,
                             null,
                             null,
                             null
                     ));

                 } catch (Exception e) {
                     logger.error(e.getMessage()); // Here it throws the error attached below
                     logger.error("Failed to read user from NexAuth db, omitting");
                 }
             }

             return users;

         });
     }
 }

Here's a cherry picked row with scrambled data. I've tampered with the password just to be safe. It really seems that they are not using any salt and I am kind of stuck on this migration.

"id","uuid","name","dateCreated","last_online","ip","password","encrypt","secretKey" 7,"429c64a2-1b92-373f-817f-645623177ce6",SampleExportUser,1712489040050,1714493991781,"0.0.0.0",d81221547bcabd23d50ba873720ba5ca820f7b5b782d08ff73a3a684ae46920a866294ad26d75e15807a9f5dafb1fc5c084020babe0be68388596e73ab8a17c6,SHA512,"{ ""question"": """", ""answer"": """" }"

The schema: schemaNex

The error of my migration module: schemaerror

kyngs commented 2 months ago

I'm honestly not sure what to do here, you would prolly have to add a salt-less MessageDigest CryptoProvider

exwtsaikaimemes commented 2 months ago

I'm honestly not sure what to do here, you would prolly have to add a salt-less MessageDigest CryptoProvider

Thanks for the quick reply, yeah, I have no idea how to do this but I'll search a bit. Have a good night!