[java-metadata-aggregator] 04/06: MDA-155 provide validator for small or invalid RSA exponents

Ian Young ian at iay.org.uk
Thu Dec 10 12:32:47 EST 2015


This is an automated email from the git hooks/post-receive script.

iay pushed a commit to branch master
in repository java-metadata-aggregator.

commit 84bceb13149c51ad0f247982a9810feeece3f091
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Thu Dec 10 17:24:07 2015 +0000

    MDA-155 provide validator for small or invalid RSA exponents
    
    Initial import from ukf-mda project.
---
 .../validate/x509/X509RSAExponentValidator.java    | 115 +++++++++++++++++++++
 .../x509/X509RSAExponentValidatorTest.java         |  65 ++++++++++++
 .../validate/x509/X509RSAExponentValidator-3.pem   |  21 ++++
 .../validate/x509/X509RSAExponentValidator-35.pem  |  27 +++++
 .../x509/X509RSAExponentValidator-65537.pem        |  22 ++++
 5 files changed, 250 insertions(+)

diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator.java
new file mode 100644
index 0000000..d855645
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development, 
+ * Inc. (UCAID) under one or more contributor license agreements.  See the 
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.metadata.validate.x509;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+
+import net.shibboleth.metadata.Item;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Validator class to check RSA public exponent values in X.509 certificates.
+ * 
+ * An instance of the class can be configured to have both a warning boundary and an
+ * error boundary. The default is to give an error for any exponent less than or equal to
+ * three, with no provision for warnings.
+ * 
+ * This NIST recommendation is for at least 65537 (2**16+1) but it's not obvious where
+ * this came from so doesn't seem worth insisting on by default.
+ */
+ at ThreadSafe
+public class X509RSAExponentValidator extends AbstractX509Validator {
+
+    /** The RSA public exponent value below which an error should result. Default: 5. */
+    private BigInteger errorBoundary = BigInteger.valueOf(5);
+    
+    /** The RSA public exponent value below which a warning should result. Default: 0 (disabled). */
+    private BigInteger warningBoundary = BigInteger.ZERO;
+    
+    /**
+     * Constructor.
+     */
+    public X509RSAExponentValidator() {
+        super();
+        setId("RSAExponent");
+    }
+
+    /**
+     * Get the RSA public exponent below which an error will result.
+     * 
+     * @return the RSA public exponent below which an error will result.
+     */
+    public long getErrorBoundary() {
+        return errorBoundary.longValue();
+    }
+    
+    /**
+     * Set the RSA public exponent below which an error should result.
+     * 
+     * @param length the RSA public exponent below which an error should result
+     */
+    public void setErrorBoundary(final long length) {
+        Constraint.isGreaterThanOrEqual(0, length, "boundary value must not be negative");
+        errorBoundary = BigInteger.valueOf(length);
+    }
+    
+    /**
+     * Get the RSA public exponent below which a warning will result.
+     * 
+     * @return the RSA public exponent below which a warning will result.
+     */
+    public long getWarningBoundary() {
+        return warningBoundary.longValue();
+    }
+    
+    /**
+     * Set the RSA public exponent below which a warning should result.
+     * 
+     * @param length the RSA public exponent below which a warning should result
+     */
+    public void setWarningBoundary(final long length) {
+        Constraint.isGreaterThanOrEqual(0, length, "boundary value must not be negative");
+        warningBoundary = BigInteger.valueOf(length);
+    }
+    
+    @Override
+    public void validate(@Nonnull final X509Certificate cert, @Nonnull final Item<?> item,
+            @Nonnull final String stageId) {
+        final PublicKey key = cert.getPublicKey();
+        if ("RSA".equals(key.getAlgorithm())) {
+            final RSAPublicKey rsaKey = (RSAPublicKey) key;
+            final BigInteger exponent = rsaKey.getPublicExponent();
+            if (!exponent.testBit(0)) {
+                addError("RSA public exponent of " + exponent + " must be odd", item, stageId);
+            } else if (exponent.compareTo(errorBoundary) < 0) {
+                addError("RSA public exponent of " + exponent + " is less than required " + errorBoundary,
+                        item, stageId);
+            } else if (exponent.compareTo(warningBoundary) < 0) {
+                addWarning("RSA public exponent of " + exponent + " is less than recommended " + warningBoundary,
+                        item, stageId);
+            }
+        }
+    }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidatorTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidatorTest.java
new file mode 100644
index 0000000..83463e4
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/validate/x509/X509RSAExponentValidatorTest.java
@@ -0,0 +1,65 @@
+
+package net.shibboleth.metadata.validate.x509;
+
+import java.security.cert.X509Certificate;
+
+import net.shibboleth.metadata.Item;
+import net.shibboleth.metadata.MockItem;
+import net.shibboleth.metadata.validate.Validator;
+
+import org.testng.annotations.Test;
+
+public class X509RSAExponentValidatorTest extends BaseX509ValidatorTest {
+    
+    /** Constructor sets class under test. */
+    public X509RSAExponentValidatorTest() throws Exception {
+        super(X509RSAExponentValidator.class);
+    }
+
+    private void testCert(final String certName,
+            final Validator<X509Certificate> val,
+            final int expectedErrors, final int expectedWarnings) throws Exception {
+        final Item<String> item = new MockItem("foo");
+        final X509Certificate cert = getCertificate(certName);
+        val.validate(cert, item, "stage");
+        errorsAndWarnings(item, expectedErrors, expectedWarnings);
+    }
+
+    private void testThreeCerts(final Validator<X509Certificate> val,
+            final int expectedErrors3, final int expectedWarnings3,
+            final int expectedErrors35, final int expectedWarnings35,
+            final int expectedErrors65537, final int expectedWarnings65537) throws Exception {
+        testCert("3.pem", val, expectedErrors3, expectedWarnings3); // exponent == 3
+        testCert("35.pem", val, expectedErrors35, expectedWarnings35); // exponent == 35
+        testCert("65537.pem", val, expectedErrors65537, expectedWarnings65537); // exponent == 65537
+    }
+    
+    @Test
+    public void testDefaults() throws Exception {
+        final X509RSAExponentValidator val = new X509RSAExponentValidator();
+        testThreeCerts(val, 1, 0, 0, 0, 0, 0);
+    }
+
+    @Test
+    public void testNISTWarning() throws Exception {
+        final X509RSAExponentValidator val = new X509RSAExponentValidator();
+        val.setWarningBoundary(65537);
+        testThreeCerts(val, 1, 0, 0, 1, 0, 0);
+    }
+
+    @Test
+    public void testNISTError() throws Exception {
+        final X509RSAExponentValidator val = new X509RSAExponentValidator();
+        val.setErrorBoundary(65537);
+        testThreeCerts(val, 1, 0, 1, 0, 0, 0);
+    }
+
+    @Test
+    public void testWarningOnly() throws Exception {
+        final X509RSAExponentValidator val = new X509RSAExponentValidator();
+        val.setErrorBoundary(0);
+        val.setWarningBoundary(65537);
+        testThreeCerts(val, 0, 1, 0, 1, 0, 0);
+    }
+
+}
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-3.pem b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-3.pem
new file mode 100644
index 0000000..92de831
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-3.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDgzCCAmugAwIBAgIJALJ4x0pefs06MA0GCSqGSIb3DQEBBQUAMFkxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWV4cG9uZW50MzAeFw0xMzExMjAxNjI1
+MTNaFw0xMzEyMjAxNjI1MTNaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l
+LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV
+BAMMCWV4cG9uZW50MzCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBALRb
+mfVz1+aj6QdHnGBmykVOwtaCPj5QtHq6ghRQ7GgvYjZA9oOCa+DRmTcZzvp/mwm8
+CiCjMQE58OIF5LIE1WCToNWk3PjbcGRd6zqGulonFclXWsWrcFLEUP3Zv+1WRvbS
+Mqh1arsFFgC+t3kkJvEdXloVFoCUE6kiIOWCcUmI7b0lHiUhxV/qfCd/NNszdqNn
+BEGqiSSW0MSBfMBuIehm4M9jZtrGslVEfggBchJh5bN/DL/OhNWzNXuf/IVaZRTY
+tS7LTuGHTpqaTD6twGgBRwYSNBrZ23b7ThkzvdIRPivDU4F+touLkl+vIJyUx2SA
+DLezHgxil/GCo3HWwjMCAQOjUDBOMB0GA1UdDgQWBBTfMwp0CVCqcGKyGFGUQZPp
+y06eIDAfBgNVHSMEGDAWgBTfMwp0CVCqcGKyGFGUQZPpy06eIDAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQANDh63Hayi3ZqVpTm2+l15KFNLlPwsTTyw
+qqDG3M6S3bg2LAvDD7jgrzk2cWkcEr3hbcZoichWadiwBWgQki9LGMweApDPcIO6
+TU+Y1EXeTC+WwKm4Wk4+1HplQHIx2bYzg3qktOWRN8mhfDJ9RLPIpp9iYm7LpGto
+PC2KaXz/I7UTE/2zLWkx6turKBqCkbYJ4ZVi6JF6ZMC5QRUhuzLlL4HHj0Anicvt
+kbLfRxUkOM8NbPqT4iHGw+Uj5DNdxTs04FBWQMynUfTBqw1waIOgyHXNSyFbsSah
+KQmEwyVr3vgFnAswSVrGDroqNWX/blvhCRu19VZMHMw5Qyr50VBs
+-----END CERTIFICATE-----
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-35.pem b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-35.pem
new file mode 100644
index 0000000..0cb27f3
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-35.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEojCCA4qgAwIBAgIRAPAgFccUOwHXw+NHO3EBPLIwDQYJKoZIhvcNAQEFBQAw
+NjELMAkGA1UEBhMCTkwxDzANBgNVBAoTBlRFUkVOQTEWMBQGA1UEAxMNVEVSRU5B
+IFNTTCBDQTAeFw0xMjAxMTIwMDAwMDBaFw0xNTAxMTEyMzU5NTlaMHwxCzAJBgNV
+BAYTAkdCMQ4wDAYDVQQIEwVEZXZvbjERMA8GA1UEBxMIUGx5bW91dGgxHzAdBgNV
+BAoTFlVuaXZlcnNpdHkgb2YgUGx5bW91dGgxDDAKBgNVBAsTA0lMUzEbMBkGA1UE
+AxMSaWRwLnBseW1vdXRoLmFjLnVrMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIB
+CAKCAQEA2cxCI11J+TQ0XHlfomNIzFRmUvZ4Y63NcL94TOMpFkbV7idiAkwbydCi
+grpv5oKEGT4hrFB1woHOFmC7iJTO+0jcw0uKALFHyR7kf9KVxKy42Sklsoz73SJf
+TmaNhpvbnzfw9fbtSNH2IjzAnSGoG7xKj7v3Nq/MT1ApjAm57tpj3tE5bwG1TzCp
+7tvdCXVJHx++heCMVG0g6ZhlOoH6Y8cJSqBri2z4cTpOcB+uAlaacUszS4hM4j2m
+2miiRdlA81KX72GH6q6FuWQWygOzD0wMl7ycBzpF3d9cIdUrS1qNIqOmkRGmBgXk
+j2QjWxArO/aVGcEaCCPjOxiPlUQEUQIBI6OCAWUwggFhMB8GA1UdIwQYMBaAFAy9
+k2gM896ro0lrKzdXR+qQ47ntMB0GA1UdDgQWBBREvPPuf6gQb2OMLPtaoSOCX+L6
+zjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEF
+BQcDAQYIKwYBBQUHAwIwGAYDVR0gBBEwDzANBgsrBgEEAbIxAQICHTA6BgNVHR8E
+MzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVOQVNTTENB
+LmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9jcnQudGNz
+LnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpodHRwOi8v
+b2NzcC50Y3MudGVyZW5hLm9yZzAdBgNVHREEFjAUghJpZHAucGx5bW91dGguYWMu
+dWswDQYJKoZIhvcNAQEFBQADggEBAI+28c16qkQLYd10tvEk9Id2HWyoawuFBdlg
+HUYUWvXF8OllyXUxtkQnELy6boQrRqK+XbtVPlZrbXtb0OLdYri1J5O+rNumzSX/
+lEy3Q/6n172RObPQqd35HYcReEHLB64D5dAbrr5VLEspPneLAluyKc94rS7vtuim
+vxBSL8/3DeG5O3gVyQVsRN/DGq2MOui82bjoINoBdLAlhO4jHu2LH1EcY9zql13i
+HGMqojRFDFchKtjoKm4y1i1qFQXllYAglyXUBGei/DdVk6zGtv+XDLJDdjm2fUt0
+37HLzgXSRUxWkoLzCzFxYhO/VHJJvFjUswGOeuzDpxSNG70XoZA=
+-----END CERTIFICATE-----
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-65537.pem b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-65537.pem
new file mode 100644
index 0000000..0418de2
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/validate/x509/X509RSAExponentValidator-65537.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIJAJlJWgeSp3K/MA0GCSqGSIb3DQEBBQUAMF0xCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQxFjAUBgNVBAMMDWV4cG9uZW50NjU1MzcwHhcNMTMxMTIw
+MTYyNTM5WhcNMTMxMjIwMTYyNTM5WjBdMQswCQYDVQQGEwJBVTETMBEGA1UECAwK
+U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRYw
+FAYDVQQDDA1leHBvbmVudDY1NTM3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA5Vgc6fJWxckSvIMKPJSN5/buzE/I5CpHucTf1ZWHUlhcmkNrRQoDl+94
+iryM2v62t4MmehS6oBHGT4eJ9avqagzwXAPdUFLSIBa3TnVi4cX/5bwl932wDMJE
+qsPYrorv/zFs22XMjKJ5igahTMpa6qmQkjRH8p5cTfRan8LgYeW0PNYZhBGuy4Da
+C2CRuplMWINAYuLZsWLTXhSe0Y+NJnRKDOGsAUsHphi6/REkjwMpD1zOz8ljkfUn
+NzpdaeMl3AK8ubhLVXc127rayfpgb4U+7a4yDyC/5Dt7vwwx0slq+/GFGOKLbU8H
+AgCmTYNmbrt/68bpywcDvZhnOEfc0wIDAQABo1AwTjAdBgNVHQ4EFgQUdsNE7q7f
+cjyqffss1+Yad6ovoawwHwYDVR0jBBgwFoAUdsNE7q7fcjyqffss1+Yad6ovoaww
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAR0Ob26lk50C/yu5Iiqhz
+m6odwas0tEYEhf7w9u4bxuAueAto9/1y8IXjh0/UcMBjHN4EXqjkqXDGg6IS6Lye
+Y5kGgYaAaxYAJ8oYpmhUGWWXE+p8neAknSCgj65EDS7NU8J7rv/WiIetHYt456A3
+4rHvRKBPIVypt2kAFCmOKedwCsYfUBBYp4fDsxDrHDiOnGqEeOcrSzsN8ubcMwCN
+ONrwTDBxLoSA3ow+yPRVeGU1Kv0RXSlirX7LKmjWdDg5/WdAM/KkCOJRyQFBRadK
+gtL+YmChQkZ0tyTa6bkdTsGvlZV9SuMARKjiNFDnhQ3kjdCJohmfiGxXwsKM2FNF
+1Q==
+-----END CERTIFICATE-----

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list