-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Require salt and iterationCount configuration
- Loading branch information
Showing
10 changed files
with
260 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 0 additions & 88 deletions
88
rest-api/src/main/java/life/qbic/data_download/rest/security/QBiCTokenMatcher.java
This file was deleted.
Oops, something went wrong.
86 changes: 86 additions & 0 deletions
86
rest-api/src/main/java/life/qbic/data_download/rest/security/QBicTokenEncoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package life.qbic.data_download.rest.security; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import java.security.NoSuchAlgorithmException; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.security.spec.KeySpec; | ||
import java.util.HexFormat; | ||
import javax.crypto.SecretKey; | ||
import javax.crypto.SecretKeyFactory; | ||
import javax.crypto.spec.PBEKeySpec; | ||
import javax.crypto.spec.SecretKeySpec; | ||
|
||
/** | ||
* A token encoder | ||
*/ | ||
public class QBicTokenEncoder implements TokenEncoder { | ||
|
||
private static final int EXPECTED_MIN_SALT_BITS = 128; | ||
private static final int EXPECTED_MIN_SALT_BYTES = (int) Math.ceil( | ||
(double) EXPECTED_MIN_SALT_BITS / 8); | ||
private static final int EXPECTED_MIN_ITERATION_COUNT = 100_000; | ||
|
||
private final byte[] salt; | ||
private final int iterationCount; | ||
|
||
public QBicTokenEncoder(String salt, int iterationCount) { | ||
this.salt = fromHex(requireNonNull(salt, "salt must not be null")); | ||
if (this.salt.length < EXPECTED_MIN_SALT_BYTES) { | ||
throw new IllegalArgumentException( | ||
"salt must have at least " + EXPECTED_MIN_SALT_BITS + " bits."); | ||
} | ||
if (iterationCount < EXPECTED_MIN_ITERATION_COUNT) { | ||
throw new IllegalArgumentException( | ||
"Iteration count n=" + iterationCount + " cannot be less than n=" | ||
+ EXPECTED_MIN_ITERATION_COUNT); | ||
} | ||
this.iterationCount = iterationCount; | ||
} | ||
|
||
@Override | ||
public String encode(String token) { | ||
byte[] hash = pbe(token.toCharArray(), salt, iterationCount); | ||
return iterationCount + ":" + toHex(salt) + ":" + toHex(hash); | ||
} | ||
|
||
private record EncryptionSettings(String cipher, int keyBitSize) { | ||
} | ||
|
||
private static final EncryptionSettings ENCRYPTION_SETTINGS = new EncryptionSettings( | ||
"AES", | ||
256 | ||
); | ||
|
||
private static byte[] fromHex(String hex) { | ||
return HexFormat.of().parseHex(hex); | ||
} | ||
|
||
private static String toHex(byte[] bytes) { | ||
HexFormat hexFormat = HexFormat.of(); | ||
return hexFormat.formatHex(bytes); | ||
} | ||
|
||
/** | ||
* Uses Password-Based Encryption to encrypt a token given a salt and iterations | ||
* @param token the token to be encrypted | ||
* @param salt the salt used in the encryption | ||
* @param iterationCount the number of iterations | ||
* @return encryption result | ||
*/ | ||
private static byte[] pbe(char[] token, byte[] salt, int iterationCount) { | ||
KeySpec spec = | ||
new PBEKeySpec(token, salt, iterationCount, ENCRYPTION_SETTINGS.keyBitSize()); | ||
SecretKey secretKey; | ||
try { | ||
SecretKeyFactory result; | ||
result = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); | ||
SecretKeyFactory factory = result; | ||
secretKey = factory.generateSecret(spec); | ||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) { | ||
throw new RuntimeException("error encrypting token: " + e.getMessage()); | ||
} | ||
return new SecretKeySpec(secretKey.getEncoded(), ENCRYPTION_SETTINGS.cipher()).getEncoded(); | ||
} | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
rest-api/src/main/java/life/qbic/data_download/rest/security/TokenEncoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package life.qbic.data_download.rest.security; | ||
|
||
/** | ||
* Encodes QBiC Access Tokens | ||
*/ | ||
public interface TokenEncoder { | ||
|
||
String encode(String token); | ||
} |
6 changes: 4 additions & 2 deletions
6
...in/java/life/qbic/data_download/rest/security/jpa/token/EncodedAccessTokenRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
package life.qbic.data_download.rest.security.jpa.token; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import java.util.Optional; | ||
import org.springframework.data.repository.Repository; | ||
|
||
|
||
public interface EncodedAccessTokenRepository extends JpaRepository<EncodedAccessToken, Integer> { | ||
public interface EncodedAccessTokenRepository extends Repository<EncodedAccessToken, Integer> { | ||
|
||
Optional<EncodedAccessToken> findByAccessTokenEquals(String accessToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 0 additions & 22 deletions
22
rest-api/src/test/java/life/qbic/data_download/rest/security/QBiCTokenMatcherTest.java
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.