Skip to content

Commit

Permalink
make Cryptographers speak Business talk
Browse files Browse the repository at this point in the history
  • Loading branch information
bhuism committed Dec 3, 2024
1 parent 2b73cd0 commit 9062e94
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 42 deletions.
12 changes: 4 additions & 8 deletions src/main/java/nl/ictu/controller/v1/ExchangeIdentifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import static nl.ictu.pseudoniemenservice.generated.server.model.WsIdentifierTypes.BSN;
import static nl.ictu.pseudoniemenservice.generated.server.model.WsIdentifierTypes.ORGANISATION_PSEUDO;
import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED;
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;

@RequiredArgsConstructor
@RestController
Expand Down Expand Up @@ -47,7 +47,7 @@ public ResponseEntity<WsExchangeIdentifierResponse> exchangeIdentifierForIdentif
return ResponseEntity.ok(convertPseudoToBEsn(wsIdentifierRequest.getValue(), recipientOIN));

} else {
return ResponseEntity.status(NOT_IMPLEMENTED).build();
return ResponseEntity.status(UNPROCESSABLE_ENTITY).build();
}


Expand All @@ -59,9 +59,7 @@ private WsExchangeIdentifierResponse convertBsnToPseudo(final String bsn, final

identifier.setBsn(bsn);

final String encode = identifierConverter.encode(identifier);

final String oinNencyptedIdentifier = aesGcmSivCryptographer.encrypt(encode, oin);
final String oinNencyptedIdentifier = aesGcmSivCryptographer.encrypt(identifier, oin);

final WsExchangeIdentifierResponse wsExchangeTokenForIdentifier200Response = new WsExchangeIdentifierResponse();

Expand All @@ -78,9 +76,7 @@ private WsExchangeIdentifierResponse convertBsnToPseudo(final String bsn, final

private WsExchangeIdentifierResponse convertPseudoToBEsn(final String pseudo, final String oin) throws IOException, InvalidCipherTextException {

final String encodedIdentifier = aesGcmSivCryptographer.decrypt(pseudo, oin);

final Identifier identifier = identifierConverter.decode(encodedIdentifier);
final Identifier identifier = aesGcmSivCryptographer.decrypt(pseudo, oin);

final WsExchangeIdentifierResponse wsExchangeTokenForIdentifier200Response = new WsExchangeIdentifierResponse();

Expand Down
8 changes: 3 additions & 5 deletions src/main/java/nl/ictu/controller/v1/ExchangeToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
import nl.ictu.service.AesGcmSivCryptographer;
import nl.ictu.service.IdentifierConverter;
import nl.ictu.service.TokenConverter;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import static nl.ictu.pseudoniemenservice.generated.server.model.WsIdentifierTypes.BSN;
import static nl.ictu.pseudoniemenservice.generated.server.model.WsIdentifierTypes.ORGANISATION_PSEUDO;
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;

@Slf4j
@RequiredArgsConstructor
Expand Down Expand Up @@ -60,16 +60,14 @@ public ResponseEntity<WsExchangeTokenResponse> exchangeTokenForIdentifier(final

identifier.setBsn(token.getBsn());

final String encode = identifierConverter.encode(identifier);

final String encrypt = aesGcmSivCryptographer.encrypt(encode, callerOIN);
final String encrypt = aesGcmSivCryptographer.encrypt(identifier, callerOIN);

wsIdentifier.setType(ORGANISATION_PSEUDO);
wsIdentifier.setValue(encrypt);

}
default -> {
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).build();
return ResponseEntity.status(UNPROCESSABLE_ENTITY).build();
}

}
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/nl/ictu/controller/v1/GetToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
import nl.ictu.service.AesGcmSivCryptographer;
import nl.ictu.service.IdentifierConverter;
import nl.ictu.service.TokenConverter;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;

@RestController
@RequiredArgsConstructor
public final class GetToken implements GetTokenApi, VersionOneController {
Expand Down Expand Up @@ -47,15 +48,13 @@ public ResponseEntity<WsGetTokenResponse> getToken(final String callerOIN, final

final String orgPseudoEncryptedString = wsGetTokenRequest.getIdentifier().getValue();

final String orgPseudoString = aesGcmSivCryptographer.decrypt(orgPseudoEncryptedString, wsGetTokenRequest.getRecipientOIN());

final Identifier decodedIdentifier = identifierConverter.decode(orgPseudoString);
final Identifier decodedIdentifier = aesGcmSivCryptographer.decrypt(orgPseudoEncryptedString, wsGetTokenRequest.getRecipientOIN());

token.setBsn(decodedIdentifier.getBsn());

}
default -> {
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).build();
return ResponseEntity.status(UNPROCESSABLE_ENTITY).build();
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/nl/ictu/service/AesGcmCryptographerImpl.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nl.ictu.service;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.SneakyThrows;
import nl.ictu.configuration.PseudoniemenServiceProperties;
import nl.ictu.utils.ByteArrayUtils;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -42,15 +43,12 @@ public class AesGcmCryptographerImpl implements AesGcmCryptographer {
private final PseudoniemenServiceProperties pseudoniemenServiceProperties;

@SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
@SneakyThrows
public AesGcmCryptographerImpl(final PseudoniemenServiceProperties pseudoniemenServicePropertiesArg) {

pseudoniemenServiceProperties = pseudoniemenServicePropertiesArg;

try {
sha256Digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
sha256Digest = MessageDigest.getInstance("SHA-256");

if (!StringUtils.hasText(pseudoniemenServiceProperties.getTokenPrivateKey())) {
throw new RuntimeException("Please set a private token key");
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/nl/ictu/service/AesGcmSivCryptographer.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package nl.ictu.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import nl.ictu.Identifier;
import org.bouncycastle.crypto.InvalidCipherTextException;

import java.io.IOException;

public interface AesGcmSivCryptographer {

String encrypt(String plaintext, String salt) throws InvalidCipherTextException;
String encrypt(Identifier identifier, String salt) throws InvalidCipherTextException, IOException;

String decrypt(String ciphertext, String salt) throws InvalidCipherTextException;
Identifier decrypt(String ciphertext, String salt) throws InvalidCipherTextException, JsonProcessingException;
}
30 changes: 19 additions & 11 deletions src/main/java/nl/ictu/service/AesGcmSivCryptographerImpl.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package nl.ictu.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import nl.ictu.Identifier;
import nl.ictu.configuration.PseudoniemenServiceProperties;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
Expand All @@ -11,9 +14,9 @@
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;

Expand All @@ -38,18 +41,17 @@ public class AesGcmSivCryptographerImpl implements AesGcmSivCryptographer {

private final MessageDigest sha256Digest;

private final IdentifierConverter identifierConverter;

@SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
public AesGcmSivCryptographerImpl(final PseudoniemenServiceProperties pseudoniemenServicePropertiesArg) {
@SneakyThrows
public AesGcmSivCryptographerImpl(final PseudoniemenServiceProperties pseudoniemenServicePropertiesArg, final IdentifierConverter identifierConverterArg) {

pseudoniemenServiceProperties = pseudoniemenServicePropertiesArg;
identifierConverter = identifierConverterArg;

aesEngine = new AESEngine();

try {
this.sha256Digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
sha256Digest = MessageDigest.getInstance("SHA-256");

if (!StringUtils.hasText(pseudoniemenServiceProperties.getIdentifierPrivateKey())) {
throw new RuntimeException("Please set a private identifier key");
Expand All @@ -74,7 +76,9 @@ private AEADParameters createSecretKey(final String salt) {
}

@Override
public String encrypt(final String plaintext, final String salt) throws InvalidCipherTextException {
public String encrypt(final Identifier identifier, final String salt) throws InvalidCipherTextException, IOException {

final String plaintext = identifierConverter.encode(identifier);

final GCMSIVBlockCipher cipher = new GCMSIVBlockCipher(aesEngine);

Expand All @@ -95,7 +99,7 @@ public String encrypt(final String plaintext, final String salt) throws InvalidC
}

@Override
public String decrypt(final String ciphertextString, final String salt) throws InvalidCipherTextException {
public Identifier decrypt(final String ciphertextString, final String salt) throws InvalidCipherTextException, JsonProcessingException {

final GCMSIVBlockCipher cipher = new GCMSIVBlockCipher(aesEngine);

Expand All @@ -111,7 +115,11 @@ public String decrypt(final String ciphertextString, final String salt) throws I

cipher.reset();

return new String(plaintext, StandardCharsets.UTF_8);
final String encodedIdentifier = new String(plaintext, StandardCharsets.UTF_8);

final Identifier identifier = identifierConverter.decode(encodedIdentifier);

return identifier;

}

Expand Down
23 changes: 17 additions & 6 deletions src/test/java/nl/ictu/service/TestAesGcmSivCryptographer.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package nl.ictu.service;


import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import nl.ictu.Identifier;
import nl.ictu.configuration.PseudoniemenServiceProperties;
import org.junit.jupiter.api.Test;
import org.springframework.test.context.ActiveProfiles;
Expand All @@ -20,7 +22,10 @@
@ActiveProfiles("test")
public class TestAesGcmSivCryptographer {

private AesGcmSivCryptographer aesGcmSivCryptographer = new AesGcmSivCryptographerImpl(new PseudoniemenServiceProperties().setIdentifierPrivateKey("QTBtVEhLN3EwMHJ3QXN1ZUFqNzVrT3hDQTBIWWNIZTU="));
private AesGcmSivCryptographer aesGcmSivCryptographer = new AesGcmSivCryptographerImpl(
new PseudoniemenServiceProperties().setIdentifierPrivateKey("QTBtVEhLN3EwMHJ3QXN1ZUFqNzVrT3hDQTBIWWNIZTU="),
new IdentifierConverterImpl(new ObjectMapper())
);

private Set<String> testStrings = new HashSet<>(Arrays.asList("a", "bb", "dsv", "ghad", "dhaht", "uDg5Av", "d93fdvv", "dj83hzHo", "38iKawKv9", "dk(gkzm)Mh", "gjk)s3$g9cQ"));

Expand All @@ -30,9 +35,12 @@ public void testEncyptDecryptForDifferentStringLengths() {
testStrings.forEach(plain -> {

try {
final String crypted = aesGcmSivCryptographer.encrypt(plain, "helloHowAreyo12345678");
final String actual = aesGcmSivCryptographer.decrypt(crypted, "helloHowAreyo12345678");
assertThat(actual).isEqualTo(plain);
final Identifier identifier = new Identifier();
identifier.setBsn(plain);

final String crypted = aesGcmSivCryptographer.encrypt(identifier, "helloHowAreyo12345678");
final Identifier actual = aesGcmSivCryptographer.decrypt(crypted, "helloHowAreyo12345678");
assertThat(actual.getBsn()).isEqualTo(plain);
} catch (final Exception e) {
throw new RuntimeException(e);
}
Expand All @@ -48,8 +56,11 @@ public void testCiphertextIsTheSameForSamePlaintext() throws Exception {
// The same plaintext message
String plaintext = "This is a test message to ensure ciphertext is different!";

String encryptedMessage1 = aesGcmSivCryptographer.encrypt(plaintext, "aniceSaltGorYu");
String encryptedMessage2 = aesGcmSivCryptographer.encrypt(plaintext, "aniceSaltGorYu");
final Identifier identifier = new Identifier();
identifier.setBsn(plaintext);

String encryptedMessage1 = aesGcmSivCryptographer.encrypt(identifier, "aniceSaltGorYu");
String encryptedMessage2 = aesGcmSivCryptographer.encrypt(identifier, "aniceSaltGorYu");

// Assert that the two ciphertexts are different
assertThat(encryptedMessage1).isEqualTo(encryptedMessage2);
Expand Down

0 comments on commit 9062e94

Please sign in to comment.