diff --git a/build.gradle b/build.gradle index 8764d2e..1e24572 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ repositories { mavenCentral() } -version = '1.2.0' +version = '1.2.1' sourceSets { @@ -54,7 +54,6 @@ dependencies { // MISC compile 'org.apache.commons:commons-lang3:3.7' - compile 'org.bouncycastle:bcprov-jdk15on:1.61' // Unit Testing testCompile 'junit:junit:4.11' @@ -70,6 +69,8 @@ jar { from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } + + exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' } combineJs { diff --git a/src/main/java/io/linuxserver/fleet/auth/authenticator/AuthenticatorFactory.java b/src/main/java/io/linuxserver/fleet/auth/authenticator/AuthenticatorFactory.java index d72e856..1692aa1 100644 --- a/src/main/java/io/linuxserver/fleet/auth/authenticator/AuthenticatorFactory.java +++ b/src/main/java/io/linuxserver/fleet/auth/authenticator/AuthenticatorFactory.java @@ -17,7 +17,6 @@ package io.linuxserver.fleet.auth.authenticator; -import io.linuxserver.fleet.auth.security.PKCS5S2PasswordEncoder; import io.linuxserver.fleet.core.FleetBeans; import io.linuxserver.fleet.core.FleetProperties; import org.slf4j.Logger; diff --git a/src/main/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoder.java b/src/main/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoder.java similarity index 82% rename from src/main/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoder.java rename to src/main/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoder.java index 1dd6799..a39ab0a 100644 --- a/src/main/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoder.java +++ b/src/main/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoder.java @@ -18,36 +18,37 @@ package io.linuxserver.fleet.auth.security; import io.linuxserver.fleet.auth.security.util.SaltGenerator; -import org.bouncycastle.crypto.PBEParametersGenerator; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Base64; /** *
- * Uses the PKCS5S2 crypto algorithm to encode and verify hashed passwords. + * Uses the PBKDF2 crypto algorithm to encode and verify hashed passwords. *
*/ -public class PKCS5S2PasswordEncoder implements PasswordEncoder { +public class PBKDF2PasswordEncoder implements PasswordEncoder { private static final int DEFAULT_HASH_WIDTH = 512; private static final int DEFAULT_ITERATIONS = 150051; + private static final String PBKDF2 = "PBKDF2WithHmacSHA512"; + private final SaltGenerator saltGenerator = new SaltGenerator(); private final byte[] secret; private final int hashWidth; private final int iterations; - public PKCS5S2PasswordEncoder(String secret) { + public PBKDF2PasswordEncoder(String secret) { this(secret, DEFAULT_HASH_WIDTH, DEFAULT_ITERATIONS); } - public PKCS5S2PasswordEncoder(String secret, int hashWidth, int iterations) { + public PBKDF2PasswordEncoder(String secret, int hashWidth, int iterations) { this.secret = secret.getBytes(StandardCharsets.UTF_8); this.hashWidth = hashWidth; @@ -104,14 +105,21 @@ public class PKCS5S2PasswordEncoder implements PasswordEncoder { */ private byte[] encode(String rawPassword, byte[] salt) { - PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest()); - generator.init( - PBEParametersGenerator.PKCS5PasswordToBytes(rawPassword.toCharArray()), - joinArrays(salt, secret), - iterations - ); + try { - return joinArrays(salt, ((KeyParameter) generator.generateDerivedMacParameters(hashWidth)).getKey()); + PBEKeySpec spec = new PBEKeySpec( + + rawPassword.toCharArray(), + joinArrays(salt, secret), + iterations, + hashWidth + ); + + return joinArrays(salt, SecretKeyFactory.getInstance(PBKDF2).generateSecret(spec).getEncoded()); + + } catch (GeneralSecurityException e) { + throw new IllegalStateException("Unable to create password hash", e); + } } /** diff --git a/src/main/java/io/linuxserver/fleet/core/FleetBeans.java b/src/main/java/io/linuxserver/fleet/core/FleetBeans.java index 0900980..0199522 100644 --- a/src/main/java/io/linuxserver/fleet/core/FleetBeans.java +++ b/src/main/java/io/linuxserver/fleet/core/FleetBeans.java @@ -18,7 +18,7 @@ package io.linuxserver.fleet.core; import io.linuxserver.fleet.auth.authenticator.AuthenticatorFactory; -import io.linuxserver.fleet.auth.security.PKCS5S2PasswordEncoder; +import io.linuxserver.fleet.auth.security.PBKDF2PasswordEncoder; import io.linuxserver.fleet.auth.security.PasswordEncoder; import io.linuxserver.fleet.db.DefaultDatabaseConnection; import io.linuxserver.fleet.db.dao.DefaultImageDAO; @@ -58,7 +58,7 @@ public class FleetBeans { final DefaultDatabaseConnection databaseConnection = new DefaultDatabaseConnection(properties); - passwordEncoder = new PKCS5S2PasswordEncoder(properties.getAppSecret()); + passwordEncoder = new PBKDF2PasswordEncoder(properties.getAppSecret()); databaseVersion = new DatabaseVersion(databaseConnection); imageDelegate = new ImageDelegate(new DefaultImageDAO(databaseConnection)); repositoryDelegate = new RepositoryDelegate(new DefaultRepositoryDAO(databaseConnection)); diff --git a/src/test/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoderTest.java b/src/test/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoderTest.java similarity index 78% rename from src/test/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoderTest.java rename to src/test/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoderTest.java index 6069750..7777556 100644 --- a/src/test/java/io/linuxserver/fleet/auth/security/PKCS5S2PasswordEncoderTest.java +++ b/src/test/java/io/linuxserver/fleet/auth/security/PBKDF2PasswordEncoderTest.java @@ -23,11 +23,11 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -public class PKCS5S2PasswordEncoderTest { +public class PBKDF2PasswordEncoderTest { - private static final String HASH_FOR_PASSWORD = "CYvjZH/RPa+6Y4JVQiKjOTEIrdntD+6DJDmolYpO0gta8gjI5yRiN/dRoHr0PhpJB0EoTmqR4gJakqk6HElT2yRaLp6WPG4U0GZIYjQSUo8="; + private static final String HASH_FOR_PASSWORD = "AEGvVmpwYMMYdW5XkX5lqQWKsuZp0fSIxo27KUaI7nPqHF1gTVFvKlEIJyN9FJWsBG5bF59v5axUg2gpyqAsNbT7l9nT5KwKenfkcx7IVEo="; - private PKCS5S2PasswordEncoder encoder = new PKCS5S2PasswordEncoder("superSecret"); + private PBKDF2PasswordEncoder encoder = new PBKDF2PasswordEncoder("superSecret"); @Test public void shouldGenerateHash() {