Skip to content

Commit

Permalink
Encryption updates
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorBalog-Eng committed Feb 19, 2024
1 parent 10ae831 commit bba7510
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 5 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ All notable changes to this project will be documented in this file.
### Added

- Audit logs stored in database
- Column encrypted using AES/GCM/NoPadding
- New endpoint for fetching audit events

- requires to set environment variable with AES256-SECRET-KEY used in encryption algorithm

### Changed

- Using JFrog for IDS dependency management
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ application.connectorUUID=
application.dapsJWKSUrl=
```
* Choose one of 2 profiles: SENDER or RECEIVER.
* Set environment variable with following name: *AES256-SECRET-KEY* with any value (MyPassword for example). This will be used for encrypting AuditLog column in DB.
* Start application

### Creating docker image
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-https-form/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-https-header/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-https-mixed/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-idscp2-form/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-idscp2-header/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/https-idscp2-mixed/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/ws-idscp2/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/test-cases/ws-ws/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BROKER_URL=https://broker.ids.isst.fraunhofer.de/infrastructure

AES256-SECRET-KEY=TRUEConnectorAESSecretKey123

#SSL settings
KEYSTORE_NAME=ssl-server.jks
KEY_PASSWORD=changeit
Expand Down
4 changes: 3 additions & 1 deletion doc/AUDIT.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Audit events in TRUE Connector

Audit events are stored in database (H2 with default configuration, possible to replace with PostgreSQL), this way tampering of the logs is prohibited. Entries in database are done only by the Execution Core Container, and ECC exposes protected endpoint, for API user, to fetch all audit logs, or audit logs for specific date:
Audit events are stored in database (H2 with default configuration, possible to replace with PostgreSQL), this way tampering of the logs is prohibited. Entries in database are done only by the Execution Core Container. Column for storing auditLog entry is encrypted using *AES/GCM/NoPadding* algorithm which requires user to set valid password. It must be done using environment variable with following name: *AES256-SECRET-KEY*. </br>
When ECC inserts audit entry into Database, AuditLog value will be encrypted using provided algorithm, and when data is requested, it will be decrypted.</br>
ECC exposes protected endpoint, for API user, to fetch all audit logs, or audit logs for specific date:

```
https://localhost:8090/api/audit/
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/it/eng/idsa/businesslogic/entity/AuditLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import com.fasterxml.jackson.annotation.JsonProperty;

import it.eng.idsa.businesslogic.util.AES256Static;

@Entity
@Table(name = "AuditLogs")
public class AuditLog {
Expand All @@ -28,7 +30,7 @@ public AuditLog() {
}

public AuditLog(String event) {
this.event = event;
this.event = AES256Static.encrypt(event);
this.timestamp = LocalDateTime.now();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import it.eng.idsa.businesslogic.entity.AuditLog;
import it.eng.idsa.businesslogic.repository.AuditEventRepository;
import it.eng.idsa.businesslogic.util.AES256Static;

@Service
public class AuditEventService {
Expand All @@ -21,13 +23,27 @@ public AuditLog saveAuditEvent(AuditLog auditEvent) {
}

public List<AuditLog> getAllAuditEvents() {
return auditRepository.findAll();
return auditRepository.findAll()
.parallelStream()
.map(this::decryptAuditLog)
.collect(Collectors.toList());
}

public List<AuditLog> getAuditEventsForDate(LocalDate date) {
LocalDateTime startOfDay = date.atStartOfDay(); // Start of the day
LocalDateTime endOfDay = date.atTime(LocalTime.MAX); // End of the day

return auditRepository.findByTimestampBetween(startOfDay, endOfDay);
return auditRepository.findByTimestampBetween(startOfDay, endOfDay)
.parallelStream()
.map(this::decryptAuditLog)
.collect(Collectors.toList());
}

private AuditLog decryptAuditLog(AuditLog auditLog) {
AuditLog a = new AuditLog();
a.setId(auditLog.getId());
a.setEvent(AES256Static.decrypt(auditLog.getEvent()));
a.setTimestamp(auditLog.getTimestamp());
return a;
}
}
140 changes: 140 additions & 0 deletions src/main/java/it/eng/idsa/businesslogic/util/AES256.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package it.eng.idsa.businesslogic.util;

import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AES256 {

private static final Logger logger = LoggerFactory.getLogger(AES256.class);

private static final int KEY_LENGTH = 256;
private static final int ITERATION_COUNT = 65536;
private static String secretKey;
private static final String salt = "hd2y3vxlLv";
private static String algorithm = "AES/GCM/NoPadding";

static {
secretKey = ObjectUtils.isNotEmpty(System.getenv("AES256-SECRET-KEY")) ?
System.getenv("AES256-SECRET-KEY") : "FPrnUtKJIGX1EMs";
}

public static String encrypt(String strToEncrypt) {
try {
SecureRandom secureRandom = new SecureRandom();
byte[] ivBytes = new byte[16];
secureRandom.nextBytes(ivBytes);

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, ivBytes);

Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec);

byte[] cipherText = cipher.doFinal(strToEncrypt.getBytes("UTF-8"));
byte[] encryptedData = new byte[ivBytes.length + cipherText.length];
System.arraycopy(ivBytes, 0, encryptedData, 0, ivBytes.length);
System.arraycopy(cipherText, 0, encryptedData, ivBytes.length, cipherText.length);

return Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
logger.error("Error while encrypting", e);
return null;
}
}

public static String decrypt(String strToDecrypt) {
try {
byte[] encryptedData = Base64.getDecoder().decode(strToDecrypt);
byte[] ivBytes = new byte[16];
System.arraycopy(encryptedData, 0, ivBytes, 0, ivBytes.length);

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, ivBytes);

Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);

byte[] cipherText = new byte[encryptedData.length - 16];
System.arraycopy(encryptedData, 16, cipherText, 0, cipherText.length);

byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText, "UTF-8");
} catch (Exception e) {
logger.error("Error while decrypting", e);
return null;
}
}

/*
public static String encrypt(String strToEncrypt) {
try {
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
byte[] cipherText = cipher.doFinal(strToEncrypt.getBytes("UTF-8"));
byte[] encryptedData = new byte[iv.length + cipherText.length];
System.arraycopy(iv, 0, encryptedData, 0, iv.length);
System.arraycopy(cipherText, 0, encryptedData, iv.length, cipherText.length);
return Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
logger.error("Error while encrypting", e);
return null;
}
}
public static String decrypt(String strToDecrypt) {
try {
byte[] encryptedData = Base64.getDecoder().decode(strToDecrypt);
byte[] iv = new byte[16];
System.arraycopy(encryptedData, 0, iv, 0, iv.length);
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
byte[] cipherText = new byte[encryptedData.length - 16];
System.arraycopy(encryptedData, 16, cipherText, 0, cipherText.length);
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText, "UTF-8");
} catch (Exception e) {
logger.error("Error while decrypting", e);
return null;
}
}
*/
}

0 comments on commit bba7510

Please sign in to comment.