Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dataEncryption): removes lombok from data-encryption module #179

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,93 +20,91 @@
*/
package org.eclipse.tractusx.edc.data.encryption.algorithms.aes;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.eclipse.tractusx.edc.data.encryption.algorithms.CryptoAlgorithm;
import org.eclipse.tractusx.edc.data.encryption.data.CryptoDataFactory;
import org.eclipse.tractusx.edc.data.encryption.data.DecryptedData;
import org.eclipse.tractusx.edc.data.encryption.data.EncryptedData;
import org.eclipse.tractusx.edc.data.encryption.key.AesKey;
import org.eclipse.tractusx.edc.data.encryption.util.ArrayUtil;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Objects;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.eclipse.tractusx.edc.data.encryption.algorithms.CryptoAlgorithm;
import org.eclipse.tractusx.edc.data.encryption.data.CryptoDataFactory;
import org.eclipse.tractusx.edc.data.encryption.data.DecryptedData;
import org.eclipse.tractusx.edc.data.encryption.data.EncryptedData;
import org.eclipse.tractusx.edc.data.encryption.key.AesKey;
import org.eclipse.tractusx.edc.data.encryption.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;

public class AesAlgorithm implements CryptoAlgorithm<AesKey> {

private static final String AES_GCM = "AES/GCM/NoPadding";
private static final String AES = "AES";
private static final Object MONITOR = new Object();
private static final String AES_GCM = "AES/GCM/NoPadding";
private static final String AES = "AES";
private static final Object MONITOR = new Object();

private final SecureRandom secureRandom;

private final SecureRandom secureRandom;
private final CryptoDataFactory cryptoDataFactory;
private AesInitializationVectorIterator initializationVectorIterator;

@NonNull private final CryptoDataFactory cryptoDataFactory;
private AesInitializationVectorIterator initializationVectorIterator;
public AesAlgorithm(CryptoDataFactory cryptoDataFactory) {
this.cryptoDataFactory = Objects.requireNonNull(cryptoDataFactory);

@SneakyThrows
public AesAlgorithm(@NotNull CryptoDataFactory cryptoDataFactory) {
this.cryptoDataFactory = cryptoDataFactory;
// We use new SecureRandom() and not SecureRandom.getInstanceStrong(), as the second one
// would use a blocking algorithm, which leads to an increased encryption time of up to 3
// minutes. Since we have already used /dev/urandom, which only provides pseudo-randomness and
// is also non-blocking, switching to a non-blocking algorithm should not matter here either.
this.secureRandom = new SecureRandom();
this.initializationVectorIterator = new AesInitializationVectorIterator(this.secureRandom);
}

// We use new SecureRandom() and not SecureRandom.getInstanceStrong(), as the second one
// would use a blocking algorithm, which leads to an increased encryption time of up to 3
// minutes. Since we have already used /dev/urandom, which only provides pseudo-randomness and
// is also non-blocking, switching to a non-blocking algorithm should not matter here either.
this.secureRandom = new SecureRandom();
this.initializationVectorIterator = new AesInitializationVectorIterator(this.secureRandom);
}
@Override
public synchronized EncryptedData encrypt(DecryptedData data, AesKey key)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {

@Override
public synchronized EncryptedData encrypt(DecryptedData data, AesKey key)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
final byte[] initializationVector;
synchronized (MONITOR) {
if (!initializationVectorIterator.hasNext()) {
initializationVectorIterator = new AesInitializationVectorIterator(this.secureRandom);
}

final byte[] initializationVector;
synchronized (MONITOR) {
if (!initializationVectorIterator.hasNext()) {
initializationVectorIterator = new AesInitializationVectorIterator(this.secureRandom);
}
initializationVector = initializationVectorIterator.next();
}

initializationVector = initializationVectorIterator.next();
Cipher cipher = Cipher.getInstance(AES_GCM, new BouncyCastleProvider());
final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
final GCMParameterSpec gcmParameterSpec =
new GCMParameterSpec(16 * 8 /* =128 */, initializationVector);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
byte[] encrypted = cipher.doFinal(data.getBytes());
byte[] encryptedWithVector = ArrayUtil.concat(initializationVector, encrypted);

return cryptoDataFactory.encryptedFromBytes(encryptedWithVector);
}

Cipher cipher = Cipher.getInstance(AES_GCM, new BouncyCastleProvider());
final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
final GCMParameterSpec gcmParameterSpec =
new GCMParameterSpec(16 * 8 /* =128 */, initializationVector);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
byte[] encrypted = cipher.doFinal(data.getBytes());
byte[] encryptedWithVector = ArrayUtil.concat(initializationVector, encrypted);

return cryptoDataFactory.encryptedFromBytes(encryptedWithVector);
}

@Override
public DecryptedData decrypt(EncryptedData data, AesKey key)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
byte[] encryptedWithVector = data.getBytes();
byte[] initializationVector = ArrayUtil.subArray(encryptedWithVector, 0, 16);
byte[] encrypted = ArrayUtil.subArray(encryptedWithVector, 16, encryptedWithVector.length - 16);

Cipher cipher = Cipher.getInstance(AES_GCM, new BouncyCastleProvider());
final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
final GCMParameterSpec gcmParameterSpec =
new GCMParameterSpec(16 * 8 /* =128 */, initializationVector);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
byte[] decryptedData = cipher.doFinal(encrypted);
return cryptoDataFactory.decryptedFromBytes(decryptedData);
}

public String getAlgorithm() {
return this.secureRandom.getAlgorithm();
}
@Override
public DecryptedData decrypt(EncryptedData data, AesKey key)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
byte[] encryptedWithVector = data.getBytes();
byte[] initializationVector = ArrayUtil.subArray(encryptedWithVector, 0, 16);
byte[] encrypted = ArrayUtil.subArray(encryptedWithVector, 16, encryptedWithVector.length - 16);

Cipher cipher = Cipher.getInstance(AES_GCM, new BouncyCastleProvider());
final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
final GCMParameterSpec gcmParameterSpec =
new GCMParameterSpec(16 * 8 /* =128 */, initializationVector);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
byte[] decryptedData = cipher.doFinal(encrypted);
return cryptoDataFactory.decryptedFromBytes(decryptedData);
}

public String getAlgorithm() {
return this.secureRandom.getAlgorithm();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,51 +20,50 @@
*/
package org.eclipse.tractusx.edc.data.encryption.algorithms.aes;

import org.eclipse.tractusx.edc.data.encryption.util.ArrayUtil;

import java.security.SecureRandom;
import java.util.Iterator;
import java.util.NoSuchElementException;
import lombok.SneakyThrows;
import org.eclipse.tractusx.edc.data.encryption.util.ArrayUtil;

public class AesInitializationVectorIterator implements Iterator<byte[]> {

public static final int RANDOM_SIZE = 12;
public static final int COUNTER_SIZE = 4;

private final ByteCounter counter;
public static final int RANDOM_SIZE = 12;
public static final int COUNTER_SIZE = 4;

private SecureRandom secureRandom;
private final ByteCounter counter;

public AesInitializationVectorIterator(SecureRandom secureRandom) {
this.counter = new ByteCounter(COUNTER_SIZE);
this.secureRandom = secureRandom;
}
private SecureRandom secureRandom;

public AesInitializationVectorIterator(ByteCounter byteCounter) {
this.counter = byteCounter;
}
public AesInitializationVectorIterator(SecureRandom secureRandom) {
this.counter = new ByteCounter(COUNTER_SIZE);
this.secureRandom = secureRandom;
}

@Override
public boolean hasNext() {
return !counter.isMaxed();
}
public AesInitializationVectorIterator(ByteCounter byteCounter) {
this.counter = byteCounter;
}

@Override
public byte[] next() {
if (counter.isMaxed()) {
throw new NoSuchElementException(getClass().getSimpleName() + " has no more elements");
@Override
public boolean hasNext() {
return !counter.isMaxed();
}

byte[] random = getNextRandom();
counter.increment();
@Override
public byte[] next() {
if (counter.isMaxed()) {
throw new NoSuchElementException(getClass().getSimpleName() + " has no more elements");
}

return ArrayUtil.concat(random, counter.getBytes());
}
byte[] random = getNextRandom();
counter.increment();

@SneakyThrows
public byte[] getNextRandom() {
byte[] newVector = new byte[RANDOM_SIZE];
secureRandom.nextBytes(newVector);
return newVector;
}
return ArrayUtil.concat(random, counter.getBytes());
}

public byte[] getNextRandom() {
byte[] newVector = new byte[RANDOM_SIZE];
secureRandom.nextBytes(newVector);
return newVector;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,63 +19,69 @@
*/
package org.eclipse.tractusx.edc.data.encryption.algorithms.aes;

/** Big Endian Byte Counter */
/**
* Big Endian Byte Counter
*/
public class ByteCounter {

private final byte[] counter;

/**
* Constructs a new ByteCounter with the given number of bytes. E.g. a ByteCounter with 4 bytes
* will have a counter value of [0, 0, 0, 0].
*
* @param size number of bytes used by the counter
*/
public ByteCounter(int size) {
this.counter = new byte[size];
}
private final byte[] counter;

/**
* Constructs a new ByteCounter with the given counter value. Counter cannot grow bigger than the
* size of the array.
*
* @param counter initial counter value
*/
public ByteCounter(byte[] counter) {
this.counter = counter;
}
/**
* Constructs a new ByteCounter with the given number of bytes. E.g. a ByteCounter with 4 bytes
* will have a counter value of [0, 0, 0, 0].
*
* @param size number of bytes used by the counter
*/
public ByteCounter(int size) {
this.counter = new byte[size];
}

/** Returns the counter value as a byte array. */
public byte[] getBytes() {
return counter;
}
/**
* Constructs a new ByteCounter with the given counter value. Counter cannot grow bigger than the
* size of the array.
*
* @param counter initial counter value
*/
public ByteCounter(byte[] counter) {
this.counter = counter;
}

/** Returns true if counter is maxed */
public boolean isMaxed() {
for (byte b : counter) {
if (b != (byte) 0xff) return false;
/**
* Returns the counter value as a byte array.
*/
public byte[] getBytes() {
return counter;
}
return true;
}

/**
* Increments the counter by one.
*
* @throws IllegalStateException if the counter is already maxed
*/
public void increment() {
incrementByte(counter.length - 1);
}
/**
* Returns true if counter is maxed
*/
public boolean isMaxed() {
for (byte b : counter) {
if (b != (byte) 0xff) return false;
}
return true;
}

private void incrementByte(int index) {
if (isMaxed()) {
throw new IllegalStateException("Counter is already maxed");
/**
* Increments the counter by one.
*
* @throws IllegalStateException if the counter is already maxed
*/
public void increment() {
incrementByte(counter.length - 1);
}

if (counter[index] == (byte) 0xff) {
incrementByte(index - 1);
counter[index] = (byte) 0x00;
} else {
counter[index]++;
private void incrementByte(int index) {
if (isMaxed()) {
throw new IllegalStateException("Counter is already maxed");
}

if (counter[index] == (byte) 0xff) {
incrementByte(index - 1);
counter[index] = (byte) 0x00;
} else {
counter[index]++;
}
}
}
}
Loading