diff --git a/src/org/kde/kdeconnect/Helpers/SecurityHelpers/ConstantTimeCompare.kt b/src/org/kde/kdeconnect/Helpers/SecurityHelpers/ConstantTimeCompare.kt new file mode 100644 index 00000000..c3728908 --- /dev/null +++ b/src/org/kde/kdeconnect/Helpers/SecurityHelpers/ConstantTimeCompare.kt @@ -0,0 +1,12 @@ +package org.kde.kdeconnect.Helpers.SecurityHelpers + +fun constantTimeCompare(a: ByteArray, b: ByteArray): Boolean { + if (a.size != b.size) { + return false + } + var result = 0 + for (i in a.indices) { + result = result or (a[i].toInt() xor b[i].toInt()) + } + return result == 0 +} diff --git a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.java b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.java index 6e33c28a..23d43e02 100644 --- a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.java @@ -152,7 +152,7 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref np2.set("ip", NetworkHelper.getLocalIpAddress().getHostAddress()); np2.set("port", server.getPort()); np2.set("user", SimpleSftpServer.USER); - np2.set("password", server.getPassword()); + np2.set("password", server.regeneratePassword()); //Kept for compatibility, in case "multiPaths" is not possible or the other end does not support it if (paths.size() == 1) { diff --git a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.java b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.java index 542f8eeb..3d0c864b 100644 --- a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.java +++ b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.java @@ -31,14 +31,19 @@ import org.kde.kdeconnect.Helpers.RandomHelper; import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Arrays; import java.util.Collections; import java.util.List; +import static org.kde.kdeconnect.Helpers.SecurityHelpers.ConstantTimeCompareKt.constantTimeCompare; + class SimpleSftpServer { private static final int STARTPORT = 1739; private static final int ENDPORT = 1764; @@ -114,7 +119,7 @@ class SimpleSftpServer { public boolean start() { if (!started) { - passwordAuth.password = RandomHelper.randomString(28); + regeneratePassword(); port = STARTPORT; while (!started) { @@ -149,8 +154,10 @@ class SimpleSftpServer { return started; } - String getPassword() { - return passwordAuth.password; + String regeneratePassword() { + String password = RandomHelper.randomString(28); + passwordAuth.setPassword(password); + return password; } int getPort() { @@ -163,11 +170,25 @@ class SimpleSftpServer { static class SimplePasswordAuthenticator implements PasswordAuthenticator { - String password; + MessageDigest sha; + { + try { + sha = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public void setPassword(String password) { + sha.digest(password.getBytes(StandardCharsets.UTF_8)); + } + + byte[] passwordHash; @Override public boolean authenticate(String user, String password, ServerSession session) { - return user.equals(SimpleSftpServer.USER) && password.equals(this.password); + byte[] receivedPasswordHash = sha.digest(password.getBytes(StandardCharsets.UTF_8)); + return user.equals(SimpleSftpServer.USER) && constantTimeCompare(passwordHash, receivedPasswordHash); } }