SEBSERV-135 finished up decryption
This commit is contained in:
parent
a4cb075f42
commit
c9be24197d
3 changed files with 98 additions and 36 deletions
|
@ -11,17 +11,57 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.CertificateService;
|
||||
|
||||
public abstract class AbstractCertificateCryptor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractCertificateCryptor.class);
|
||||
|
||||
protected static final int PUBLIC_KEY_HASH_SIZE = 20;
|
||||
protected static final int ENCRYPTION_KEY_BITS = 256;
|
||||
protected static final int KEY_LENGTH_SIZE = 4;
|
||||
|
||||
protected final CertificateService certificateService;
|
||||
|
||||
public AbstractCertificateCryptor(final CertificateService certificateService) {
|
||||
this.certificateService = certificateService;
|
||||
}
|
||||
|
||||
protected Certificate getCertificateByPublicKeyHash(final Long institutionId, final byte[] publicKeyHash) {
|
||||
try {
|
||||
|
||||
final Certificates certs = this.certificateService
|
||||
.getCertificates(institutionId)
|
||||
.getOrThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Enumeration<String> engineAliases = certs.keyStore.engineAliases();
|
||||
while (engineAliases.hasMoreElements()) {
|
||||
final Certificate certificate = certs.keyStore.engineGetCertificate(engineAliases.nextElement());
|
||||
final byte[] otherPublicKeyHash = generatePublicKeyHash(certificate);
|
||||
if (Objects.equals(otherPublicKeyHash, publicKeyHash)) {
|
||||
return certificate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to get certificate by public key hash: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] generatePublicKeyHash(final Certificate cert) {
|
||||
|
||||
try {
|
||||
|
@ -38,7 +78,11 @@ public abstract class AbstractCertificateCryptor {
|
|||
return encryptWithCert(cert, data, data.length);
|
||||
}
|
||||
|
||||
protected byte[] encryptWithCert(final Certificate cert, final byte[] data, final int length) throws Exception {
|
||||
protected byte[] encryptWithCert(
|
||||
final Certificate cert,
|
||||
final byte[] data,
|
||||
final int length) throws Exception {
|
||||
|
||||
final String algorithm = cert.getPublicKey().getAlgorithm();
|
||||
final Cipher encryptCipher = Cipher.getInstance(algorithm);
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, cert);
|
||||
|
@ -46,10 +90,17 @@ public abstract class AbstractCertificateCryptor {
|
|||
}
|
||||
|
||||
protected byte[] decryptWithCert(final Certificate cert, final byte[] encryptedData) throws Exception {
|
||||
return decryptWithCert(cert, encryptedData, encryptedData.length);
|
||||
}
|
||||
|
||||
protected byte[] decryptWithCert(
|
||||
final Certificate cert,
|
||||
final byte[] encryptedData, final int length) throws Exception {
|
||||
|
||||
final String algorithm = cert.getPublicKey().getAlgorithm();
|
||||
final Cipher encryptCipher = Cipher.getInstance(algorithm);
|
||||
encryptCipher.init(Cipher.DECRYPT_MODE, cert);
|
||||
return encryptCipher.doFinal(encryptedData);
|
||||
return encryptCipher.doFinal(encryptedData, 0, length);
|
||||
}
|
||||
|
||||
protected byte[] parsePublicKeyHash(final InputStream input) throws IOException {
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
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;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigEncryptionContext;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SEBConfigEncryptionService.Strategy;
|
||||
|
@ -32,9 +33,14 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(CertificateAsymetricKeyCryptor.class);
|
||||
|
||||
private static final int BUFFER_LENGTH = 128;
|
||||
private static final Set<Strategy> STRATEGIES = Utils.immutableSetOf(
|
||||
Strategy.PUBLIC_KEY_HASH);
|
||||
|
||||
public CertificateAsymetricKeyCryptor(final CertificateService certificateService) {
|
||||
super(certificateService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Strategy> strategies() {
|
||||
return STRATEGIES;
|
||||
|
@ -57,7 +63,7 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
|
||||
output.write(publicKeyHash, 0, publicKeyHash.length);
|
||||
|
||||
final byte[] buffer = new byte[128];
|
||||
final byte[] buffer = new byte[BUFFER_LENGTH];
|
||||
|
||||
int readBytes = input.read(buffer, 0, buffer.length);
|
||||
while (readBytes > 0) {
|
||||
|
@ -86,7 +92,36 @@ public class CertificateAsymetricKeyCryptor extends AbstractCertificateCryptor i
|
|||
final InputStream input,
|
||||
final SEBConfigEncryptionContext context) {
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
try {
|
||||
final byte[] publicKeyHash = parsePublicKeyHash(input);
|
||||
final Certificate certificate = getCertificateByPublicKeyHash(
|
||||
context.institutionId(),
|
||||
publicKeyHash);
|
||||
|
||||
if (certificate == null) {
|
||||
throw new RuntimeException("No matching certificate found to decrypt the configuration");
|
||||
}
|
||||
|
||||
final byte[] buffer = new byte[BUFFER_LENGTH];
|
||||
|
||||
int readBytes = input.read(buffer, 0, buffer.length);
|
||||
while (readBytes > 0) {
|
||||
final byte[] encryptedBlock = decryptWithCert(certificate, buffer, readBytes);
|
||||
output.write(encryptedBlock, 0, encryptedBlock.length);
|
||||
readBytes = input.read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Error while trying to stream and decrypt data: ", e);
|
||||
} finally {
|
||||
try {
|
||||
output.flush();
|
||||
output.close();
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to close output: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("*** Start streaming asynchronous certificate asymmetric-key decryption");
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ import java.nio.ByteOrder;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Base64;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
|
@ -30,7 +28,6 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Certificates;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.CertificateService;
|
||||
|
@ -59,16 +56,15 @@ public class CertificateSymetricKeyCryptor extends AbstractCertificateCryptor im
|
|||
|
||||
private final PasswordEncryptor passwordEncryptor;
|
||||
private final PasswordDecryptor passwordDecryptor;
|
||||
private final CertificateService certificateService;
|
||||
|
||||
public CertificateSymetricKeyCryptor(
|
||||
final PasswordEncryptor passwordEncryptor,
|
||||
final PasswordDecryptor passwordDecryptor,
|
||||
final CertificateService certificateService) {
|
||||
|
||||
super(certificateService);
|
||||
this.passwordEncryptor = passwordEncryptor;
|
||||
this.passwordDecryptor = passwordDecryptor;
|
||||
this.certificateService = certificateService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,11 +120,16 @@ public class CertificateSymetricKeyCryptor extends AbstractCertificateCryptor im
|
|||
try {
|
||||
|
||||
final byte[] publicKeyHash = parsePublicKeyHash(input);
|
||||
final Certificate cert = getCertificateByPublicKeyHash(
|
||||
final Certificate certificate = getCertificateByPublicKeyHash(
|
||||
context.institutionId(),
|
||||
publicKeyHash);
|
||||
|
||||
if (certificate == null) {
|
||||
throw new RuntimeException("No matching certificate found to decrypt the configuration");
|
||||
}
|
||||
|
||||
final byte[] encryptedKey = getEncryptedKey(input);
|
||||
final byte[] symetricKey = decryptWithCert(cert, encryptedKey);
|
||||
final byte[] symetricKey = decryptWithCert(certificate, encryptedKey);
|
||||
final CharSequence symetricKeyBase64 = Base64.getEncoder().encodeToString(symetricKey);
|
||||
|
||||
this.passwordDecryptor.decrypt(output, input, symetricKeyBase64);
|
||||
|
@ -161,31 +162,6 @@ public class CertificateSymetricKeyCryptor extends AbstractCertificateCryptor im
|
|||
return encryptedKey;
|
||||
}
|
||||
|
||||
private Certificate getCertificateByPublicKeyHash(final Long institutionId, final byte[] publicKeyHash) {
|
||||
try {
|
||||
|
||||
final Certificates certs = this.certificateService
|
||||
.getCertificates(institutionId)
|
||||
.getOrThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Enumeration<String> engineAliases = certs.keyStore.engineAliases();
|
||||
while (engineAliases.hasMoreElements()) {
|
||||
final Certificate certificate = certs.keyStore.engineGetCertificate(engineAliases.nextElement());
|
||||
final byte[] otherPublicKeyHash = generatePublicKeyHash(certificate);
|
||||
if (Objects.equals(otherPublicKeyHash, publicKeyHash)) {
|
||||
return certificate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to get certificate by public key hash: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] generateSymetricKey() throws NoSuchAlgorithmException {
|
||||
final KeyGenerator keyGenerator = KeyGenerator.getInstance(Constants.AES);
|
||||
keyGenerator.init(ENCRYPTION_KEY_BITS);
|
||||
|
|
Loading…
Reference in a new issue