package at.gv.egiz.eaaf.core.test.credentials; import static org.junit.Assert.assertArrayEquals; import java.security.Provider; import java.util.concurrent.CompletableFuture; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import org.apache.commons.lang3.RandomStringUtils; import org.junit.Assert; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration; import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricKeyType; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @Slf4j @Getter public class EncryptionTask implements Runnable { private static final String HSM_FACASE_HOST = "eid.a-sit.at"; private static final String HSM_FACASE_PORT = "9050"; private static final String HSM_FACASE_SSL_TRUST = "src/test/resources/data/hsm_facade_trust_root.crt"; private static final String HSM_FACASE_USERNAME = "authhandler-junit"; private static final String HSM_FACASE_PASSWORD = "supersecret123"; private static final String PATH_TO_SOFTWARE_KEYSTORE_JKS_WITH_TRUSTED_CERTS = "src/test/resources/data/junit.jks"; private static final String PATH_TO_SOFTWARE_KEYSTORE_JKS = "src/test/resources/data/junit_without_trustcerts.jks"; private static final String PATH_TO_SOFTWARE_KEYSTORE_PKCS12 = "src/test/resources/data/junit_without_trustcerts.p12"; private static final String SOFTWARE_KEYSTORE_PASSWORD = "password"; private static final String HSM_FACADE_KEY_ALIAS = "authhandler-sign"; private static final String CIPHER_MODE = "AES/GCM/NoPadding"; private static final int GCM_NONCE_LENGTH = 12; // in bytes private static final int GCM_TAG_LENGTH = 16; // in bytes protected static final String KEYNAME = "AES"; @Autowired private DummyAuthConfigMap mapConfig; @Autowired private ApplicationContext context; String keyName; int rounds; private Exception error; public EncryptionTask(ApplicationContext context2, DummyAuthConfigMap mapConfig2, String keyName, int rounds) { this.context = context2; this.mapConfig = mapConfig2; this.keyName = keyName; this.rounds = rounds; } @Override public void run() { run(this.keyName, this.rounds); } @Async public CompletableFuture run(String keyName, int rounds) { try { Pair key = loadSymmetricKey(keyName); Assert.assertNotNull("Key container is null", key); for(int i = 0; i < rounds; i++) { log.info("Starting threat: {} Round: {}", Thread.currentThread().getName(), i); byte[] data = RandomStringUtils.randomAlphanumeric(1024*64).getBytes(); Pair enc = encryptData(key.getFirst(), data); byte[] checkData = decryptData(enc, key.getFirst()); log.info("Finishing threat: {} Round: {}", Thread.currentThread().getName(), i); assertArrayEquals("plaintext not match", data, checkData); } } catch (Exception e) { this.error = e; throw new RuntimeException(e); } return new AsyncResult<>("finished").completable(); } private byte[] decryptData(Pair enc, SecretKey secret) throws Exception { final GCMParameterSpec iv = new GCMParameterSpec(GCM_TAG_LENGTH * 8, enc.getSecond()); final Cipher cipher = Cipher.getInstance(CIPHER_MODE); cipher.init(Cipher.DECRYPT_MODE, secret, iv); return cipher.doFinal(enc.getFirst()); } private Pair encryptData(SecretKey secret, byte[] toEncrypt) throws Exception { final byte[] nonce = Random.nextBytes(GCM_NONCE_LENGTH); final GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce); final Cipher cipher = Cipher.getInstance(CIPHER_MODE); cipher.init(Cipher.ENCRYPT_MODE, secret, spec); final byte[] encdata = cipher.doFinal(toEncrypt); final byte[] iv = cipher.getIV(); return Pair.newInstance(encdata, iv); } private Pair loadSymmetricKey(String keyName) throws EaafException { mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, HSM_FACASE_HOST); mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, HSM_FACASE_PORT); mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, HSM_FACASE_SSL_TRUST); mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, HSM_FACASE_USERNAME); mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, HSM_FACASE_PASSWORD); final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration(); keyConfig.setFriendlyName("jUnit test"); keyConfig.setKeyType(SymmetricKeyType.HSMFACADE); keyConfig.setKeyStoreName("authhandler"); keyConfig.setKeyAlias(keyName); return keyStoreFactory.buildNewSymmetricKey(keyConfig); } }