From 2b4d9dc8fcde4cdd5a13d9524b3a80a59376b4b8 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 22 Jun 2020 09:00:57 +0200 Subject: fix problem with JOSE encryption in combination with HSM-Facade add jUnit test for JoseUtils --- .../sl20/utils/AbstractJsonSecurityUtilsTest.java | 292 +++++++++++++++++++++ .../sl20/utils/JsonSecurityUtilsHsmKeyTest.java | 41 --- .../utils/JsonSecurityUtilsSoftwareKeyTest.java | 106 ++++++-- 3 files changed, 379 insertions(+), 60 deletions(-) create mode 100644 eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java delete mode 100644 eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java (limited to 'eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils') diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java new file mode 100644 index 00000000..ebea35c6 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java @@ -0,0 +1,292 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.Security; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; + +import org.apache.commons.lang3.RandomStringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.jose4j.jca.ProviderContext; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; +import org.jose4j.jwe.JsonWebEncryption; +import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; +import org.jose4j.lang.JoseException; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.databind.JsonNode; + +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.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_sl20_hsm.beans.xml") +public abstract class AbstractJsonSecurityUtilsTest { + + @Autowired protected DummyAuthConfigMap config; + @Autowired protected IJoseTools joseTools; + @Autowired protected EaafKeyStoreFactory keyStoreFactory; + + @BeforeClass + public static void classInitializer() { + Security.addProvider(new BouncyCastleProvider()); + + } + + protected abstract void setRsaSigningKey(); + + protected abstract void setEcSigningKey(); + + protected abstract void setRsaEncryptionKey(); + + protected abstract void setEcEncryptionKey(); + + protected abstract Pair getEncryptionKeyStore() throws EaafException; + + protected abstract String getRsaKeyAlias(); + + protected abstract String getRsaKeyPassword(); + + protected abstract String getEcKeyAlias(); + + protected abstract String getEcKeyPassword(); + + + @Test + public void fullEncryptDecrypt() throws JoseException, EaafException { + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(joseTools.getEncryptionCertificate().getPublicKey()); + jwe.setX509CertSha256ThumbprintHeaderValue(joseTools.getEncryptionCertificate()); + jwe.setPayload(payLoad); + + // set special provider if required + Pair rsaEncKeyStore = getEncryptionKeyStore(); + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + rsaEncKeyStore.getSecond().getName()); + jwe.setProviderContext(providerCtx); + + } + + String encData = jwe.getCompactSerialization(); + Assert.assertNotNull("JWE Encryption", encData); + + + JsonNode decData = joseTools.decryptPayload(encData); + Assert.assertNotNull("JWE Decryption", decData); + + } + + @Test + public void encryptionRsa() throws JoseException, EaafException { + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + Pair rsaEncKeyStore = getEncryptionKeyStore(); + Pair key = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + rsaEncKeyStore.getFirst(), getRsaKeyAlias(), getRsaKeyPassword().toCharArray(), + true, "jUnit RSA JWE"); + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(key.getSecond()[0].getPublicKey()); + jwe.setPayload(payLoad); + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + rsaEncKeyStore.getSecond().getName()); + jwe.setProviderContext(providerCtx); + + } + + String encData = jwe.getCompactSerialization(); + Assert.assertNotNull("JWE", encData); + + + } + + @Test + public void encryptionEc() throws JoseException, EaafException { + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + Pair rsaEncKeyStore = getEncryptionKeyStore(); + Pair key = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + rsaEncKeyStore.getFirst(), getEcKeyAlias(), getEcKeyPassword().toCharArray(), + true, "jUnit RSA JWE"); + + final JsonWebEncryption jwe = new JsonWebEncryption(); + jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW); + jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + jwe.setKey(key.getSecond()[0].getPublicKey()); + jwe.setPayload(payLoad); + + // set special provider if required + if (rsaEncKeyStore.getSecond() != null) { + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + rsaEncKeyStore.getSecond().getName()); + jwe.setProviderContext(providerCtx); + + } + + String encData = jwe.getCompactSerialization(); + + Assert.assertNotNull("JWE", encData); + + + } + + + @Test + public void noTrustedCert() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + try { + joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigOnlyEc()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (JoseException e) { + Assert.assertEquals("Wrong errorCode", + "Can NOT select verification key for JWS. Signature verification FAILED", + e.getMessage()); + + } + } + + @Test + public void invalidSignature() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + String invalidJws = + jws.substring(0, jws.indexOf(".") + 5) + "dd" + jws.substring(jws.indexOf(".") + 6); + + try { + joseTools.validateSignature( + invalidJws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (JoseException e) { + Assert.assertEquals("Wrong errorCode", + "JWS signature is invalid.", + e.getMessage()); + + } + + } + + @Test + public void validSigningRsa() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setRsaSigningKey(); + setRsaEncryptionKey(); + + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + VerificationResult verify = joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.assertTrue("wrong verify state", verify.isValidSigned()); + Assert.assertNotNull("JWS Header", verify.getJoseHeader()); + Assert.assertNotNull("JWS Payload", verify.getPayload()); + Assert.assertNotNull("CertChain", verify.getCertChain()); + + + } + + @Test + public void validSigningEc() throws CertificateEncodingException, KeyStoreException, + JoseException, IOException, EaafException { + setEcSigningKey(); + setEcEncryptionKey(); + + String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; + + String jws = joseTools.createSignature(payLoad); + Assert.assertNotNull("Signed msg", jws); + + VerificationResult verify = joseTools.validateSignature( + jws, + keyStoreFactory.buildNewKeyStore(getSigTrustStoreConfigValid()).getFirst(), + getDefaultAlgorithmConstrains()); + Assert.assertTrue("wrong verify state", verify.isValidSigned()); + Assert.assertNotNull("JWS Header", verify.getJoseHeader()); + Assert.assertNotNull("JWS Payload", verify.getPayload()); + Assert.assertNotNull("CertChain", verify.getCertChain()); + + } + + protected KeyStoreConfiguration getSigTrustStoreConfigValid() { + KeyStoreConfiguration trustConfig = new KeyStoreConfiguration(); + trustConfig.setFriendlyName("jUnit TrustStore"); + trustConfig.setKeyStoreType(KeyStoreType.JKS); + trustConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit.jks"); + trustConfig.setSoftKeyStorePassword("password"); + + return trustConfig; + + } + + protected KeyStoreConfiguration getSigTrustStoreConfigOnlyEc() { + KeyStoreConfiguration trustConfig = new KeyStoreConfiguration(); + trustConfig.setFriendlyName("jUnit TrustStore"); + trustConfig.setKeyStoreType(KeyStoreType.JKS); + trustConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit_no_rsa.jks"); + trustConfig.setSoftKeyStorePassword("password"); + + return trustConfig; + + } + + private AlgorithmConstraints getDefaultAlgorithmConstrains() { + return new AlgorithmConstraints(ConstraintType.WHITELIST, + SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING + .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); + } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java deleted file mode 100644 index 64987942..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsHsmKeyTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.security.Security; - -import org.apache.commons.lang3.RandomStringUtils; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("/spring/test_eaaf_sl20_hsm.beans.xml") -public class JsonSecurityUtilsHsmKeyTest { - - @Autowired private IJoseTools joseTools; - - @BeforeClass - public static void classInitializer() { - Security.addProvider(new BouncyCastleProvider()); - - } - - @Test - public void simpleSigningTest() throws SL20Exception { - String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; - - String jws = joseTools.createSignature(payLoad); - Assert.assertNotNull("Signed msg", jws); - - //VerificationResult verify = joseTools.validateSignature(jws); - //Assert.assertTrue("wrong verify state", verify.isValidSigned()); - - } - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java index 5b8acb16..d78bdbd7 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtilsSoftwareKeyTest.java @@ -1,42 +1,110 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils; -import java.security.Security; +import java.security.KeyStore; +import java.security.Provider; import org.apache.commons.lang3.RandomStringUtils; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.Base64Utils; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/spring/test_eaaf_sl20.beans.xml") -public class JsonSecurityUtilsSoftwareKeyTest { +public class JsonSecurityUtilsSoftwareKeyTest extends AbstractJsonSecurityUtilsTest { - @Autowired private IJoseTools joseTools; - - @BeforeClass - public static void classInitializer() { - Security.addProvider(new BouncyCastleProvider()); - + @Test + public void invalidSignatureRandomString() { + try { + joseTools.validateSignature(RandomStringUtils.randomAlphabetic(10)); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (SL20Exception e) { + Assert.assertEquals("Wrong errorCode", "sl20.05", e.getErrorId()); + } + } @Test - public void simpleSigningTest() throws SL20Exception { - String payLoad = "{\"aac\":\"" + RandomStringUtils.randomAlphanumeric(100) + "\"}"; - - String jws = joseTools.createSignature(payLoad); - Assert.assertNotNull("Signed msg", jws); + public void invalidSignatureRandomBase64UrlEncoded() { + String testValue = Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()) + + "." + + Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()) + + "." + + Base64Utils.encodeToUrlSafeString(RandomStringUtils.randomAlphanumeric(10).getBytes()); + + try { + joseTools.validateSignature(testValue); + Assert.fail("Wrong JOSE Sig not detected"); + + } catch (SL20Exception e) { + Assert.assertEquals("Wrong errorCode", "sl20.05", e.getErrorId()); + } - VerificationResult verify = joseTools.validateSignature(jws); - Assert.assertTrue("wrong verify state", verify.isValidSigned()); + } + + @Override + protected void setRsaSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "meta"); + + } + + @Override + protected void setEcSigningKey() { + config.putConfigValue("modules.sl20.security.sign.alias", "sig"); + + } + + @Override + protected void setRsaEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "meta"); + + } + + @Override + protected void setEcEncryptionKey() { + config.putConfigValue("modules.sl20.security.encryption.alias", "sig"); } + + @Override + protected Pair getEncryptionKeyStore() throws EaafException { + KeyStoreConfiguration keyConfig = new KeyStoreConfiguration(); + keyConfig.setFriendlyName("Junit Enc Key Rsa"); + keyConfig.setKeyStoreType(KeyStoreType.JKS); + keyConfig.setSoftKeyStoreFilePath("src/test/resources/data/junit.jks"); + keyConfig.setSoftKeyStorePassword("password"); + + return keyStoreFactory.buildNewKeyStore(keyConfig); + } + + @Override + protected String getRsaKeyAlias() { + return "meta"; + } + + @Override + protected String getRsaKeyPassword() { + return "password"; + } + + @Override + protected String getEcKeyAlias() { + return "sig"; + } + + @Override + protected String getEcKeyPassword() { + return "password"; + } } -- cgit v1.2.3