SEBSERV-304 fixed
This commit is contained in:
parent
d9b03e7894
commit
a043f2b787
7 changed files with 115 additions and 32 deletions
|
@ -36,4 +36,6 @@ public interface SEBConfigEncryptionContext {
|
|||
* @throws UnsupportedOperationException if not supported */
|
||||
Certificate getCertificate();
|
||||
|
||||
String getCertificateAlias();
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
|
@ -21,7 +22,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.CertificateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigEncryptionContext;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.SEBConfigEncryptionServiceImpl.EncryptionContext;
|
||||
|
||||
public abstract class AbstractCertificateCryptor {
|
||||
|
||||
|
@ -32,25 +36,38 @@ public abstract class AbstractCertificateCryptor {
|
|||
protected static final int KEY_LENGTH_SIZE = 4;
|
||||
|
||||
protected final CertificateService certificateService;
|
||||
protected final Cryptor cryptor;
|
||||
|
||||
public AbstractCertificateCryptor(
|
||||
final CertificateService certificateService,
|
||||
final Cryptor cryptor) {
|
||||
|
||||
public AbstractCertificateCryptor(final CertificateService certificateService) {
|
||||
this.certificateService = certificateService;
|
||||
this.cryptor = cryptor;
|
||||
}
|
||||
|
||||
protected Certificate getCertificateByPublicKeyHash(final Long institutionId, final byte[] publicKeyHash) {
|
||||
protected SEBConfigEncryptionContext getCertificateByPublicKeyHash(
|
||||
final SEBConfigEncryptionContext sebConfigEncryptionContext,
|
||||
final byte[] publicKeyHash) {
|
||||
|
||||
try {
|
||||
|
||||
final Certificates certs = this.certificateService
|
||||
.getCertificates(institutionId)
|
||||
.getCertificates(sebConfigEncryptionContext.institutionId())
|
||||
.getOrThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Enumeration<String> engineAliases = certs.keyStore.engineAliases();
|
||||
while (engineAliases.hasMoreElements()) {
|
||||
final Certificate certificate = certs.keyStore.engineGetCertificate(engineAliases.nextElement());
|
||||
final String alias = engineAliases.nextElement();
|
||||
final Certificate certificate = certs.keyStore.engineGetCertificate(alias);
|
||||
final byte[] otherPublicKeyHash = generatePublicKeyHash(certificate);
|
||||
if (Arrays.equals(otherPublicKeyHash, publicKeyHash)) {
|
||||
return certificate;
|
||||
return EncryptionContext.contextOf(
|
||||
sebConfigEncryptionContext.institutionId(),
|
||||
sebConfigEncryptionContext.getStrategy(),
|
||||
certificate,
|
||||
alias);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,21 +102,33 @@ public abstract class AbstractCertificateCryptor {
|
|||
|
||||
final String algorithm = cert.getPublicKey().getAlgorithm();
|
||||
final Cipher encryptCipher = Cipher.getInstance(algorithm);
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, cert);
|
||||
return encryptCipher.doFinal(data, 0, length);
|
||||
}
|
||||
|
||||
protected byte[] decryptWithCert(final Certificate cert, final byte[] encryptedData) throws Exception {
|
||||
return decryptWithCert(cert, encryptedData, encryptedData.length);
|
||||
protected byte[] decryptWithCert(
|
||||
final SEBConfigEncryptionContext sebConfigEncryptionContext,
|
||||
final byte[] encryptedData) throws Exception {
|
||||
|
||||
return decryptWithCert(sebConfigEncryptionContext, encryptedData, encryptedData.length);
|
||||
}
|
||||
|
||||
protected byte[] decryptWithCert(
|
||||
final Certificate cert,
|
||||
final byte[] encryptedData, final int length) throws Exception {
|
||||
final SEBConfigEncryptionContext sebConfigEncryptionContext,
|
||||
final byte[] encryptedData,
|
||||
final int length) throws Exception {
|
||||
|
||||
final String algorithm = cert.getPublicKey().getAlgorithm();
|
||||
final Certificate certificate = sebConfigEncryptionContext.getCertificate();
|
||||
final String certificateAlias = sebConfigEncryptionContext.getCertificateAlias();
|
||||
final String algorithm = certificate.getPublicKey().getAlgorithm();
|
||||
final Cipher encryptCipher = Cipher.getInstance(algorithm);
|
||||
encryptCipher.init(Cipher.DECRYPT_MODE, cert.getPublicKey());
|
||||
final Certificates certificates = this.certificateService
|
||||
.getCertificates(sebConfigEncryptionContext.institutionId())
|
||||
.getOrThrow();
|
||||
final PrivateKey privateKey = this.cryptor
|
||||
.getPrivateKey(certificates.keyStore, certificateAlias)
|
||||
.getOrThrow();
|
||||
encryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
return encryptCipher.doFinal(encryptedData, 0, length);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.CertificateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigCryptor;
|
||||
|
@ -37,8 +38,11 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
private static final Set<Strategy> STRATEGIES = Utils.immutableSetOf(
|
||||
Strategy.PUBLIC_KEY_HASH);
|
||||
|
||||
public CertificateAsymetricKeyCryptor(final CertificateService certificateService) {
|
||||
super(certificateService);
|
||||
public CertificateAsymetricKeyCryptor(
|
||||
final CertificateService certificateService,
|
||||
final Cryptor cryptor) {
|
||||
|
||||
super(certificateService, cryptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,9 +98,10 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
|
||||
try {
|
||||
final byte[] publicKeyHash = parsePublicKeyHash(input);
|
||||
final Certificate certificate = getCertificateByPublicKeyHash(
|
||||
context.institutionId(),
|
||||
final SEBConfigEncryptionContext sebConfigEncryptionContext = getCertificateByPublicKeyHash(
|
||||
context,
|
||||
publicKeyHash);
|
||||
final Certificate certificate = sebConfigEncryptionContext.getCertificate();
|
||||
|
||||
if (certificate == null) {
|
||||
throw new RuntimeException("No matching certificate found to decrypt the configuration");
|
||||
|
@ -106,7 +111,7 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
|
||||
int readBytes = input.read(buffer, 0, buffer.length);
|
||||
while (readBytes > 0) {
|
||||
final byte[] encryptedBlock = decryptWithCert(certificate, buffer, readBytes);
|
||||
final byte[] encryptedBlock = decryptWithCert(sebConfigEncryptionContext, buffer, readBytes);
|
||||
output.write(encryptedBlock, 0, encryptedBlock.length);
|
||||
readBytes = input.read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.CertificateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigCryptor;
|
||||
|
@ -60,9 +61,10 @@ public class CertificateSymetricKeyCryptor extends AbstractCertificateCryptor im
|
|||
public CertificateSymetricKeyCryptor(
|
||||
final PasswordEncryptor passwordEncryptor,
|
||||
final PasswordDecryptor passwordDecryptor,
|
||||
final CertificateService certificateService) {
|
||||
final CertificateService certificateService,
|
||||
final Cryptor cryptor) {
|
||||
|
||||
super(certificateService);
|
||||
super(certificateService, cryptor);
|
||||
this.passwordEncryptor = passwordEncryptor;
|
||||
this.passwordDecryptor = passwordDecryptor;
|
||||
}
|
||||
|
@ -120,16 +122,17 @@ public class CertificateSymetricKeyCryptor extends AbstractCertificateCryptor im
|
|||
try {
|
||||
|
||||
final byte[] publicKeyHash = parsePublicKeyHash(input);
|
||||
final Certificate certificate = getCertificateByPublicKeyHash(
|
||||
context.institutionId(),
|
||||
final SEBConfigEncryptionContext sebConfigEncryptionContext = getCertificateByPublicKeyHash(
|
||||
context,
|
||||
publicKeyHash);
|
||||
final Certificate certificate = sebConfigEncryptionContext.getCertificate();
|
||||
|
||||
if (certificate == null) {
|
||||
throw new RuntimeException("No matching certificate found to decrypt the configuration");
|
||||
}
|
||||
|
||||
final byte[] encryptedKey = getEncryptedKey(input);
|
||||
final byte[] symetricKey = decryptWithCert(certificate, encryptedKey);
|
||||
final byte[] symetricKey = decryptWithCert(sebConfigEncryptionContext, encryptedKey);
|
||||
final CharSequence symetricKeyBase64 = Base64.getEncoder().encodeToString(symetricKey);
|
||||
|
||||
this.passwordDecryptor.decrypt(output, input, symetricKeyBase64);
|
||||
|
|
|
@ -293,9 +293,9 @@ public class ClientConfigServiceImpl implements ClientConfigService {
|
|||
|
||||
private SEBConfigEncryptionContext buildCertificateEncryptionContext(final SEBClientConfig config) {
|
||||
|
||||
final Certificate certificate = this.certificateDAO.getCertificate(
|
||||
config.institutionId,
|
||||
String.valueOf(config.getEncryptCertificateAlias()))
|
||||
final String alias = String.valueOf(config.getEncryptCertificateAlias());
|
||||
final Certificate certificate = this.certificateDAO
|
||||
.getCertificate(config.institutionId, alias)
|
||||
.getOrThrow();
|
||||
|
||||
return EncryptionContext.contextOf(
|
||||
|
@ -303,7 +303,8 @@ public class ClientConfigServiceImpl implements ClientConfigService {
|
|||
(config.encryptCertificateAsym)
|
||||
? SEBConfigEncryptionService.Strategy.PUBLIC_KEY_HASH
|
||||
: SEBConfigEncryptionService.Strategy.PUBLIC_KEY_HASH_SYMMETRIC_KEY,
|
||||
certificate);
|
||||
certificate,
|
||||
alias);
|
||||
}
|
||||
|
||||
private SEBConfigEncryptionContext buildPasswordEncryptionContext(final SEBClientConfig config) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.io.OutputStream;
|
|||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.SequenceInputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -50,6 +51,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationFormat;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigEncryptionService.Strategy;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ZipService;
|
||||
|
||||
@Lazy
|
||||
|
@ -243,6 +245,10 @@ public class ExamConfigIO {
|
|||
throw new IllegalArgumentException("Failed to verify Zip type from input stream. Header size mismatch.");
|
||||
}
|
||||
|
||||
if (Arrays.equals(Strategy.PLAIN_TEXT.header, zipHeader)) {
|
||||
return unzip(input);
|
||||
}
|
||||
|
||||
final boolean isZipped = Byte.toUnsignedInt(zipHeader[0]) == Constants.GZIP_ID1
|
||||
&& Byte.toUnsignedInt(zipHeader[1]) == Constants.GZIP_ID2
|
||||
&& Byte.toUnsignedInt(zipHeader[2]) == Constants.GZIP_CM;
|
||||
|
|
|
@ -150,6 +150,34 @@ public final class SEBConfigEncryptionServiceImpl implements SEBConfigEncryption
|
|||
.getOrThrow()
|
||||
.decrypt(pout, newIn, context);
|
||||
|
||||
// if (strategy == Strategy.PLAIN_TEXT) {
|
||||
//
|
||||
// getEncryptor(strategy)
|
||||
// .getOrThrow()
|
||||
// .decrypt(pout, newIn, context);
|
||||
//
|
||||
// } else if ((strategy == Strategy.PASSWORD_PSWD || strategy == Strategy.PASSWORD_PWCC)) {
|
||||
// if (StringUtils.isBlank(context.getPassword())) {
|
||||
// return new AsyncResult<>(new APIMessage.APIMessageException(
|
||||
// APIMessage.ErrorMessage.MISSING_PASSWORD.of("Missing Password")));
|
||||
// } else {
|
||||
//
|
||||
// // then decrypt stream with password
|
||||
// getEncryptor(strategy)
|
||||
// .getOrThrow()
|
||||
// .decrypt(pout, newIn, context);
|
||||
// }
|
||||
// } else {
|
||||
//
|
||||
// // then decrypt stream with certificate
|
||||
// getEncryptor(strategy)
|
||||
// .getOrThrow()
|
||||
// .decrypt(
|
||||
// pout,
|
||||
// newIn,
|
||||
// EncryptionContext.contextOf(context.institutionId(), strategy, null, null));
|
||||
// }
|
||||
|
||||
IOUtils.copyLarge(pin, output);
|
||||
|
||||
return new AsyncResult<>(null);
|
||||
|
@ -194,17 +222,20 @@ public final class SEBConfigEncryptionServiceImpl implements SEBConfigEncryption
|
|||
public final Strategy strategy;
|
||||
public final CharSequence password;
|
||||
public final Certificate certificate;
|
||||
public final String certificateAlias;
|
||||
|
||||
private EncryptionContext(
|
||||
final Long institutionId,
|
||||
final Strategy strategy,
|
||||
final CharSequence password,
|
||||
final Certificate certificate) {
|
||||
final Certificate certificate,
|
||||
final String certificateAlias) {
|
||||
|
||||
this.institutionId = institutionId;
|
||||
this.strategy = strategy;
|
||||
this.password = password;
|
||||
this.certificate = certificate;
|
||||
this.certificateAlias = certificateAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -227,22 +258,28 @@ public final class SEBConfigEncryptionServiceImpl implements SEBConfigEncryption
|
|||
return this.certificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCertificateAlias() {
|
||||
return this.certificateAlias;
|
||||
}
|
||||
|
||||
static SEBConfigEncryptionContext contextOf(
|
||||
final Long institutionId,
|
||||
final Strategy strategy,
|
||||
final CharSequence password) {
|
||||
|
||||
checkPasswordBased(strategy);
|
||||
return new EncryptionContext(institutionId, strategy, password, null);
|
||||
return new EncryptionContext(institutionId, strategy, password, null, null);
|
||||
}
|
||||
|
||||
static SEBConfigEncryptionContext contextOf(
|
||||
final Long institutionId,
|
||||
final Strategy strategy,
|
||||
final Certificate certificate) {
|
||||
final Certificate certificate,
|
||||
final String certificateAlias) {
|
||||
|
||||
checkCertificateBased(strategy);
|
||||
return new EncryptionContext(institutionId, strategy, null, certificate);
|
||||
return new EncryptionContext(institutionId, strategy, null, certificate, certificateAlias);
|
||||
}
|
||||
|
||||
static void checkPasswordBased(final Strategy strategy) {
|
||||
|
@ -259,14 +296,14 @@ public final class SEBConfigEncryptionServiceImpl implements SEBConfigEncryption
|
|||
|
||||
public static SEBConfigEncryptionContext contextOfPlainText(final Long institutionId) {
|
||||
|
||||
return new EncryptionContext(institutionId, Strategy.PLAIN_TEXT, null, null);
|
||||
return new EncryptionContext(institutionId, Strategy.PLAIN_TEXT, null, null, null);
|
||||
}
|
||||
|
||||
public static SEBConfigEncryptionContext contextOf(
|
||||
final Long institutionId,
|
||||
final CharSequence password) {
|
||||
|
||||
return new EncryptionContext(institutionId, null, password, null);
|
||||
return new EncryptionContext(institutionId, null, password, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue