Skip to content

Commit

Permalink
Merge branch 'master' into synctool
Browse files Browse the repository at this point in the history
  • Loading branch information
Hu committed Apr 4, 2024
2 parents b7cc057 + 40f7956 commit bcd7f2c
Show file tree
Hide file tree
Showing 32 changed files with 335 additions and 70 deletions.
2 changes: 1 addition & 1 deletion gsrs-controlled-vocabulary-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-controlled-vocabulary/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-core-entities/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package gsrs.model;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
public class UserProfileAuthenticationResult {
private boolean matchesRepository;

public boolean matchesRepository() {
return matchesRepository;
}

public void setMatchesRepository(boolean matchesRepository) {
this.matchesRepository = matchesRepository;
}

public boolean needsSave() {
return needsSave;
}

public void setNeedsSave(boolean needsSave) {
this.needsSave = needsSave;
}

private boolean needsSave;
}
45 changes: 36 additions & 9 deletions gsrs-core-entities/src/main/java/ix/core/models/UserProfile.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package ix.core.models;


import ch.qos.logback.core.rolling.helper.TokenConverter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;

import gov.nih.ncats.common.util.CachedSupplier;
import gov.nih.ncats.common.util.TimeUtil;
import gsrs.model.UserProfileAuthenticationResult;
import gsrs.security.TokenConfiguration;
import gsrs.springUtils.StaticContextAccessor;
import gsrs.util.GsrsPasswordHasher;
import gsrs.util.Hasher;
import gsrs.util.LegacyTypeSalter;
import gsrs.util.Salter;
import ix.utils.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.*;
import java.util.*;
Expand All @@ -22,7 +25,14 @@
@SequenceGenerator(name = "LONG_SEQ_ID", sequenceName = "ix_core_userprof_seq", allocationSize = 1)
@EntityListeners(UserProfileEntityProcessor.class)
public class UserProfile extends IxModel{
private static ObjectMapper om = new ObjectMapper();
private final static String SALT_PREFIX = "G";

private static ObjectMapper om = new ObjectMapper();

//todo: look into autowiring the salter and hasher
private static Salter salter = new LegacyTypeSalter(new GsrsPasswordHasher(), SALT_PREFIX);

private static Hasher hasher = new GsrsPasswordHasher();

private static CachedSupplier<UserProfile> GUEST_PROF= CachedSupplier.of(()->{
UserProfile up = new UserProfile(new Principal("GUEST"));
Expand Down Expand Up @@ -182,21 +192,38 @@ public boolean acceptToken(String token) {
return false;
}

public boolean acceptPassword(String password) {
if (this.hashp == null || this.salt == null)
return false;
return this.hashp.equals(Util.encrypt(password, this.salt));
public UserProfileAuthenticationResult acceptPassword(String password) {
UserProfileAuthenticationResult result = new UserProfileAuthenticationResult(false, false);
if (this.hashp == null || this.salt == null) {
return result;
}
boolean pwOk = this.hashp.equals(hasher.hash(password, this.salt));
log.trace("pwOk: {}", pwOk);
boolean legacyPwOk = false;
//when authentication using latest algorithms fails, see if the password works with the legacy methods
if( !pwOk) {
legacyPwOk= this.hashp.equals(Util.encrypt(password, this.salt));
}
if( legacyPwOk && !salter.mayBeOneOfMine(this.salt)) {
//we have a pw assigned using the older algorithm so we need to resalt and rehash
log.trace("going to request rehash of password");
setPassword(password);
result.setNeedsSave(true);
}
result.setMatchesRepository(pwOk || legacyPwOk);
return result;
}

public void setPassword(String password) {
if (password == null || password.length() <= 0) {
password = UUID.randomUUID().toString();
}
this.salt = Util.generateSalt();
this.hashp = Util.encrypt(password, this.salt);
this.salt = salter.generateSalt();
this.hashp = hasher.hash(password, salt); //Util.encrypt(password, this.salt);
setIsDirty("salt");
setIsDirty("hashp");
}

@Indexable(indexed = false)
@JsonIgnore
public String getEncodePassword(){
Expand Down
38 changes: 38 additions & 0 deletions gsrs-core-entities/src/test/java/gsrs/LegacySalterTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package gsrs;

import gsrs.util.GsrsPasswordHasher;
import gsrs.util.Hasher;
import gsrs.util.LegacyTypeSalter;
import gsrs.util.Salter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class LegacySalterTests {

private final String SALT_PREFIX = "G";

private final Hasher hasher = new GsrsPasswordHasher();

private final Salter salter = new LegacyTypeSalter(hasher, SALT_PREFIX);

@Test
void testGenerateSalt() {
String salt1 = salter.generateSalt();
Assertions.assertNotNull(salt1);
System.out.printf("salt: %s\n", salt1);
}

@Test
void testGenerateOwnSalt() {
String salt1 = salter.generateSalt();
Assertions.assertTrue(salter.mayBeOneOfMine(salt1));
}

@Test
void testGenerateNotOwnSalt() {
String salt1 = salter.generateSalt();
String changedSalt = salt1.replace('G', 'N');
Assertions.assertFalse(salter.mayBeOneOfMine(changedSalt));
}

}
2 changes: 1 addition & 1 deletion gsrs-core-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
62 changes: 62 additions & 0 deletions gsrs-core/src/main/java/gsrs/util/GsrsPasswordHasher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package gsrs.util;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

@Slf4j
public class GsrsPasswordHasher implements Hasher {

String preferredHashAlgorithm = "PBKDF2";
static int iterations = 1000;
static String characterSet ="utf8";

private final static String HASHING_ALGORITHM = "PBKDF2WithHmacSHA512";

@Override
public String getHashType() {
return this.preferredHashAlgorithm;
}

@Override
public String hash(String... values) {
if (values == null) {
return null;
}
try {
if(preferredHashAlgorithm.equals("PBKDF2")) {
return hash(values[0], values.length > 1 ? values[1] : null, iterations);
}
MessageDigest md = MessageDigest.getInstance(preferredHashAlgorithm);
for (String v : values) {
md.update(v.getBytes(characterSet));
}
return toHex(md.digest());
} catch (Exception ex) {
log.error("Can't generate hash!", ex);
throw new RuntimeException(ex);
}
}

public static String toHex(byte[] d) {
StringBuilder sb = new StringBuilder();
for (byte b : d) {
sb.append(String.format("%1$02x", b & 0xff));
}
return sb.toString();
}

public static String hash(String input, String salt, int iterations) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException {
PBEKeySpec spec = new PBEKeySpec(input.toCharArray(), salt != null ? salt.getBytes(characterSet) :
input.getBytes(characterSet), iterations, 64 * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance(HASHING_ALGORITHM);

byte[] hash = skf.generateSecret(spec).getEncoded();
return toHex(hash);
}
}
8 changes: 8 additions & 0 deletions gsrs-core/src/main/java/gsrs/util/Hasher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gsrs.util;

public interface Hasher {

String getHashType();

String hash(String... values);
}
34 changes: 34 additions & 0 deletions gsrs-core/src/main/java/gsrs/util/LegacyTypeSalter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gsrs.util;

import gov.nih.ncats.common.util.TimeUtil;
import lombok.Data;

import static java.lang.String.valueOf;

@Data
public class LegacyTypeSalter implements Salter {

Hasher hasher;

String prefix = "";

public LegacyTypeSalter(Hasher newHasher, String newPrefix) {
hasher = newHasher;
prefix = newPrefix;
}
@Override
public void setHasher(Hasher hasher) {
this.hasher = hasher;
}

@Override
public String generateSalt() {
String text = "---" + TimeUtil.getCurrentDate().toString() + "---" + String.valueOf(Math.random()) + "---";
return prefix + hasher.hash(text);
}

@Override
public boolean mayBeOneOfMine(String testHash) {
return testHash != null && testHash.startsWith(prefix);
}
}
10 changes: 10 additions & 0 deletions gsrs-core/src/main/java/gsrs/util/Salter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package gsrs.util;

public interface Salter {

void setHasher(Hasher hasher);

String generateSalt();

boolean mayBeOneOfMine(String testHash);
}
2 changes: 1 addition & 1 deletion gsrs-data-exchange/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-discovery/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>gov.nih.ncats</groupId>
<artifactId>gsrs-discovery</artifactId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
<name>gsrs-discovery</name>
<description>Demo project for Spring Boot</description>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-rest-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-scheduled-tasks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-spring-akka/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion gsrs-spring-boot-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>gsrs-spring-boot</artifactId>
<groupId>gov.nih.ncats</groupId>
<version>3.1</version>
<version>3.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Loading

0 comments on commit bcd7f2c

Please sign in to comment.