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…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti