You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ol...@apache.org on 2019/12/05 20:41:29 UTC

[sling-org-apache-sling-commons-crypto] branch master updated: SLING-8885 Provide an extensible crypto implementation based on Jasypt

This is an automated email from the ASF dual-hosted git repository.

olli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-crypto.git


The following commit(s) were added to refs/heads/master by this push:
     new def23b1  SLING-8885 Provide an extensible crypto implementation based on Jasypt
def23b1 is described below

commit def23b11d584d1991df2ccb9f1d31676cb82775e
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Thu Dec 5 21:40:05 2019 +0100

    SLING-8885 Provide an extensible crypto implementation based on Jasypt
---
 pom.xml                                            |  14 ++
 .../internal/JasyptRandomIvGeneratorRegistrar.java |  75 +++++++++++
 ...yptRandomIvGeneratorRegistrarConfiguration.java |  37 ++++++
 .../JasyptRandomSaltGeneratorRegistrar.java        |  75 +++++++++++
 ...tRandomSaltGeneratorRegistrarConfiguration.java |  37 ++++++
 .../JasyptStandardPBEStringCryptoService.java      | 143 +++++++++++++++++++++
 ...tandardPBEStringCryptoServiceConfiguration.java |  93 ++++++++++++++
 .../commons/crypto/it/tests/CryptoTestSupport.java |   2 +
 .../JasyptStandardPBEStringCryptoServiceIT.java    |  76 +++++++++++
 src/test/resources/password.ascii85                |   1 +
 10 files changed, 553 insertions(+)

diff --git a/pom.xml b/pom.xml
index 9e20357..77afcb2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,13 @@
       <artifactId>org.osgi.service.metatype.annotations</artifactId>
       <scope>provided</scope>
     </dependency>
+    <!-- Apache Commons -->
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.9</version>
+      <scope>provided</scope>
+    </dependency>
     <!-- Apache Felix -->
     <dependency>
       <groupId>org.apache.felix</groupId>
@@ -158,6 +165,13 @@
       <version>1.0.1</version>
       <scope>test</scope>
     </dependency>
+    <!-- Jasypt -->
+    <dependency>
+      <groupId>org.apache.servicemix.bundles</groupId>
+      <artifactId>org.apache.servicemix.bundles.jasypt</artifactId>
+      <version>1.9.3_1</version>
+      <scope>provided</scope>
+    </dependency>
     <!-- JSR 305-->
     <dependency>
       <groupId>org.jetbrains</groupId>
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrar.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrar.java
new file mode 100644
index 0000000..ef53c58
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrar.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Objects;
+
+import org.jasypt.iv.IvGenerator;
+import org.jasypt.iv.RandomIvGenerator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.metatype.annotations.Designate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+    property = {
+        Constants.SERVICE_DESCRIPTION + "=Apache Sling Commons Crypto – Jasypt Random IV Generator Registrar",
+        Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
+    }
+)
+@Designate(
+    ocd = JasyptRandomIvGeneratorRegistrarConfiguration.class,
+    factory = true
+)
+public class JasyptRandomIvGeneratorRegistrar {
+
+    private ServiceRegistration<IvGenerator> serviceRegistration;
+
+    private final Logger logger = LoggerFactory.getLogger(JasyptRandomIvGeneratorRegistrar.class);
+
+    public JasyptRandomIvGeneratorRegistrar() {
+    }
+
+    @Activate
+    private void activate(final JasyptRandomIvGeneratorRegistrarConfiguration configuration, final BundleContext bundleContext) {
+        logger.debug("activating");
+        final String algorithm = configuration.algorithm();
+        final RandomIvGenerator ivGenerator = new RandomIvGenerator(algorithm);
+        final Dictionary<String, String> properties = new Hashtable<>();
+        properties.put("algorithm", algorithm);
+        logger.debug("registering Random IV Generator with algorithm {}", algorithm);
+        serviceRegistration = bundleContext.registerService(IvGenerator.class, ivGenerator, properties);
+    }
+
+    @Deactivate
+    private void deactivate() {
+        logger.debug("deactivating");
+        if (Objects.nonNull(serviceRegistration)) {
+            serviceRegistration.unregister();
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrarConfiguration.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrarConfiguration.java
new file mode 100644
index 0000000..6483950
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomIvGeneratorRegistrarConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import org.jasypt.iv.RandomIvGenerator;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(
+    name = "Apache Sling Commons Crypto “Jasypt Random IV Generator Registrar”",
+    description = "TODO"
+)
+@interface JasyptRandomIvGeneratorRegistrarConfiguration {
+
+    @AttributeDefinition(
+        name = "Algorithm",
+        description = "secure random number generation algorithm"
+    )
+    String algorithm() default RandomIvGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM;
+
+}
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrar.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrar.java
new file mode 100644
index 0000000..9678e43
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrar.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Objects;
+
+import org.jasypt.salt.RandomSaltGenerator;
+import org.jasypt.salt.SaltGenerator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.metatype.annotations.Designate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+    property = {
+        Constants.SERVICE_DESCRIPTION + "=Apache Sling Commons Crypto – Jasypt Random Salt Generator Registrar",
+        Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
+    }
+)
+@Designate(
+    ocd = JasyptRandomSaltGeneratorRegistrarConfiguration.class,
+    factory = true
+)
+public class JasyptRandomSaltGeneratorRegistrar {
+
+    private ServiceRegistration<SaltGenerator> serviceRegistration;
+
+    private final Logger logger = LoggerFactory.getLogger(JasyptRandomSaltGeneratorRegistrar.class);
+
+    public JasyptRandomSaltGeneratorRegistrar() {
+    }
+
+    @Activate
+    private void activate(final JasyptRandomSaltGeneratorRegistrarConfiguration configuration, final BundleContext bundleContext) {
+        logger.debug("activating");
+        final String algorithm = configuration.algorithm();
+        final RandomSaltGenerator saltGenerator = new RandomSaltGenerator(algorithm);
+        final Dictionary<String, String> properties = new Hashtable<>();
+        properties.put("algorithm", algorithm);
+        logger.debug("registering Random Salt Generator with algorithm {}", algorithm);
+        serviceRegistration = bundleContext.registerService(SaltGenerator.class, saltGenerator, properties);
+    }
+
+    @Deactivate
+    private void deactivate() {
+        logger.debug("deactivating");
+        if (Objects.nonNull(serviceRegistration)) {
+            serviceRegistration.unregister();
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrarConfiguration.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrarConfiguration.java
new file mode 100644
index 0000000..68c8793
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptRandomSaltGeneratorRegistrarConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import org.jasypt.salt.RandomSaltGenerator;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(
+    name = "Apache Sling Commons Crypto “Jasypt Random Salt Generator Registrar”",
+    description = "TODO"
+)
+@interface JasyptRandomSaltGeneratorRegistrarConfiguration {
+
+    @AttributeDefinition(
+        name = "Algorithm",
+        description = "secure random number generation algorithm"
+    )
+    String algorithm() default RandomSaltGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM;
+
+}
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoService.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoService.java
new file mode 100644
index 0000000..46e5107
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoService.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import java.security.Provider;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.commons.crypto.CryptoService;
+import org.apache.sling.commons.crypto.PasswordProvider;
+import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
+import org.jasypt.iv.IvGenerator;
+import org.jasypt.registry.AlgorithmRegistry;
+import org.jasypt.salt.SaltGenerator;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.metatype.annotations.Designate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+    property = {
+        Constants.SERVICE_DESCRIPTION + "=Apache Sling Commons Crypto – Jasypt Standard PBE String Crypto Service",
+        Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
+    }
+)
+@Designate(
+    ocd = JasyptStandardPBEStringCryptoServiceConfiguration.class,
+    factory = true
+)
+public class JasyptStandardPBEStringCryptoService implements CryptoService {
+
+    @Reference
+    private volatile PasswordProvider passwordProvider;
+
+    @Reference
+    private volatile IvGenerator ivGenerator;
+
+    @Reference(
+        cardinality = ReferenceCardinality.OPTIONAL
+    )
+    private volatile Provider provider;
+
+    @Reference(
+        cardinality = ReferenceCardinality.OPTIONAL
+    )
+    private volatile SaltGenerator saltGenerator;
+
+    private StandardPBEStringEncryptor encryptor;
+
+    private final Logger logger = LoggerFactory.getLogger(JasyptStandardPBEStringCryptoService.class);
+
+    public JasyptStandardPBEStringCryptoService() {
+    }
+
+    @Activate
+    private void activate(final JasyptStandardPBEStringCryptoServiceConfiguration configuration) {
+        logger.debug("activating");
+        setupEncryptor(configuration);
+    }
+
+    @Modified
+    private void modified(final JasyptStandardPBEStringCryptoServiceConfiguration configuration) {
+        logger.debug("modifying");
+        setupEncryptor(configuration);
+    }
+
+    @Deactivate
+    private void deactivate() {
+        logger.debug("deactivating");
+        this.encryptor = null;
+    }
+
+    private void setupEncryptor(final JasyptStandardPBEStringCryptoServiceConfiguration configuration) {
+        final String algorithm = configuration.algorithm();
+        final Set<?> algorithms = AlgorithmRegistry.getAllPBEAlgorithms();
+        if (!algorithms.contains(algorithm)) {
+            logger.warn("Configured algorithm {} for password based encryption is not available. {}", algorithm, algorithms);
+        }
+        final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
+        // mandatory
+        encryptor.setAlgorithm(algorithm);
+        final IvGenerator ivGenerator = this.ivGenerator;
+        if (Objects.nonNull(ivGenerator)) {
+            encryptor.setIvGenerator(ivGenerator);
+        }
+        // optional
+        encryptor.setKeyObtentionIterations(configuration.keyObtentionIterations());
+        encryptor.setStringOutputType(configuration.stringOutputType());
+        if (StringUtils.isNotBlank(configuration.providerName())) {
+            encryptor.setProviderName(configuration.providerName());
+        }
+        final Provider provider = this.provider;
+        if (Objects.nonNull(provider)) {
+            encryptor.setProvider(provider);
+        }
+        final SaltGenerator saltGenerator = this.saltGenerator;
+        if (Objects.nonNull(saltGenerator)) {
+            encryptor.setSaltGenerator(saltGenerator);
+        }
+        // set mandatory password, initialize encryptor, clear password
+        final char[] password = passwordProvider.getPassword();
+        encryptor.setPasswordCharArray(password);
+        encryptor.initialize();
+        Arrays.fill(password, '0');
+        this.encryptor = encryptor;
+    }
+
+    @Override
+    public @NotNull String encrypt(@NotNull final String message) {
+        return encryptor.encrypt(message);
+    }
+
+    @Override
+    public @NotNull String decrypt(@NotNull final String message) {
+        return encryptor.decrypt(message);
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoServiceConfiguration.java b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoServiceConfiguration.java
new file mode 100644
index 0000000..9968645
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/jasypt/internal/JasyptStandardPBEStringCryptoServiceConfiguration.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.jasypt.internal;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.osgi.service.metatype.annotations.Option;
+
+import static org.jasypt.commons.CommonUtils.STRING_OUTPUT_TYPE_BASE64;
+import static org.jasypt.commons.CommonUtils.STRING_OUTPUT_TYPE_HEXADECIMAL;
+import static org.jasypt.encryption.pbe.StandardPBEByteEncryptor.DEFAULT_KEY_OBTENTION_ITERATIONS;
+
+@ObjectClassDefinition(
+    name = "Apache Sling Commons Crypto “Jasypt Standard PBE String Crypto Service”",
+    description = "TODO"
+)
+@interface JasyptStandardPBEStringCryptoServiceConfiguration {
+
+    @AttributeDefinition(
+        name = "Names",
+        description = "names of this service"
+    )
+    String[] names() default {"default"};
+
+    @AttributeDefinition(
+        name = "Algorithm",
+        description = "TODO"
+    )
+    String algorithm() default "PBEWITHHMACSHA512ANDAES_256";
+
+    @AttributeDefinition(
+        name = "Key Obtention Iterations",
+        description = "number of hashing iterations applied for obtaining the encryption key from the specified password"
+    )
+    int keyObtentionIterations() default DEFAULT_KEY_OBTENTION_ITERATIONS;
+
+    @AttributeDefinition(
+        name = "Provider Name",
+        description = "TODO"
+    )
+    String providerName();
+
+    @AttributeDefinition(
+        name = "String Output Type",
+        description = "TODO",
+        options = {
+            @Option(label = "Base16 (hexadecimal)", value = STRING_OUTPUT_TYPE_HEXADECIMAL),
+            @Option(label = "Base64", value = STRING_OUTPUT_TYPE_BASE64)
+        }
+    )
+    String stringOutputType() default STRING_OUTPUT_TYPE_BASE64;
+
+    @AttributeDefinition(
+        name = "Provider Name",
+        description = "TODO"
+    )
+    String passwordProvider_target();
+
+    @AttributeDefinition(
+        name = "Provider Name",
+        description = "filter expression to target a Security Provider"
+    )
+    String provider_target();
+
+    @AttributeDefinition(
+        name = "IV Generator Target",
+        description = "filter expression to target an IV Generator"
+    )
+    String ivGenerator_target();
+
+    @AttributeDefinition(
+        name = "Provider Name",
+        description = "filter expression to target a Salt Generator"
+    )
+    String saltGenerator_target();
+
+}
diff --git a/src/test/java/org/apache/sling/commons/crypto/it/tests/CryptoTestSupport.java b/src/test/java/org/apache/sling/commons/crypto/it/tests/CryptoTestSupport.java
index 42e0a88..34a61f7 100644
--- a/src/test/java/org/apache/sling/commons/crypto/it/tests/CryptoTestSupport.java
+++ b/src/test/java/org/apache/sling/commons/crypto/it/tests/CryptoTestSupport.java
@@ -35,6 +35,8 @@ public abstract class CryptoTestSupport extends TestSupport {
             super.baseConfiguration(),
             // Sling Commons Crypto
             testBundle("bundle.filename"),
+            mavenBundle().groupId("org.apache.commons").artifactId("commons-lang3").versionAsInProject(),
+            mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.jasypt").versionAsInProject(),
             scr(),
             // testing
             junitBundles(),
diff --git a/src/test/java/org/apache/sling/commons/crypto/it/tests/jasypt/JasyptStandardPBEStringCryptoServiceIT.java b/src/test/java/org/apache/sling/commons/crypto/it/tests/jasypt/JasyptStandardPBEStringCryptoServiceIT.java
new file mode 100644
index 0000000..ba44b92
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/crypto/it/tests/jasypt/JasyptStandardPBEStringCryptoServiceIT.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.crypto.it.tests.jasypt;
+
+import javax.inject.Inject;
+
+import org.apache.sling.commons.crypto.CryptoService;
+import org.apache.sling.commons.crypto.it.tests.CryptoTestSupport;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.util.PathUtils;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.jasypt.iv.RandomIvGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class JasyptStandardPBEStringCryptoServiceIT extends CryptoTestSupport {
+
+    @Inject
+    private CryptoService cryptoService;
+
+    @Configuration
+    public Option[] configuration() {
+        final String path = String.format("%s/src/test/resources/password.ascii85", PathUtils.getBaseDir());
+        return options(
+            baseConfiguration(),
+            factoryConfiguration("org.apache.sling.commons.crypto.jasypt.internal.JasyptStandardPBEStringCryptoService")
+                .put("algorithm", "PBEWITHHMACSHA512ANDAES_256")
+                .asOption(),
+            factoryConfiguration("org.apache.sling.commons.crypto.jasypt.internal.JasyptRandomIvGeneratorRegistrar")
+                .put("algorithm", DEFAULT_SECURE_RANDOM_ALGORITHM)
+                .asOption(),
+            factoryConfiguration("org.apache.sling.commons.crypto.internal.FilePasswordProvider")
+                .put("path", path)
+                .asOption()
+        );
+    }
+
+    @Test
+    public void testCryptoService() {
+        assertThat(cryptoService).isNotNull();
+    }
+
+    @Test
+    public void testEncryptAndDecrypt() {
+        final String message = "Rudy, a Message to You";
+        final String encrypted = cryptoService.encrypt(message);
+        final String decrypted = cryptoService.decrypt(encrypted);
+        assertThat(decrypted).isEqualTo(message);
+    }
+
+}
diff --git a/src/test/resources/password.ascii85 b/src/test/resources/password.ascii85
new file mode 100644
index 0000000..ad66ce8
--- /dev/null
+++ b/src/test/resources/password.ascii85
@@ -0,0 +1 @@
++AQ?aDes!'DBMkrCi:FE6q\sOn=Pbmn=PK8n=PK?
\ No newline at end of file