diff --git a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/pom.xml b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/pom.xml
index f36866903200899673024fa6026157c1e4c5ea2d..fa122c3c976c0622f41c6cea0ac4c3d96e68ccca 100644
--- a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/pom.xml
+++ b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/pom.xml
@@ -33,7 +33,6 @@
   <properties>
     <!-- Name to display by the Extension Manager -->
     <xwiki.extension.name>Script Service for the Cryptographic API</xwiki.extension.name>
-    <checkstyle.suppressions.location>${basedir}/src/checkstyle/checkstyle-suppressions.xml</checkstyle.suppressions.location>
     <xwiki.jacoco.instructionRatio>0.00</xwiki.jacoco.instructionRatio>
   </properties>
   <dependencies>
diff --git a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/checkstyle/checkstyle-suppressions.xml b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/checkstyle/checkstyle-suppressions.xml
deleted file mode 100644
index f937ace71cb699faca550f78a1baf7d39afa498c..0000000000000000000000000000000000000000
--- a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/checkstyle/checkstyle-suppressions.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  ~ See the NOTICE file distributed with this work for additional
-  ~ information regarding copyright ownership.
-  ~
-  ~ This is free software; you can redistribute it and/or modify it
-  ~ under the terms of the GNU Lesser General Public License as
-  ~ published by the Free Software Foundation; either version 2.1 of
-  ~ the License, or (at your option) any later version.
-  ~
-  ~ This software is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  ~ Lesser General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU Lesser General Public
-  ~ License along with this software; if not, write to the Free
-  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-  -->
-
-<!DOCTYPE suppressions PUBLIC
-    "-//Puppy Crawl//DTD Suppressions 1.0//EN"
-    "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
-
-<suppressions>
-  <suppress checks="FanOutComplexity" files="RSACryptoScriptService.java"/>
-</suppressions>
diff --git a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/internal/RSACryptoHelper.java b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/internal/RSACryptoHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f4c071b04dec59f758c12fa65fdeb1ac1423b1a
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/internal/RSACryptoHelper.java
@@ -0,0 +1,210 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.xwiki.crypto.internal;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.crypto.params.cipher.asymmetric.AsymmetricKeyPair;
+import org.xwiki.crypto.params.cipher.asymmetric.PublicKeyParameters;
+import org.xwiki.crypto.pkix.CertificateGeneratorFactory;
+import org.xwiki.crypto.pkix.CertifyingSigner;
+import org.xwiki.crypto.pkix.X509ExtensionBuilder;
+import org.xwiki.crypto.pkix.params.CertifiedKeyPair;
+import org.xwiki.crypto.pkix.params.CertifiedPublicKey;
+import org.xwiki.crypto.pkix.params.x509certificate.DistinguishedName;
+import org.xwiki.crypto.pkix.params.x509certificate.X509CertificateGenerationParameters;
+import org.xwiki.crypto.pkix.params.x509certificate.X509CertificateParameters;
+import org.xwiki.crypto.pkix.params.x509certificate.X509CertifiedPublicKey;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.ExtendedKeyUsages;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.KeyUsage;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.X509DnsName;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.X509GeneralName;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.X509IpAddress;
+import org.xwiki.crypto.pkix.params.x509certificate.extension.X509Rfc822Name;
+import org.xwiki.crypto.signer.SignerFactory;
+
+/**
+ * Helper component for operations provided in {@link org.xwiki.crypto.script.RSACryptoScriptService}.
+ *
+ * @version $Id$
+ * @since 16.8.0RC1
+ */
+@Component(roles = RSACryptoHelper.class)
+@Singleton
+public class RSACryptoHelper
+{
+    @Inject
+    private Provider<X509ExtensionBuilder> extensionBuilder;
+
+    @Inject
+    @Named("X509")
+    private CertificateGeneratorFactory certificateGeneratorFactory;
+
+    @Inject
+    @Named("SHA256withRSAEncryption")
+    private SignerFactory signerFactory;
+
+    /**
+     * Create an end entity certificate. By default, the key can be used for encryption and signing. If the end entity
+     * contains some alternate subject names of type X509Rfc822Name a extended email protection usage is added. If the
+     * end entity contains some alternate subject names of type X509DnsName or X509IpAddress extended server and client
+     * authentication usages are added.
+     *
+     * @param issuer the keypair for issuing the certificate
+     * @param publicKey the public key to certify
+     * @param dn the distinguished name for the new the certificate.
+     * @param validity the validity of the certificate from now in days.
+     * @param subjectAltName the alternative names for the certificate
+     * @return a certified public key.
+     * @throws IOException in case on error while reading the public key.
+     * @throws GeneralSecurityException in case of error.
+     */
+    public CertifiedPublicKey issueCertificate(CertifiedKeyPair issuer, PublicKeyParameters publicKey,
+        String dn, int validity, List<X509GeneralName> subjectAltName) throws IOException, GeneralSecurityException
+    {
+        X509CertificateParameters params;
+        X509ExtensionBuilder builder = extensionBuilder.get().addKeyUsage(EnumSet.of(KeyUsage.digitalSignature,
+            KeyUsage.dataEncipherment));
+
+        if (subjectAltName != null) {
+            params = new X509CertificateParameters(
+                extensionBuilder.get().addSubjectAltName(false, subjectAltName.toArray(new X509GeneralName[]{}))
+                    .build());
+            Set<String> extUsage = new HashSet<>();
+            for (X509GeneralName genName : subjectAltName) {
+                if (genName instanceof X509Rfc822Name) {
+                    extUsage.add(ExtendedKeyUsages.EMAIL_PROTECTION);
+                } else if (genName instanceof X509DnsName || genName instanceof X509IpAddress) {
+                    extUsage.add(ExtendedKeyUsages.SERVER_AUTH);
+                    extUsage.add(ExtendedKeyUsages.CLIENT_AUTH);
+                }
+                builder.addExtendedKeyUsage(false, new ExtendedKeyUsages(extUsage));
+            }
+        } else {
+            params = new X509CertificateParameters();
+        }
+
+
+        return certificateGeneratorFactory.getInstance(
+                CertifyingSigner.getInstance(true, issuer, signerFactory),
+                new X509CertificateGenerationParameters(validity, builder.build()))
+            .generate(new DistinguishedName(dn), publicKey, params);
+    }
+
+    /**
+     * Create a self-signed certificate for a Root CA.
+     *
+     * @param keyPair the keypair to issue the certificate for and used for signing it.
+     * @param dn the distinguished name for the new the certificate.
+     * @param validity the validity of the certificate from now in days.
+     * @return a certified public key.
+     * @throws IOException in case on error while reading the public key.
+     * @throws GeneralSecurityException in case of error.
+     */
+    public CertifiedKeyPair issueRootCACertificate(AsymmetricKeyPair keyPair, String dn, int validity)
+        throws IOException, GeneralSecurityException
+    {
+        return new CertifiedKeyPair(
+            keyPair.getPrivate(),
+            certificateGeneratorFactory.getInstance(signerFactory.getInstance(true, keyPair.getPrivate()),
+                    new X509CertificateGenerationParameters(
+                        validity,
+                        extensionBuilder.get().addBasicConstraints(true)
+                            .addKeyUsage(true, EnumSet.of(KeyUsage.keyCertSign,
+                                KeyUsage.cRLSign))
+                            .build()))
+                .generate(new DistinguishedName(dn), keyPair.getPublic(),
+                    new X509CertificateParameters())
+        );
+    }
+
+    /**
+     * Create an intermediate CA certificate.
+     *
+     * @param issuer the certified keypair for issuing the certificate
+     * @param publicKey the public key to certify
+     * @param dn the distinguished name for the new the certificate.
+     * @param validity the validity of the certificate from now in days.
+     * @return a certified public key.
+     * @throws IOException in case on error while reading the public key.
+     * @throws GeneralSecurityException in case of error.
+     */
+    public CertifiedPublicKey issueIntermediateCertificate(CertifiedKeyPair issuer, PublicKeyParameters publicKey,
+        String dn, int validity)
+        throws IOException, GeneralSecurityException
+    {
+        return certificateGeneratorFactory.getInstance(
+                CertifyingSigner.getInstance(true, issuer, signerFactory),
+                new X509CertificateGenerationParameters(
+                    validity,
+                    extensionBuilder.get().addBasicConstraints(0)
+                        .addKeyUsage(EnumSet.of(KeyUsage.keyCertSign,
+                            KeyUsage.cRLSign))
+                        .build()))
+            .generate(new DistinguishedName(dn), publicKey,
+                new X509CertificateParameters());
+    }
+
+    /**
+     * Check that an X509 certificate chain is complete and is valid on a given date.
+     *
+     * @param chain the ordered chain of certificate starting from root CA.
+     * @param date the date to check the validity for, or null to check for now.
+     * @return true if the chain is a X509 certificate chain complete and valid on the given date.
+     */
+    public boolean checkX509CertificateChainValidity(Collection<CertifiedPublicKey> chain, Date date)
+    {
+        if (chain == null || chain.isEmpty()) {
+            return false;
+        }
+
+        Date checkDate = (date != null) ? date : new Date();
+        boolean rootExpected = true;
+        for (CertifiedPublicKey cert : chain) {
+            if (!(cert instanceof X509CertifiedPublicKey)) {
+                return false;
+            }
+            if (rootExpected) {
+                if (!((X509CertifiedPublicKey) cert).isRootCA()) {
+                    return false;
+                }
+                rootExpected = false;
+            }
+            if (!((X509CertifiedPublicKey) cert).isValidOn(checkDate)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/script/RSACryptoScriptService.java b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/script/RSACryptoScriptService.java
index 879616f3005d99e45782984188ca666b49d4c5b5..a8a05b989fea08151c5d458d624f396f6db6c028 100644
--- a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/script/RSACryptoScriptService.java
+++ b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/java/org/xwiki/crypto/script/RSACryptoScriptService.java
@@ -24,39 +24,27 @@
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.Date;
-import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import javax.inject.Inject;
 import javax.inject.Named;
-import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import org.xwiki.component.annotation.Component;
 import org.xwiki.crypto.KeyPairGenerator;
+import org.xwiki.crypto.internal.RSACryptoHelper;
 import org.xwiki.crypto.params.cipher.asymmetric.AsymmetricKeyPair;
 import org.xwiki.crypto.params.cipher.asymmetric.PrivateKeyParameters;
 import org.xwiki.crypto.params.cipher.asymmetric.PublicKeyParameters;
 import org.xwiki.crypto.params.generator.asymmetric.RSAKeyGenerationParameters;
 import org.xwiki.crypto.pkix.CertificateChainBuilder;
-import org.xwiki.crypto.pkix.CertificateGeneratorFactory;
 import org.xwiki.crypto.pkix.CertificateProvider;
 import org.xwiki.crypto.pkix.CertifyingSigner;
-import org.xwiki.crypto.pkix.X509ExtensionBuilder;
 import org.xwiki.crypto.pkix.params.CertifiedKeyPair;
 import org.xwiki.crypto.pkix.params.CertifiedPublicKey;
-import org.xwiki.crypto.pkix.params.x509certificate.DistinguishedName;
-import org.xwiki.crypto.pkix.params.x509certificate.X509CertificateGenerationParameters;
-import org.xwiki.crypto.pkix.params.x509certificate.X509CertificateParameters;
-import org.xwiki.crypto.pkix.params.x509certificate.X509CertifiedPublicKey;
-import org.xwiki.crypto.pkix.params.x509certificate.extension.ExtendedKeyUsages;
-import org.xwiki.crypto.pkix.params.x509certificate.extension.KeyUsage;
-import org.xwiki.crypto.pkix.params.x509certificate.extension.X509DnsName;
 import org.xwiki.crypto.pkix.params.x509certificate.extension.X509GeneralName;
-import org.xwiki.crypto.pkix.params.x509certificate.extension.X509IpAddress;
-import org.xwiki.crypto.pkix.params.x509certificate.extension.X509Rfc822Name;
 import org.xwiki.crypto.signer.CMSSignedDataGenerator;
 import org.xwiki.crypto.signer.CMSSignedDataVerifier;
 import org.xwiki.crypto.signer.SignerFactory;
@@ -86,15 +74,14 @@ public class RSACryptoScriptService implements ScriptService
     private KeyPairGenerator keyPairGenerator;
 
     @Inject
-    @Named("SHA256withRSAEncryption")
-    private SignerFactory signerFactory;
+    private CMSSignedDataVerifier cmsSignedDataVerifier;
 
     @Inject
-    private Provider<X509ExtensionBuilder> extensionBuilder;
+    private RSACryptoHelper rsaCryptoHelper;
 
     @Inject
-    @Named("X509")
-    private CertificateGeneratorFactory certificateGeneratorFactory;
+    @Named("SHA256withRSAEncryption")
+    private SignerFactory signerFactory;
 
     @Inject
     private CMSSignedDataGenerator cmsSignedDataGenerator;
@@ -103,9 +90,6 @@ public class RSACryptoScriptService implements ScriptService
     @Named("X509")
     private CertificateChainBuilder certificateChainBuilder;
 
-    @Inject
-    private CMSSignedDataVerifier cmsSignedDataVerifier;
-
     /**
      * Generate a new RSA key pair.
      *
@@ -179,18 +163,7 @@ public CertifiedKeyPair createCertifiedKeyPair(PrivateKeyParameters privateKey,
     public CertifiedKeyPair issueRootCACertificate(AsymmetricKeyPair keyPair, String dn, int validity)
         throws IOException, GeneralSecurityException
     {
-        return new CertifiedKeyPair(
-            keyPair.getPrivate(),
-            certificateGeneratorFactory.getInstance(signerFactory.getInstance(true, keyPair.getPrivate()),
-                new X509CertificateGenerationParameters(
-                    validity,
-                    extensionBuilder.get().addBasicConstraints(true)
-                        .addKeyUsage(true, EnumSet.of(KeyUsage.keyCertSign,
-                            KeyUsage.cRLSign))
-                        .build()))
-                .generate(new DistinguishedName(dn), keyPair.getPublic(),
-                    new X509CertificateParameters())
-        );
+        return this.rsaCryptoHelper.issueRootCACertificate(keyPair, dn, validity);
     }
 
     /**
@@ -248,16 +221,7 @@ public CertifiedPublicKey issueIntermediateCertificate(CertifiedKeyPair issuer,
         String dn, int validity)
         throws IOException, GeneralSecurityException
     {
-        return certificateGeneratorFactory.getInstance(
-            CertifyingSigner.getInstance(true, issuer, signerFactory),
-            new X509CertificateGenerationParameters(
-                validity,
-                extensionBuilder.get().addBasicConstraints(0)
-                    .addKeyUsage(EnumSet.of(KeyUsage.keyCertSign,
-                        KeyUsage.cRLSign))
-                    .build()))
-                .generate(new DistinguishedName(dn), publicKey,
-                    new X509CertificateParameters());
+        return this.rsaCryptoHelper.issueIntermediateCertificate(issuer, publicKey, dn, validity);
     }
 
     /**
@@ -319,33 +283,7 @@ public CertifiedPublicKey issueCertificate(PrivateKeyParameters privateKey, Cert
     public CertifiedPublicKey issueCertificate(CertifiedKeyPair issuer, PublicKeyParameters publicKey,
         String dn, int validity, List<X509GeneralName> subjectAltName) throws IOException, GeneralSecurityException
     {
-        X509CertificateParameters params;
-        X509ExtensionBuilder builder = extensionBuilder.get().addKeyUsage(EnumSet.of(KeyUsage.digitalSignature,
-            KeyUsage.dataEncipherment));
-
-        if (subjectAltName != null) {
-            params = new X509CertificateParameters(
-                extensionBuilder.get().addSubjectAltName(false, subjectAltName.toArray(new X509GeneralName[]{}))
-                    .build());
-            Set<String> extUsage = new HashSet<>();
-            for (X509GeneralName genName : subjectAltName) {
-                if (genName instanceof X509Rfc822Name) {
-                    extUsage.add(ExtendedKeyUsages.EMAIL_PROTECTION);
-                } else if (genName instanceof X509DnsName || genName instanceof X509IpAddress) {
-                    extUsage.add(ExtendedKeyUsages.SERVER_AUTH);
-                    extUsage.add(ExtendedKeyUsages.CLIENT_AUTH);
-                }
-                builder.addExtendedKeyUsage(false, new ExtendedKeyUsages(extUsage));
-            }
-        } else {
-            params = new X509CertificateParameters();
-        }
-
-
-        return certificateGeneratorFactory.getInstance(
-                CertifyingSigner.getInstance(true, issuer, signerFactory),
-                new X509CertificateGenerationParameters(validity, builder.build()))
-            .generate(new DistinguishedName(dn), publicKey, params);
+        return this.rsaCryptoHelper.issueCertificate(issuer, publicKey, dn, validity, subjectAltName);
     }
 
     /**
@@ -526,26 +464,6 @@ public boolean checkX509CertificateChainValidity(Collection<CertifiedPublicKey>
      */
     public boolean checkX509CertificateChainValidity(Collection<CertifiedPublicKey> chain, Date date)
     {
-        if (chain == null || chain.isEmpty()) {
-            return false;
-        }
-
-        Date checkDate = (date != null) ? date : new Date();
-        boolean rootExpected = true;
-        for (CertifiedPublicKey cert : chain) {
-            if (!(cert instanceof X509CertifiedPublicKey)) {
-                return false;
-            }
-            if (rootExpected) {
-                if (!((X509CertifiedPublicKey) cert).isRootCA()) {
-                    return false;
-                }
-                rootExpected = false;
-            }
-            if (!((X509CertifiedPublicKey) cert).isValidOn(checkDate)) {
-                return false;
-            }
-        }
-        return true;
+        return this.rsaCryptoHelper.checkX509CertificateChainValidity(chain, date);
     }
 }
diff --git a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/resources/META-INF/components.txt
index ecf99fda17448db8cd7b84dc40d336c8c6920e27..3eb87ecea33aa44a0a3ca0f3d2f949d7663f4aae 100644
--- a/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/resources/META-INF/components.txt
+++ b/xwiki-platform-core/xwiki-platform-crypto/xwiki-platform-crypto-script/src/main/resources/META-INF/components.txt
@@ -1,3 +1,4 @@
+org.xwiki.crypto.internal.RSACryptoHelper
 org.xwiki.crypto.script.CryptoScriptService
 org.xwiki.crypto.script.RSACryptoScriptService
 org.xwiki.crypto.script.StoreScriptService