[java-opensaml] 03/15: Additional base crypto support for ECDH operations.

Brent Putman putmanb at georgetown.edu
Thu Jan 21 21:33:23 UTC 2021


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

putmanb pushed a commit to branch dev/OSJ-82
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=c26e5c1dc7180ffe8487c894016f120c56007fa1

commit c26e5c1dc7180ffe8487c894016f120c56007fa1
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu Dec 17 21:23:58 2020 -0500

    Additional base crypto support for ECDH operations.
---
 .../org/opensaml/security/crypto/KeySupport.java   | 55 +++++++++++++
 .../org/opensaml/security/crypto/ec/ECSupport.java | 90 ++++++++++++++++++++++
 .../opensaml/security/crypto/ec/ECSupportTest.java | 75 ++++++++++++++++++
 3 files changed, 220 insertions(+)

diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/crypto/KeySupport.java b/opensaml-security-api/src/main/java/org/opensaml/security/crypto/KeySupport.java
index 2b1eceb54..d774c7399 100644
--- a/opensaml-security-api/src/main/java/org/opensaml/security/crypto/KeySupport.java
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/crypto/KeySupport.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
 import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
 import java.security.Key;
 import java.security.KeyException;
 import java.security.KeyFactory;
@@ -42,6 +43,7 @@ import java.security.interfaces.RSAKey;
 import java.security.interfaces.RSAPrivateCrtKey;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.DSAPublicKeySpec;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.KeySpec;
@@ -452,6 +454,33 @@ public final class KeySupport {
         return keyGenerator.generateKey();
     }
 
+    /**
+     * Generate a random symmetric key.
+     * 
+     * @param algo key algorithm
+     * @param paramSpec the algorithm parameter specification
+     * @param provider JCA provider
+     * @return randomly generated symmetric key
+     * @throws NoSuchAlgorithmException algorithm not found
+     * @throws NoSuchProviderException provider not found
+     * @throws InvalidAlgorithmParameterException invalid parameter specification
+     */
+    @Nonnull public static SecretKey generateKey(@Nonnull final String algo,
+            @Nonnull final AlgorithmParameterSpec paramSpec, @Nullable final String provider)
+                    throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
+        Constraint.isNotNull(algo, "Key algorithm cannot be null");
+        Constraint.isNotNull(paramSpec, "Algorithm parameter spec cannot be null");
+        
+        KeyGenerator keyGenerator = null;
+        if (provider != null) {
+            keyGenerator = KeyGenerator.getInstance(algo, provider);
+        } else {
+            keyGenerator = KeyGenerator.getInstance(algo);
+        }
+        keyGenerator.init(paramSpec);
+        return keyGenerator.generateKey();
+    }
+
     /**
      * Generate a random asymmetric key pair.
      * 
@@ -476,6 +505,32 @@ public final class KeySupport {
         return keyGenerator.generateKeyPair();
     }
 
+    /**
+     * Generate a random asymmetric key pair.
+     * 
+     * @param algo key algorithm
+     * @param paramSpec the algorithm parameter specification
+     * @param provider JCA provider
+     * @return randomly generated key
+     * @throws NoSuchAlgorithmException algorithm not found
+     * @throws NoSuchProviderException provider not found
+     * @throws InvalidAlgorithmParameterException invalid parameter specification
+     */
+    @Nonnull public static KeyPair generateKeyPair(@Nonnull final String algo,
+            @Nonnull final AlgorithmParameterSpec paramSpec, @Nullable final String provider)
+                    throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
+        Constraint.isNotNull(algo, "Key algorithm cannot be null");
+        
+        KeyPairGenerator keyGenerator = null;
+        if (provider != null) {
+            keyGenerator = KeyPairGenerator.getInstance(algo, provider);
+        } else {
+            keyGenerator = KeyPairGenerator.getInstance(algo);
+        }
+        keyGenerator.initialize(paramSpec);
+        return keyGenerator.generateKeyPair();
+    }
+    
     /**
      * Compare the supplied public and private keys, and determine if they correspond to the same key pair.
      * 
diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/crypto/ec/ECSupport.java b/opensaml-security-api/src/main/java/org/opensaml/security/crypto/ec/ECSupport.java
new file mode 100644
index 000000000..d1ed7a34a
--- /dev/null
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/crypto/ec/ECSupport.java
@@ -0,0 +1,90 @@
+/*
+ * 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 org.opensaml.security.crypto.ec;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.crypto.KeyAgreement;
+
+import org.opensaml.security.crypto.JCAConstants;
+import org.opensaml.security.crypto.KeySupport;
+
+/**
+ * Cryptography support related to Elliptic Curve.
+ */
+public final class ECSupport {
+    
+    /** Constructor. */
+    private ECSupport() { }
+    
+    /**
+     * Perform ECDH key agreement between the given originator and recipient keys.
+     * 
+     * @param recipientKey the recipient's public key
+     * @param originatorKey the originator's private key
+     * @param provider the optional security provider to use
+     * 
+     * @return the secret produced by key agreement
+     * 
+     * @throws NoSuchAlgorithmException
+     * @throws NoSuchProviderException
+     * @throws InvalidKeyException
+     */
+    public static byte[] performKeyAgreement(@Nonnull final ECPublicKey recipientKey,
+            @Nonnull final ECPrivateKey originatorKey, @Nullable final String provider)
+                    throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
+        
+        KeyAgreement keyAgreement = null;
+        if (provider != null) {
+            keyAgreement = KeyAgreement.getInstance(JCAConstants.KEY_AGREEMENT_ECDH, provider);
+        } else {
+            keyAgreement = KeyAgreement.getInstance(JCAConstants.KEY_AGREEMENT_ECDH);
+        }
+        
+        keyAgreement.init(originatorKey);
+        keyAgreement.doPhase(recipientKey, true);
+        return keyAgreement.generateSecret();
+    }
+
+    /**
+     * Generate a key pair whose parameters are compatible with those of the specified EC public key.
+     * 
+     * @param publicKey the public key
+     * @param provider the optional security provider to use
+     * 
+     * @return the generated key pair
+     * 
+     * @throws NoSuchAlgorithmException
+     * @throws NoSuchProviderException
+     * @throws InvalidAlgorithmParameterException
+     */
+    public static KeyPair generateCompatibleKeyPair(@Nonnull final ECPublicKey publicKey,
+            @Nullable final String provider)
+                    throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
+        return KeySupport.generateKeyPair(JCAConstants.KEY_ALGO_EC, publicKey.getParams(), provider);
+    }
+    
+}
diff --git a/opensaml-security-api/src/test/java/org/opensaml/security/crypto/ec/ECSupportTest.java b/opensaml-security-api/src/test/java/org/opensaml/security/crypto/ec/ECSupportTest.java
new file mode 100644
index 000000000..ca0d6c5a0
--- /dev/null
+++ b/opensaml-security-api/src/test/java/org/opensaml/security/crypto/ec/ECSupportTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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 org.opensaml.security.crypto.ec;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECGenParameterSpec;
+
+import org.opensaml.security.crypto.JCAConstants;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class ECSupportTest {
+    
+    @DataProvider
+    public Object[][] namedCurves() {
+        return new Object[][] {
+            new Object[] {"secp256r1"},
+            new Object[] {"secp384r1"},
+            new Object[] {"secp521r1"},
+        };
+    }
+    
+    @Test(dataProvider="namedCurves")
+    public void generateCompatibleKeyPair(String namedCurve) throws Exception {
+        final KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance(JCAConstants.KEY_ALGO_EC);
+        kpGenerator.initialize(new ECGenParameterSpec(namedCurve));
+        final KeyPair origKeyPair = kpGenerator.generateKeyPair();
+        Assert.assertNotNull(origKeyPair);
+        Assert.assertTrue(ECPublicKey.class.isInstance(origKeyPair.getPublic()));
+        ECPublicKey origPublicKey = ECPublicKey.class.cast(origKeyPair.getPublic());
+        
+        final KeyPair generatedKeyPair = ECSupport.generateCompatibleKeyPair(origPublicKey, null);
+        
+        Assert.assertNotNull(generatedKeyPair);
+        Assert.assertTrue(ECPublicKey.class.isInstance(generatedKeyPair.getPublic()));
+        Assert.assertTrue(ECPrivateKey.class.isInstance(generatedKeyPair.getPrivate()));
+    }
+    
+    @Test(dataProvider="namedCurves")
+    public void performKeyAgreement(String namedCurve) throws Exception {
+        final KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance(JCAConstants.KEY_ALGO_EC);
+        kpGenerator.initialize(new ECGenParameterSpec(namedCurve));
+        final KeyPair recipientKeyPair = kpGenerator.generateKeyPair();
+        ECPublicKey recipientPublicKey = ECPublicKey.class.cast(recipientKeyPair.getPublic());
+        
+        final KeyPair originatorKeyPair = ECSupport.generateCompatibleKeyPair(recipientPublicKey, null);
+        final ECPrivateKey originatorPrivateKey = ECPrivateKey.class.cast(originatorKeyPair.getPrivate());
+        
+        byte[] secret = ECSupport.performKeyAgreement(recipientPublicKey, originatorPrivateKey, null);
+        Assert.assertNotNull(secret);
+    }
+
+}

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


More information about the commits mailing list