package at.gv.egiz.eaaf.core.impl.utils.test; import java.io.UnsupportedEncodingException; import java.security.Provider; import java.util.Base64; import javax.crypto.SecretKey; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.ReadableInstant; import org.joda.time.format.DateTimeFormat; 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.Ignore; 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.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; 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.AuthenticatedEncryptionPendingRequestIdGenerationStrategy; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/spring/test_eaaf_pvp_not_lazy.beans.xml") public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { @Autowired private EaafKeyStoreFactory keyStoreFactory; @Autowired private AuthenticatedEncryptionPendingRequestIdGenerationStrategy pendingIdStrategy; @Test public void generatePendingRequestId() throws EaafException { String pendingId = pendingIdStrategy.generateExternalPendingRequestId(); Assert.assertNotNull("pendingId", pendingId); } @Test public void validatePendingRequestId() throws EaafException { String extPendingId = pendingIdStrategy.generateExternalPendingRequestId(); Assert.assertNotNull("external pendingId", extPendingId); String pendingId = pendingIdStrategy.validateAndGetPendingRequestId(extPendingId); Assert.assertNotNull("internal pendingId", pendingId); String pendingId2 = pendingIdStrategy.getPendingRequestIdWithOutChecks(extPendingId); Assert.assertNotNull("internal pendingId", pendingId2); Assert.assertEquals("pendingId not match", pendingId, pendingId2); } @Test public void nullPendingRequestId() { try { pendingIdStrategy.validateAndGetPendingRequestId(null); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, PendingReqId is 'null' or empty]", e.getMessage()); } } @Test public void emptyPendingRequestId() { try { pendingIdStrategy.validateAndGetPendingRequestId(StringUtils.EMPTY); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, PendingReqId is 'null' or empty]", e.getMessage()); } } @Test public void noBase64UrlPendingRequestId() { try { pendingIdStrategy.validateAndGetPendingRequestId(RandomStringUtils.randomAlphanumeric(25)); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId is NOT a valid String]", e.getMessage()); } } @Test public void toLongBase64UrlPendingRequestId() { try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(RandomStringUtils.randomAlphanumeric(1100).getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "pendingReqId exceeds max.size: 1024]", e.getMessage()); } } @Test public void wrongFormat() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId has an unvalid format]", e.getMessage()); } } @Test public void wrongFormatToLong() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25) + "|" + RandomStringUtils.randomAlphanumeric(25) + "|" + "aabbcc"; String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId has an unvalid format]", e.getMessage()); } } @Test public void wrongFormatNoDate() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25) + "|" + RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId is NOT a valid String]", e.getMessage()); } } @Test public void wrongFormatWrongDate() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = "2020-01-01 12:01:55 111" + "|" + RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNotNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertTrue("Wrong errorMsg", e.getMessage().contains("PendingRequestId exceeds the valid period")); } } @Test public void wrongFormatNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId has an unvalid format]", e.getMessage()); } } @Test public void wrongFormatToLongNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25) + "|" + RandomStringUtils.randomAlphanumeric(25) + "|" + "aabbcc"; String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); try { pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId has an unvalid format]", e.getMessage()); } } @Test public void wrongFormatNoDateNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25) + "|" + RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); String intPendingId = pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.assertNotNull("Int PendingId", intPendingId); } @Test public void wrongFormatWrongDateNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = "2020-01-01 12:01:55 111" + "|" + RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); String intPendingId = pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.assertNotNull("Int PendingId", intPendingId); } @Test public void validFormat() throws EaafException, JoseException, UnsupportedEncodingException { String intId = RandomStringUtils.randomAlphanumeric(25); ReadableInstant now = DateTime.now(); String payLoad = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss SSS").print(now) + "|" + intId; String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); String intPendingId = pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.assertNotNull("Int PendingId", intPendingId); Assert.assertEquals("pendingId not match", intId, intPendingId); } @Test public void validFormatNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String intId = RandomStringUtils.randomAlphanumeric(25); String payLoad = "2020-01-01 12:01:55 111" + "|" + intId; String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); String intPendingId = pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.assertNotNull("Int PendingId", intPendingId); } @Test public void validFormatWrongDateNotValidation() throws EaafException, JoseException, UnsupportedEncodingException { String intId = RandomStringUtils.randomAlphanumeric(25); String payLoad = "2020-01-01 12:01:55 111" + "|" + intId; String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "pendingReqIdSecret"); String intPendingId = pendingIdStrategy.getPendingRequestIdWithOutChecks(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.assertNotNull("Int PendingId", intPendingId); Assert.assertEquals("pendingId not match", intId, intPendingId); } @Test public void wrongEncrypted() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.DIRECT, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, "wrongPassword"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId is NOT a valid encrypted]", e.getMessage()); } } @Ignore @Test public void wrongEncryptionAlg() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.A256KW, ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId has an unvalid format]", e.getMessage()); } } @Ignore @Test public void wrongKeyEncAlg() throws EaafException, JoseException, UnsupportedEncodingException { String payLoad = RandomStringUtils.randomAlphanumeric(25); String extPendingId = generateEncryptedPendingId(payLoad, KeyManagementAlgorithmIdentifiers.A128KW, ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256, "pendingReqIdSecret"); try { pendingIdStrategy.validateAndGetPendingRequestId(Base64.getUrlEncoder() .encodeToString(extPendingId.getBytes())); Assert.fail("Wrong pendingId not detected"); } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); Assert.assertEquals("Wrong errorMsg", "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " + "PendingReqId is NOT a valid String]", e.getMessage()); } } private String generateEncryptedPendingId(String payLoad, String direct, String aes128Gcm, String softKeyPassphrase) throws EaafException, JoseException, UnsupportedEncodingException { SymmetricKeyConfiguration config = new SymmetricKeyConfiguration(); config.setFriendlyName("jUnit"); config.setKeyType(SymmetricKeyType.PASSPHRASE); config.setSoftKeySalt("notRequiredInThisScenario"); config.setSoftKeyPassphrase(softKeyPassphrase); Pair key = keyStoreFactory.buildNewSymmetricKey(config); JsonWebEncryption encToken = new JsonWebEncryption(); encToken.setAlgorithmHeaderValue(direct); encToken.setEncryptionMethodHeaderParameter(aes128Gcm); encToken.setKey(key.getFirst()); encToken.setPayload(payLoad); return encToken.getCompactSerialization(); } }