Removed dependency on bouncycastle - implemented native PBKDF2 via java.security

This commit is contained in:
Josh Stark 2019-03-30 10:34:37 +00:00
parent c100aad7e9
commit 478541f534
5 changed files with 31 additions and 23 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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;
/**
* <p>
* Uses the PKCS5S2 crypto algorithm to encode and verify hashed passwords.
* Uses the PBKDF2 crypto algorithm to encode and verify hashed passwords.
* </p>
*/
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);
}
}
/**

View File

@ -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));

View File

@ -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() {