finished config streaming out/in

This commit is contained in:
anhefti 2019-05-11 21:42:33 +02:00
parent 06da2d026b
commit 27b75062cc
12 changed files with 326 additions and 309 deletions

View file

@ -8,14 +8,8 @@
package ch.ethz.seb.sebserver.gbl.async;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
@ -72,41 +66,4 @@ public class AsyncService {
momoized);
}
public void pipeToOutputStream(
final OutputStream output,
final Consumer<PipedOutputStream> consumer) {
this.asyncRunner.runAsync(() -> {
PipedOutputStream pout = null;
PipedInputStream pin = null;
try {
pout = new PipedOutputStream();
pin = new PipedInputStream(pout);
consumer.accept(pout);
IOUtils.copyLarge(pin, output);
pin.close();
pout.flush();
pout.close();
} catch (final IOException e) {
log.error("Error while pipe stream data: ", e);
} finally {
try {
pin.close();
} catch (final IOException e1) {
log.error("Failed to close PipedInputStream: ", e1);
}
try {
pout.close();
} catch (final IOException e1) {
log.error("Failed to close PipedOutputStream: ", e1);
}
}
});
}
}

View file

@ -181,6 +181,12 @@ public final class Result<T> {
}
}
public void ifPresent(final Consumer<T> consumer) {
if (this.value != null) {
consumer.accept(this.value);
}
}
/** Use this to map a given Result of type T to another Result of type U
* within a given mapping function.
*

View file

@ -10,10 +10,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Set;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy;
/** Interface for a SEB Configuration encryption and decryption strategy.
@ -27,32 +25,14 @@ public interface SebConfigCryptor {
* @return Set of strategies a concrete implementation is supporting */
Set<Strategy> strategies();
/** Encrypt a given SEB configuration plain text representation within the given SebConfigEncryptionContext
*
* @param plainTextConfig SEB configuration plain text representation
* @param context SebConfigEncryptionContext containing additional data if needed
* @return Result of encrypted data within a ByteBuffer or reference to an Exception on error case */
Result<ByteBuffer> encrypt(
final CharSequence plainTextConfig,
final SebConfigEncryptionContext context);
/** Decrypt a given encrypted SEB configuration that has been encrypted by one of the supported strategies.
*
* @param cipher the encrypted SEB configuration cipher(text) within a ByteBuffer
* @param context SebConfigEncryptionContext containing additional data if needed
* @return Result of decrypted SEB configuration within a ByteBuffer or reference to an Exception on error case. */
Result<ByteBuffer> decrypt(
final ByteBuffer cipher,
final SebConfigEncryptionContext context);
void encrypt(
final OutputStream encryptedOutput,
final InputStream plainTextInputStream,
final OutputStream output,
final InputStream input,
final SebConfigEncryptionContext context);
void decrypt(
final OutputStream plainTextOutput,
final InputStream cipherInputStream,
final OutputStream output,
final InputStream input,
final SebConfigEncryptionContext context);
}

View file

@ -29,8 +29,9 @@ public interface SebConfigEncryptionContext {
/** Get a defined Certificate if supported.
*
* @param key The key of the Certificate to get
* @return a defined Certificate
* @throws UnsupportedOperationException if not supported */
Certificate getCertificate();
Certificate getCertificate(CharSequence key);
}

View file

@ -10,12 +10,10 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.util.function.Function;
import java.util.function.Supplier;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public interface SebConfigEncryptionService {
@ -60,21 +58,18 @@ public interface SebConfigEncryptionService {
* @param plainTextConfig plainTextConfig plain text SEB Configuration as CharSequence
* @return Result of plain text SEB Configuration within a ByteBuffer or a reference to an Exception on error
* case */
Result<ByteBuffer> plainText(CharSequence plainTextConfig);
// void streamPlainData(
// final OutputStream output,
// final InputStream input);
void streamEncryption(
void streamEncrypted(
final OutputStream output,
final InputStream input,
final Strategy strategy,
final CharSequence password);
SebConfigEncryptionContext context);
Result<ByteBuffer> encryptWithCertificate(
CharSequence plainTextConfig,
Strategy strategy,
Certificate certificate);
Result<ByteBuffer> decrypt(
ByteBuffer cipher,
void streamDecrypted(
final OutputStream output,
final InputStream input,
Supplier<CharSequence> passwordSupplier,
Function<CharSequence, Certificate> certificateStore);

View file

@ -16,4 +16,5 @@ public interface ZipService {
void write(OutputStream out, InputStream in);
void read(OutputStream out, InputStream in);
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionContext;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy;
@Lazy
@Component
@WebServiceProfile
public class NoneEncryptor implements SebConfigCryptor {
private static final Logger log = LoggerFactory.getLogger(NoneEncryptor.class);
private static final Set<Strategy> STRATEGIES = Utils.immutableSetOf(
Strategy.PLAIN_TEXT);
@Override
public Set<Strategy> strategies() {
return STRATEGIES;
}
@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void encrypt(
final OutputStream output,
final InputStream input,
final SebConfigEncryptionContext context) {
if (log.isDebugEnabled()) {
log.debug("No encryption, write plain input data");
}
try {
IOUtils.copyLarge(input, output);
input.close();
output.flush();
output.close();
} catch (final IOException e) {
log.error("Error while streaming plain data to output: ", e);
} finally {
try {
input.close();
} catch (final IOException e) {
log.error("Failed to close InputStream");
}
if (log.isDebugEnabled()) {
log.debug("Finished with no encryption. Close input stream");
}
}
}
@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void decrypt(
final OutputStream output,
final InputStream input,
final SebConfigEncryptionContext context) {
if (log.isDebugEnabled()) {
log.debug("No decryption, read plain input data");
}
try {
IOUtils.copyLarge(input, output);
input.close();
output.flush();
output.close();
} catch (final IOException e) {
log.error("Error while streaming plain data to output: ", e);
} finally {
try {
input.close();
} catch (final IOException e) {
log.error("Failed to close InputStream");
}
if (log.isDebugEnabled()) {
log.debug("Finished with no encryption. Close input stream");
}
}
}
}

View file

@ -11,13 +11,12 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Set;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.cryptonode.jncryptor.AES256JNCryptorInputStream;
import org.cryptonode.jncryptor.AES256JNCryptorOutputStream;
import org.cryptonode.jncryptor.CryptorException;
import org.cryptonode.jncryptor.JNCryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
@ -26,7 +25,6 @@ import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionContext;
@ -43,35 +41,11 @@ public class PasswordEncryptor implements SebConfigCryptor {
Strategy.PASSWORD_PSWD,
Strategy.PASSWORD_PWCC);
private final JNCryptor jnCryptor;
protected PasswordEncryptor(final JNCryptor jnCryptor) {
this.jnCryptor = jnCryptor;
}
@Override
public Set<Strategy> strategies() {
return STRATEGIES;
}
@Override
public Result<ByteBuffer> encrypt(final CharSequence plainTextConfig, final SebConfigEncryptionContext context) {
return Result.tryCatch(() -> {
return ByteBuffer.wrap(this.jnCryptor.encryptData(
Utils.toByteArray(plainTextConfig),
Utils.toCharArray(context.getPassword())));
});
}
@Override
public Result<ByteBuffer> decrypt(final ByteBuffer cipher, final SebConfigEncryptionContext context) {
return Result.tryCatch(() -> {
return ByteBuffer.wrap(this.jnCryptor.decryptData(
Utils.toByteArray(cipher),
Utils.toCharArray(context.getPassword())));
});
}
@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void encrypt(
@ -80,7 +54,7 @@ public class PasswordEncryptor implements SebConfigCryptor {
final SebConfigEncryptionContext context) {
if (log.isDebugEnabled()) {
log.debug("*** Start streaming asynchronous encryption of SEB exam configuration data");
log.debug("*** Start streaming asynchronous encryption");
}
AES256JNCryptorOutputStream encryptOutput = null;
@ -88,17 +62,17 @@ public class PasswordEncryptor implements SebConfigCryptor {
encryptOutput = new AES256JNCryptorOutputStream(
output,
Utils.toCharArray(context.getPassword()));
Utils.toCharArray(context.getPassword()),
10000);
IOUtils.copyLarge(input, encryptOutput);
encryptOutput.close();
input.close();
encryptOutput.flush();
encryptOutput.close();
output.flush();
} catch (final CryptorException e) {
log.error("Error while trying to stream and encrypt seb exam configuration data: ", e);
log.error("Error while trying to stream and encrypt data: ", e);
} catch (final IOException e) {
log.error("Error while trying to read/write form/to streams: ", e);
} finally {
@ -110,7 +84,7 @@ public class PasswordEncryptor implements SebConfigCryptor {
}
if (log.isDebugEnabled()) {
log.debug("*** Finish streaming asynchronous encryption of SEB exam configuration data");
log.debug("*** Finish streaming asynchronous encryption");
}
}
}
@ -118,11 +92,42 @@ public class PasswordEncryptor implements SebConfigCryptor {
@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void decrypt(
final OutputStream plainTextOutput,
final InputStream cipherInputStream,
final OutputStream output,
final InputStream input,
final SebConfigEncryptionContext context) {
// TODO Auto-generated method stub
if (log.isDebugEnabled()) {
log.debug("*** Start streaming asynchronous decryption");
}
AES256JNCryptorInputStream encryptInput = null;
try {
encryptInput = new AES256JNCryptorInputStream(
input,
Utils.toCharArray(context.getPassword()));
IOUtils.copyLarge(encryptInput, output);
input.close();
encryptInput.close();
output.flush();
output.close();
} catch (final IOException e) {
log.error("Error while trying to read/write form/to streams: ", e);
} finally {
try {
if (encryptInput != null)
encryptInput.close();
} catch (final IOException e) {
log.error("Failed to close AES256JNCryptorOutputStream: ", e);
}
if (log.isDebugEnabled()) {
log.debug("*** Finish streaming asynchronous decryption");
}
}
}

View file

@ -8,13 +8,11 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.UUID;
@ -31,7 +29,6 @@ import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService;
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
@ -40,6 +37,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebClientConfigSe
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ZipService;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.SebConfigEncryptionServiceImpl.EncryptionContext;
@Lazy
@Service
@ -147,6 +145,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
PipedOutputStream pOut = null;
PipedInputStream pIn = null;
try {
// zip the plain text
final InputStream plainIn = IOUtils.toInputStream(plainTextConfig, "UTF-8");
pOut = new PipedOutputStream();
@ -157,7 +156,10 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
if (encryptionPassword != null) {
passwordEncryption(output, encryptionPassword, pIn);
} else {
noEncryption(output, plainTextConfig);
this.sebConfigEncryptionService.streamEncrypted(
output,
pIn,
EncryptionContext.contextOfPlainText());
}
} catch (final Exception e) {
@ -177,21 +179,6 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
}
}
private void noEncryption(
final OutputStream output,
final String plainTextConfig) throws IOException {
log.debug("Serve plain text seb configuration with specified header");
final ByteBuffer encryptedConfig = this.sebConfigEncryptionService.plainText(plainTextConfig)
.getOrThrow();
IOUtils.copyLarge(
new ByteArrayInputStream(Utils.toByteArray(encryptedConfig)),
output);
}
private void passwordEncryption(
final OutputStream output,
final CharSequence encryptionPassword,
@ -204,11 +191,12 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
final CharSequence encryptionPasswordPlaintext = this.clientCredentialService
.decrypt(encryptionPassword);
this.sebConfigEncryptionService.streamEncryption(
this.sebConfigEncryptionService.streamEncrypted(
output,
input,
Strategy.PASSWORD_PSWD,
encryptionPasswordPlaintext);
EncryptionContext.contextOf(
Strategy.PASSWORD_PSWD,
encryptionPasswordPlaintext));
if (log.isDebugEnabled()) {
log.debug("*** Finished Seb client configuration with password based encryption");

View file

@ -13,7 +13,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Collection;
@ -31,7 +30,6 @@ import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionContext;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService;
@ -57,27 +55,24 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
}
@Override
public Result<ByteBuffer> plainText(final CharSequence plainTextConfig) {
if (log.isDebugEnabled()) {
log.debug("No encryption, use plain text with header");
}
return Result.tryCatch(() -> {
return addHeader(
Utils.toByteBuffer(plainTextConfig),
Strategy.PLAIN_TEXT);
});
}
// @Override
// public void streamPlainData(
// final OutputStream output,
// final InputStream input) {
//
//
// getEncryptor(strategy)
// .getOrThrow()
// .encrypt(pout, input, context);
// }
@Override
public void streamEncryption(
public void streamEncrypted(
final OutputStream output,
final InputStream input,
final Strategy strategy,
final CharSequence password) {
final SebConfigEncryptionContext context) {
final Strategy strategy = context.getStrategy();
PipedOutputStream pout = null;
PipedInputStream pin = null;
try {
@ -91,26 +86,27 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
pout.write(strategy.header);
getEncryptor(strategy)
.getOrThrow()
.encrypt(pout,
input,
EncryptionContext.contextOf(strategy, password));
.encrypt(pout, input, context);
IOUtils.copyLarge(pin, output);
pin.close();
pout.flush();
pout.close();
output.flush();
} catch (final IOException e) {
log.error("Error while stream encrypted data: ", e);
} finally {
try {
pin.close();
if (pin != null)
pin.close();
} catch (final IOException e1) {
log.error("Failed to close PipedInputStream: ", e1);
}
try {
pout.close();
if (pout != null)
pout.close();
} catch (final IOException e1) {
log.error("Failed to close PipedOutputStream: ", e1);
}
@ -118,95 +114,72 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
}
@Override
public Result<ByteBuffer> encryptWithCertificate(
final CharSequence plainTextConfig,
final Strategy strategy,
final Certificate certificate) {
if (log.isDebugEnabled()) {
log.debug("Certificate encryption with strategy: {}", strategy);
}
return getEncryptor(strategy)
.flatMap(encryptor -> encryptor.encrypt(
plainTextConfig,
EncryptionContext.contextOf(strategy, certificate)))
.map(bb -> addHeader(bb, strategy));
}
@Override
public Result<ByteBuffer> decrypt(
final ByteBuffer cipher,
public void streamDecrypted(
final OutputStream output,
final InputStream input,
final Supplier<CharSequence> passwordSupplier,
final Function<CharSequence, Certificate> certificateStore) {
return verifyStrategy(cipher)
.flatMap(strategy -> decrypt(strategy, cipher, passwordSupplier, certificateStore));
}
PipedOutputStream pout = null;
PipedInputStream pin = null;
try {
pout = new PipedOutputStream();
pin = new PipedInputStream(pout);
private Result<ByteBuffer> decrypt(
final Strategy strategy,
final ByteBuffer cipher,
final Supplier<CharSequence> passwordSupplier,
final Function<CharSequence, Certificate> certificateStore) {
final Strategy strategy = verifyStrategy(input);
if (log.isDebugEnabled()) {
log.debug("Decryption with strategy: {}", strategy);
}
if (log.isDebugEnabled()) {
log.debug("Password decryption with strategy: {}", strategy);
}
if (strategy == Strategy.PLAIN_TEXT) {
return Result.of(removeHeader(cipher, strategy));
}
final EncryptionContext context = new EncryptionContext(
strategy,
(passwordSupplier != null) ? passwordSupplier.get() : null,
certificateStore);
return getEncryptor(strategy)
.flatMap(encryptor -> encryptor.decrypt(
removeHeader(cipher, strategy),
(strategy.type == Type.PASSWORD)
? EncryptionContext.contextOf(strategy, passwordSupplier.get())
: EncryptionContext.contextOf(strategy, certificateStore)));
}
getEncryptor(strategy)
.getOrThrow()
.decrypt(pout, input, context);
private ByteBuffer addHeader(final ByteBuffer input, final Strategy strategy) {
final ByteBuffer _input = (input == null) ? ByteBuffer.allocate(0) : input;
IOUtils.copyLarge(pin, output);
_input.rewind();
final ByteBuffer buffer = ByteBuffer.allocate(
SebConfigEncryptionServiceImpl.HEADER_SIZE +
_input.limit());
pin.close();
pout.flush();
pout.close();
output.flush();
buffer.put(strategy.header);
buffer.put(_input);
return buffer.asReadOnlyBuffer();
}
private ByteBuffer removeHeader(final ByteBuffer input, final Strategy strategy) {
input.rewind();
final byte[] header = new byte[SebConfigEncryptionServiceImpl.HEADER_SIZE];
input.get(header);
if (Arrays.equals(strategy.header, header)) {
final byte[] b = new byte[input.remaining()];
input.get(b);
return ByteBuffer.wrap(b).asReadOnlyBuffer();
} else {
input.clear();
return input.asReadOnlyBuffer();
}
}
private Result<Strategy> verifyStrategy(final ByteBuffer cipher) {
cipher.rewind();
final byte[] header = new byte[HEADER_SIZE];
cipher.get(header);
//final String headerString = Utils.toString(header);
for (final Strategy s : Strategy.values()) {
if (Arrays.equals(s.header, header)) {
return Result.of(s);
} catch (final IOException e) {
log.error("Error while stream decrypted data: ", e);
} finally {
try {
if (pin != null)
pin.close();
} catch (final IOException e1) {
log.error("Failed to close PipedInputStream: ", e1);
}
try {
if (pout != null)
pout.close();
} catch (final IOException e1) {
log.error("Failed to close PipedOutputStream: ", e1);
}
}
}
log.error("Failed to verify encryption strategy. Fallback to plain text strategy");
return Result.of(Strategy.PLAIN_TEXT);
private Strategy verifyStrategy(final InputStream input) {
try {
final byte[] header = new byte[HEADER_SIZE];
input.read(header);
for (final Strategy s : Strategy.values()) {
if (Arrays.equals(s.header, header)) {
return s;
}
}
throw new IllegalStateException("Failed to verify decryption strategy from input stream");
} catch (final IOException e) {
log.error("Failed to read decryption strategy from input stream");
throw new IllegalStateException("Failed to verify decryption strategy from input stream");
}
}
private Result<SebConfigCryptor> getEncryptor(final Strategy strategy) {
@ -218,21 +191,20 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
return Result.of(encryptor);
}
protected static class EncryptionContext implements SebConfigEncryptionContext {
static class EncryptionContext implements SebConfigEncryptionContext {
public final Strategy strategy;
public final CharSequence password;
public final Certificate certificate;
public final Function<CharSequence, Certificate> certificateStore;
private EncryptionContext(
final Strategy strategy,
final CharSequence password,
final Certificate certificate,
final Function<CharSequence, Certificate> certificateStore) {
this.strategy = strategy;
this.password = password;
this.certificate = certificate;
this.certificateStore = certificateStore;
}
@Override
@ -246,18 +218,16 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
}
@Override
public Certificate getCertificate() {
return this.certificate;
public Certificate getCertificate(final CharSequence key) {
if (this.certificateStore == null) {
throw new UnsupportedOperationException();
}
return this.certificateStore.apply(key);
}
static SebConfigEncryptionContext contextOf(final Strategy strategy, final CharSequence password) {
checkPasswordbased(strategy);
return new EncryptionContext(strategy, password, null, null);
}
static SebConfigEncryptionContext contextOf(final Strategy strategy, final Certificate certificate) {
checkCertificateBased(strategy);
return new EncryptionContext(strategy, null, certificate, null);
return new EncryptionContext(strategy, password, null);
}
static SebConfigEncryptionContext contextOf(
@ -265,7 +235,7 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
final Function<CharSequence, Certificate> certificateStore) {
checkCertificateBased(strategy);
return new EncryptionContext(strategy, null, null, certificateStore);
return new EncryptionContext(strategy, null, certificateStore);
}
static void checkPasswordbased(final Strategy strategy) {
@ -280,6 +250,10 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
}
}
public static SebConfigEncryptionContext contextOfPlainText() {
return new EncryptionContext(Strategy.PLAIN_TEXT, null, null);
}
}
}

View file

@ -10,10 +10,10 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
@ -22,7 +22,6 @@ import org.cryptonode.jncryptor.AES256JNCryptorOutputStream;
import org.cryptonode.jncryptor.JNCryptor;
import org.junit.Test;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionContext;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy;
@ -45,7 +44,7 @@ public class PasswordEncryptorTest {
public void testUsingPassword() throws Exception {
final String config = "<TestConfig></TestConfig>";
final byte[] plaintext = Utils.toByteArray(config);//getRandomBytes(127);
final byte[] plaintext = Utils.toByteArray(config);
final String password = "Testing1234";
@ -63,36 +62,9 @@ public class PasswordEncryptorTest {
assertArrayEquals(plaintext, result);
}
@Test
public void test1() {
final JNCryptor jnCryptor = new AES256JNCryptor();
jnCryptor.setPBKDFIterations(10000);
final PasswordEncryptor encryptor = new PasswordEncryptor(jnCryptor);
final String config = "<TestConfig></TestConfig>";
final String pwd = "password";
final SebConfigEncryptionContext context = EncryptionContext.contextOf(
Strategy.PASSWORD_PWCC,
pwd);
final Result<ByteBuffer> encrypt = encryptor.encrypt(config, context);
assertFalse(encrypt.hasError());
final ByteBuffer cipher = encrypt.getOrThrow();
final byte[] byteArray = Utils.toByteArray(cipher);
final Result<ByteBuffer> decrypt = encryptor.decrypt(cipher, context);
assertFalse(decrypt.hasError());
final String decryptedConfig = Utils.toString(decrypt.getOrThrow());
assertEquals(config, decryptedConfig);
}
@Test
public void test2() throws IOException {
final JNCryptor jnCryptor = new AES256JNCryptor();
jnCryptor.setPBKDFIterations(10000);
final PasswordEncryptor encryptor = new PasswordEncryptor(jnCryptor);
final PasswordEncryptor encryptor = new PasswordEncryptor();
final String config = "<TestConfig></TestConfig>";
final String pwd = "password";
@ -109,14 +81,16 @@ public class PasswordEncryptorTest {
final byte[] byteArray = out.toByteArray();
final Result<ByteBuffer> decrypt = encryptor.decrypt(
ByteBuffer.wrap(byteArray),
final ByteArrayOutputStream out2 = new ByteArrayOutputStream(512);
encryptor.decrypt(
out2,
new ByteArrayInputStream(byteArray),
context);
assertFalse(decrypt.hasError());
final ByteBuffer buffer = decrypt.getOrThrow();
buffer.rewind();
final String decryptedConfig = Utils.toString(buffer);
final byte[] byteArray2 = out2.toByteArray();
assertNotNull(byteArray2);
final String decryptedConfig = new String(byteArray2, "UTF-8");
assertEquals(config, decryptedConfig);
}

View file

@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -17,31 +18,44 @@ import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.cryptonode.jncryptor.AES256JNCryptor;
import org.cryptonode.jncryptor.JNCryptor;
import org.junit.Test;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.SebConfigEncryptionServiceImpl.EncryptionContext;
public class SebConfigEncryptionServiceImplTest {
@Test
public void testPlainText() {
public void testPlainText() throws IOException {
final SebConfigEncryptionServiceImpl sebConfigEncryptionServiceImpl = sebConfigEncryptionServiceImpl();
final String config = "<TestConfig></TestConfig>";
final Result<ByteBuffer> plainText = sebConfigEncryptionServiceImpl.plainText(config);
assertFalse(plainText.hasError());
final ByteBuffer cipher = plainText.get();
assertEquals("plnd<TestConfig></TestConfig>", Utils.toString(cipher));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
sebConfigEncryptionServiceImpl
.streamEncrypted(
out,
IOUtils.toInputStream(config, "UTF-8"),
EncryptionContext.contextOfPlainText());
final Result<ByteBuffer> decrypt = sebConfigEncryptionServiceImpl.decrypt(cipher, null, null);
assertFalse(decrypt.hasError());
assertEquals("<TestConfig></TestConfig>", Utils.toString(decrypt.get()));
final byte[] plainWithHeader = out.toByteArray();
assertNotNull(plainWithHeader);
assertEquals("plnd<TestConfig></TestConfig>", Utils.toString(plainWithHeader));
final ByteArrayOutputStream out2 = new ByteArrayOutputStream(512);
sebConfigEncryptionServiceImpl.streamDecrypted(
out2,
new ByteArrayInputStream(plainWithHeader),
null,
null);
final byte[] byteArray2 = out2.toByteArray();
assertNotNull(byteArray2);
final String decryptedConfig = new String(byteArray2, "UTF-8");
assertEquals(config, decryptedConfig);
}
@Test
@ -53,11 +67,12 @@ public class SebConfigEncryptionServiceImplTest {
final ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
sebConfigEncryptionServiceImpl.streamEncryption(
sebConfigEncryptionServiceImpl.streamEncrypted(
out,
IOUtils.toInputStream(config, "UTF-8"),
Strategy.PASSWORD_PWCC,
pwd);
EncryptionContext.contextOf(
Strategy.PASSWORD_PWCC,
pwd));
final byte[] byteArray = out.toByteArray();
@ -65,17 +80,24 @@ public class SebConfigEncryptionServiceImplTest {
final ByteBuffer cipher = ByteBuffer.wrap(byteArray);
assertTrue(Utils.toString(cipher).startsWith(Utils.toString(Strategy.PASSWORD_PWCC.header)));
final Result<ByteBuffer> decrypt = sebConfigEncryptionServiceImpl.decrypt(cipher, () -> pwd, null);
assertFalse(decrypt.hasError());
assertEquals("<TestConfig></TestConfig>", Utils.toString(decrypt.get()));
final ByteArrayOutputStream out2 = new ByteArrayOutputStream(512);
sebConfigEncryptionServiceImpl.streamDecrypted(
out2,
new ByteArrayInputStream(byteArray),
() -> pwd,
null);
final byte[] byteArray2 = out2.toByteArray();
assertNotNull(byteArray2);
final String decryptedConfig = new String(byteArray2, "UTF-8");
assertEquals(config, decryptedConfig);
}
private SebConfigEncryptionServiceImpl sebConfigEncryptionServiceImpl() {
final JNCryptor jnCryptor = new AES256JNCryptor();
jnCryptor.setPBKDFIterations(10000);
final List<SebConfigCryptor> encryptors = Arrays.asList(
new PasswordEncryptor(jnCryptor));
new PasswordEncryptor(),
new NoneEncryptor());
return new SebConfigEncryptionServiceImpl(encryptors);
}