[java-shib-shared] branch main updated: JSSH-9 - Rework IdentifierGenerationStrategy usage

Scott Cantor cantor.2 at osu.edu
Thu Oct 13 16:09:16 UTC 2022


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

scantor pushed a commit to branch main
in repository java-shib-shared.

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

The following commit(s) were added to refs/heads/main by this push:
     new a4f529ce JSSH-9 - Rework IdentifierGenerationStrategy usage
a4f529ce is described below

commit a4f529cefc9bc709ce6b0f89e93ed5b2528bdd8f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Oct 13 12:09:13 2022 -0400

    JSSH-9 - Rework IdentifierGenerationStrategy usage
    
    https://shibboleth.atlassian.net/browse/JSSH-9
---
 .../security/IdentifierGenerationStrategy.java     |  90 ++++++++++++++++
 .../security/RandomIdentifierParameterSpec.java    |  43 ++++++++
 .../FixedStringIdentifierGenerationStrategy.java   |  56 ----------
 .../impl/RandomIdentifierGenerationStrategy.java   |  72 +++++++------
 .../SecureRandomIdentifierGenerationStrategy.java  |  44 ++++----
 .../Type4UUIDIdentifierGenerationStrategy.java     |  21 ++++
 ...ixedStringIdentifierGenerationStrategyTest.java |  22 ----
 .../RandomIdentifierGenerationStrategyTest.java    | 117 +++++++++++++++++----
 ...cureRandomIdentifierGenerationStrategyTest.java |  18 +++-
 9 files changed, 330 insertions(+), 153 deletions(-)

diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/IdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/IdentifierGenerationStrategy.java
index 46ae6992..061ad47d 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/IdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/IdentifierGenerationStrategy.java
@@ -17,14 +17,22 @@
 
 package net.shibboleth.shared.security;
 
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
 
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.security.impl.RandomIdentifierGenerationStrategy;
+import net.shibboleth.shared.security.impl.SecureRandomIdentifierGenerationStrategy;
+import net.shibboleth.shared.security.impl.Type4UUIDIdentifierGenerationStrategy;
 
 /**
  * Interface for identifier generators. This identifier can be used for things like digital signature identifiers,
  * opaque principal identifiers, etc.
  */
+ at ThreadSafe
 public interface IdentifierGenerationStrategy {
 
     /**
@@ -41,4 +49,86 @@ public interface IdentifierGenerationStrategy {
      * @return the identifier
      */
     @Nonnull @NotEmpty public String generateIdentifier(boolean xmlSafe);
+    
+    /**
+     * Enum of supported provider types.
+     * 
+     * @since 9.0.0
+     */
+    public enum ProviderType {
+        
+        /** Produces random identifiers that may not be strongly secure. */
+        RANDOM,
+        
+        /** Produces random identifiers that rely on a theoretically secure source of randomness. */
+        SECURE,
+        
+        /** Produces random identifiers based on type 4 UUIDs. */
+        UUID
+    }
+    
+    /**
+     * Marker interface for parameters specific to particular provider types.
+     * 
+     * @since 9.0.0
+     */
+    interface ParameterSpec {
+        
+    }
+    
+    /**
+     * Get an instance of a particular provider of identifiers with no parameters.
+     * 
+     * <p>If the type is somehow unrecognized, the {@link ProviderType#RANDOM} is used to
+     * guarantee a successful result.</p>
+     * 
+     * @param type provider type
+     * 
+     * @return identifier provider
+     * 
+     * @since 9.0.0
+     */
+    @Nonnull static IdentifierGenerationStrategy getInstance(@Nonnull final ProviderType type) {
+        switch (type) {
+            case SECURE:
+                return new SecureRandomIdentifierGenerationStrategy();
+            
+            case UUID:
+                return new Type4UUIDIdentifierGenerationStrategy();
+                
+            default:
+                return new RandomIdentifierGenerationStrategy();
+        }
+    }
+    
+    /**
+     * Get an instance of a particular provider of identifiers with parameters.
+     * 
+     * @param type provider type
+     * @param params implementation-specific parameter instance
+     * 
+     * @return identifier provider
+     * 
+     * @throws NoSuchAlgorithmException if the type is unknown
+     * @throws InvalidAlgorithmParameterException if the parameters were invalid 
+     * 
+     * @since 9.0.0
+     */
+    @Nonnull static IdentifierGenerationStrategy getInstance(@Nonnull final ProviderType type,
+            @Nonnull final ParameterSpec params) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+        switch (type) {
+            case RANDOM:
+                return new RandomIdentifierGenerationStrategy(params);
+                
+            case SECURE:
+                return new SecureRandomIdentifierGenerationStrategy(params);
+            
+            case UUID:
+                return new Type4UUIDIdentifierGenerationStrategy(params);
+                
+            default:
+                throw new NoSuchAlgorithmException("Unknown IdentifierGenerationStrategy type");
+        }
+    }
+    
 }
\ No newline at end of file
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java b/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java
new file mode 100644
index 00000000..29147a93
--- /dev/null
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java
@@ -0,0 +1,43 @@
+/*
+ * 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.shared.security;
+
+import java.security.SecureRandom;
+import java.util.random.RandomGenerator;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.codec.BinaryEncoder;
+import org.apache.commons.codec.binary.Hex;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NonNegative;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy.ParameterSpec;
+
+/**
+ * Captures the supported parameters for the {@link IdentifierGenerationStrategy.ProviderType#RANDOM}
+ * and {@link IdentifierGenerationStrategy.ProviderType#SECURE} strategy types.
+ * 
+ * @param source random generator (this MUST be thread-safe), defaults to standard Java {@link SecureRandom} 
+ * @param identifierSize size of identifiers to generate, defaults to 16
+ * @param identifierEncoder an encoder to apply to the random data, defaults to {@link Hex}
+ */
+public record RandomIdentifierParameterSpec(@Nullable @ParameterName(name="source") RandomGenerator source,
+        @Nullable @NonNegative @ParameterName(name="identifierSize") Integer identifierSize,
+        @Nullable @ParameterName(name="identifierEncoder") BinaryEncoder identifierEncoder) implements ParameterSpec {
+}
\ No newline at end of file
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategy.java
deleted file mode 100644
index 3cd22cfc..00000000
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategy.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.shared.security.impl;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.security.IdentifierGenerationStrategy;
-
-/**
- * Identifier generation strategy using a fixed identifier string.
- *
- * This can be used in circumstances where there is no requirement that identifiers be
- * different from each other.
- */
-public class FixedStringIdentifierGenerationStrategy implements IdentifierGenerationStrategy {
-
-    /** Fixed identifier to use for all invocations. */
-    @Nonnull @NotEmpty private final String identifier;
-
-    /**
-     * Constructor.
-     *
-     * @param id fixed identifier to use for all invocations.
-     */
-    public FixedStringIdentifierGenerationStrategy(@Nonnull @NotEmpty final String id) {
-        identifier = Constraint.isNotEmpty(id, "identifier cannot be null or empty");
-    }
-
-    /** {@inheritDoc} */
-    @Nonnull @NotEmpty public String generateIdentifier() {
-        return identifier;
-    }
-
-    /** {@inheritDoc} */
-    @Nonnull @NotEmpty public String generateIdentifier(final boolean xmlSafe) {
-        return identifier;
-    }
-
-}
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
index 57feb7f5..729590e1 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
@@ -17,14 +17,17 @@
 
 package net.shibboleth.shared.security.impl;
 
+import java.security.InvalidAlgorithmParameterException;
 import java.security.SecureRandom;
 import java.util.Random;
+import java.util.random.RandomGenerator;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
 
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.security.IdentifierGenerationStrategy;
+import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
 
 import org.apache.commons.codec.BinaryEncoder;
 import org.apache.commons.codec.EncoderException;
@@ -35,55 +38,64 @@ import org.apache.commons.codec.binary.StringUtils;
  * Generates a random number of bytes via a {@link Random} source and encodes them into a string using a
  * {@link BinaryEncoder} ({@link Hex} by default).
  */
+ at ThreadSafe
 public class RandomIdentifierGenerationStrategy implements IdentifierGenerationStrategy {
 
     /** Random number generator. */
-    private final Random random;
+    @Nonnull private final RandomGenerator random;
 
     /** Number of random bytes in the identifier. */
     private final int sizeOfIdentifier;
 
     /** Encoder used to convert the random bytes in to a string. */
-    private final BinaryEncoder encoder;
-
+    @Nonnull final private BinaryEncoder encoder;
+    
     /**
-     * Constructor. Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
-     * bytes, and the encoder is set to a {@link Hex}.
-     */
-    public RandomIdentifierGenerationStrategy() {
-        this(16);
-    }
-
-    /**
-     * Constructor. Initializes the random number source to a new {@link SecureRandom} and the encoder is set to a
-     * {@link Hex}.
+     * Default constructor.
      * 
-     * @param identifierSize number of random bytes in identifier
+     * <p>Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
+     * bytes, and the encoder is set to a {@link Hex}.</p>
      */
-    public RandomIdentifierGenerationStrategy(final int identifierSize) {
+    public RandomIdentifierGenerationStrategy() {
         random = new SecureRandom();
-        sizeOfIdentifier =
-                Constraint.isGreaterThan(0, identifierSize,
-                        "Number of bytes in the identifier must be greater than 0");
+        sizeOfIdentifier = 16;
         encoder = new Hex();
     }
 
     /**
      * Constructor.
      * 
-     * @param source source of random bytes
-     * @param identifierSize number of random bytes in the identifier
-     * @param identifierEncoder encoder used to convert random bytes to string identifier
+     * @param params parameter object, must be a {@link RandomIdentifierParameterSpec}
+     * 
+     * @throws InvalidAlgorithmParameterException if the parameters are invalid
      */
-    public RandomIdentifierGenerationStrategy(@Nonnull final Random source, final int identifierSize,
-            @Nonnull final BinaryEncoder identifierEncoder) {
-        random = Constraint.isNotNull(source, "Random number source can not be null");
-        sizeOfIdentifier =
-                Constraint.isGreaterThan(0, identifierSize,
-                        "Number of bytes in the identifier must be greater than 0");
-        encoder = Constraint.isNotNull(identifierEncoder, "Identifier is encoder can not be null");
-    }
+    public RandomIdentifierGenerationStrategy(@Nonnull ParameterSpec params) throws InvalidAlgorithmParameterException {
+        if (params instanceof RandomIdentifierParameterSpec spec) {
+            if (spec.source() != null) {
+                random = spec.source();
+            } else {
+                random = new SecureRandom();
+            }
 
+            if (spec.identifierSize() != null) {
+                if (spec.identifierSize() <= 0) {
+                    throw new InvalidAlgorithmParameterException("Identifier length must be greater than 0");
+                }
+                sizeOfIdentifier = spec.identifierSize();
+            } else {
+                sizeOfIdentifier = 16;
+            }
+            
+            if (spec.identifierEncoder() != null) {
+                encoder = spec.identifierEncoder();
+            } else {
+                encoder = new Hex();
+            }
+        } else {
+            throw new InvalidAlgorithmParameterException("Invalid or unrecognized RandomParameterSpec");
+        }
+    }
+    
     /** {@inheritDoc} */
     @Nonnull @NotEmpty public String generateIdentifier() {
         return generateIdentifier(true);
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
index d9b9163f..1f862e59 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
@@ -17,49 +17,49 @@
 
 package net.shibboleth.shared.security.impl;
 
+import java.security.InvalidAlgorithmParameterException;
 import java.security.SecureRandom;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
 
-import org.apache.commons.codec.BinaryEncoder;
+import org.apache.commons.codec.binary.Hex;
 
-import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
 
 /**
  * A specialized subclass of {@link RandomIdentifierGenerationStrategy} which constrains the supplied
  * random number generator to be an instance of {@link SecureRandom}.
  */
+ at ThreadSafe
 public class SecureRandomIdentifierGenerationStrategy extends RandomIdentifierGenerationStrategy {
 
     /**
-     * Constructor. Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
-     * bytes, and the encoder is set to a {@link org.apache.commons.codec.binary.Hex}.
+     * Default constructor.
+     * 
+     * <p>Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
+     * bytes, and the encoder is set to a {@link Hex}.</p>
      */
     public SecureRandomIdentifierGenerationStrategy() {
         
     }
 
-    /**
-     * Constructor. Initializes the random number source to a new {@link SecureRandom} and the encoder is set to a
-     * {@link org.apache.commons.codec.binary.Hex}.
-     * 
-     * @param identifierSize number of random bytes in identifier
-     */
-    public SecureRandomIdentifierGenerationStrategy(@ParameterName(name="identifierSize") final int identifierSize) {
-        super(identifierSize);
-    }
-
     /**
      * Constructor.
      * 
-     * @param source source of random bytes
-     * @param identifierSize number of random bytes in the identifier
-     * @param identifierEncoder encoder used to convert random bytes to string identifier
+     * @param params parameter object, must be a {@link RandomIdentifierParameterSpec}
+     * 
+     * @throws InvalidAlgorithmParameterException if the parameters are invalid
      */
-    public SecureRandomIdentifierGenerationStrategy(@ParameterName(name="source") @Nonnull final SecureRandom source, 
-            @ParameterName(name="identifierSize") final int identifierSize,
-            @ParameterName(name="identifierEncoder") @Nonnull final BinaryEncoder identifierEncoder) {
-        super(source, identifierSize, identifierEncoder);
+    public SecureRandomIdentifierGenerationStrategy(@Nonnull ParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        super(params);
+        
+        if (((RandomIdentifierParameterSpec) params).source() != null) {
+            if (!(((RandomIdentifierParameterSpec) params).source() instanceof SecureRandom)) {
+                throw new InvalidAlgorithmParameterException("Random source was not an instance of SecureRandom");
+            }
+        }
     }
 
-}
+}
\ No newline at end of file
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/Type4UUIDIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/Type4UUIDIdentifierGenerationStrategy.java
index d2e9ad3c..d66e8be9 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/Type4UUIDIdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/Type4UUIDIdentifierGenerationStrategy.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.shared.security.impl;
 
+import java.security.InvalidAlgorithmParameterException;
 import java.util.UUID;
 
 import javax.annotation.Nonnull;
@@ -29,6 +30,25 @@ import net.shibboleth.shared.security.IdentifierGenerationStrategy;
 @ThreadSafe
 public class Type4UUIDIdentifierGenerationStrategy implements IdentifierGenerationStrategy {
 
+    /** Default constructor. */
+    public Type4UUIDIdentifierGenerationStrategy() {
+        
+    }
+
+    /**
+     * Constructor.
+     * 
+     * <p>It is invalid to supply any parameters to this method.</p>
+     *
+     * @param params must be null
+     * 
+     * @throws InvalidAlgorithmParameterException if the parameters are non-null
+     */
+    public Type4UUIDIdentifierGenerationStrategy(@Nonnull final IdentifierGenerationStrategy.ParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        throw new InvalidAlgorithmParameterException("Type4UUIDIdentifierGenerationStrategy does not support parameters");
+    }
+
     /** {@inheritDoc} */
     @Nonnull @NotEmpty public String generateIdentifier() {
         return generateIdentifier(true);
@@ -41,4 +61,5 @@ public class Type4UUIDIdentifierGenerationStrategy implements IdentifierGenerati
         }
         return UUID.randomUUID().toString();
     }
+    
 }
\ No newline at end of file
diff --git a/shib-security/src/test/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategyTest.java b/shib-security/src/test/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategyTest.java
deleted file mode 100644
index 8b5e7f49..00000000
--- a/shib-security/src/test/java/net/shibboleth/shared/security/impl/FixedStringIdentifierGenerationStrategyTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-
-package net.shibboleth.shared.security.impl;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class FixedStringIdentifierGenerationStrategyTest {
-
-    @Test
-    public void generateIdentifier() {
-        final FixedStringIdentifierGenerationStrategy f = new FixedStringIdentifierGenerationStrategy("aaa");
-        Assert.assertEquals(f.generateIdentifier(), "aaa");
-        Assert.assertEquals(f.generateIdentifier(), "aaa");
-    }
-
-    @Test
-    public void generateIdentifierboolean() {
-        final FixedStringIdentifierGenerationStrategy f = new FixedStringIdentifierGenerationStrategy("bbb");
-        Assert.assertEquals(f.generateIdentifier(true), "bbb");
-        Assert.assertEquals(f.generateIdentifier(false), "bbb");
-    }
-}
diff --git a/shib-security/src/test/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategyTest.java b/shib-security/src/test/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategyTest.java
index ed5ca8bc..8264d995 100644
--- a/shib-security/src/test/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategyTest.java
+++ b/shib-security/src/test/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategyTest.java
@@ -17,16 +17,96 @@
 
 package net.shibboleth.shared.security.impl;
 
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.random.RandomGenerator;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import net.shibboleth.shared.security.IdentifierGenerationStrategy;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy.ParameterSpec;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy.ProviderType;
+import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
+
 /** Unit test for {@link RandomIdentifierGenerationStrategy}. */
 public class RandomIdentifierGenerationStrategyTest {
+    
+    /**
+     * Test default construction.
+     * 
+     * @throws NoSuchAlgorithmException 
+     * @throws InvalidAlgorithmParameterException
+     */
+    @Test
+    public void testDefaultInstantiation() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+        IdentifierGenerationStrategy strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM);
+        String id = strat.generateIdentifier(false);
+        Assert.assertEquals(id.length(), 32);
+        
+        final RandomIdentifierParameterSpec spec = new RandomIdentifierParameterSpec(null, null, null);
+        strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM, spec);
+        id = strat.generateIdentifier(false);
+        Assert.assertEquals(id.length(), 32);
+    }
+
+    /**
+     * Test construction with specific source.
+     * 
+     * @throws NoSuchAlgorithmException 
+     * @throws InvalidAlgorithmParameterException
+     */
+    @Test
+    public void testSource() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+        
+        final RandomGenerator myRandom = new RandomGenerator() {
+            public long nextLong() {
+                return 0xAAAAAAAAAAAAAAAAL;
+            }
+        };
+        
+        final RandomIdentifierParameterSpec spec = new RandomIdentifierParameterSpec(myRandom, null, null);
+        final IdentifierGenerationStrategy strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM, spec);
+        final String id = strat.generateIdentifier(false);
+        Assert.assertEquals(id, "a".repeat(32));
+    }
+
+    /**
+     * Test construction with specific source and length.
+     * 
+     * @throws NoSuchAlgorithmException 
+     * @throws InvalidAlgorithmParameterException
+     */
+    @Test
+    public void testSourceAndLength() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+        
+        final RandomGenerator myRandom = new RandomGenerator() {
+            public long nextLong() {
+                return 0xAAAAAAAAAAAAAAAAL;
+            }
+        };
+        
+        final RandomIdentifierParameterSpec spec = new RandomIdentifierParameterSpec(myRandom, 8, null);
+        final IdentifierGenerationStrategy strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM, spec);
+        final String id = strat.generateIdentifier(false);
+        Assert.assertEquals(id, "a".repeat(16));
+    }
+
+    /**
+     * Test construction with invalid parameter spec type.
+     * 
+     * @throws NoSuchAlgorithmException 
+     * @throws InvalidAlgorithmParameterException
+     */
+    @Test(expectedExceptions=InvalidAlgorithmParameterException.class)
+    public void testInvalidParams() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
+        
+        IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM, new ParameterSpec(){});
+    }
 
     /**
      * Test generateIdentifier by generating a large number of identifiers
@@ -35,24 +115,25 @@ public class RandomIdentifierGenerationStrategyTest {
      */
     @Test
     public void testGenerateIdentifier() {
-      final Pattern ncNamePattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_\\-\\.]+$");
-      final RandomIdentifierGenerationStrategy strat = new RandomIdentifierGenerationStrategy();
-      final int howMany = 1000;
-      final Set<String> values = new HashSet<>(1000);
-      for (int iteration = 1; iteration<=howMany; iteration++) {
-          final String value = strat.generateIdentifier();
+        final Pattern ncNamePattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_\\-\\.]+$");
+        final IdentifierGenerationStrategy strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM);
+        final int howMany = 1000;
+        final Set<String> values = new HashSet<>(1000);
+        for (int iteration = 1; iteration<=howMany; iteration++) {
+            final String value = strat.generateIdentifier();
           
-          // we shouldn't see the same value twice
-          if (values.contains(value)) {
+            // we shouldn't see the same value twice
+            if (values.contains(value)) {
               Assert.fail("duplicate value " + value + " on iteration " + iteration);
-          }
-          values.add(value);
+            }
+            values.add(value);
           
-          // values should be valid NCNames
-          final Matcher match = ncNamePattern.matcher(value);
-          if (!match.matches()) {
-              Assert.fail("value " + value + " is not a valid NCName on iteration " + iteration);
-          }
-      }
-  }
-}
+            // values should be valid NCNames
+            final Matcher match = ncNamePattern.matcher(value);
+            if (!match.matches()) {
+                Assert.fail("value " + value + " is not a valid NCName on iteration " + iteration);   
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java b/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
index bfdbe019..9b0186e1 100644
--- a/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
+++ b/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
@@ -18,6 +18,7 @@
 
 package net.shibboleth.shared.security.impl;
 
+import java.security.InvalidAlgorithmParameterException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.util.HashSet;
@@ -29,6 +30,10 @@ import org.apache.commons.codec.binary.Hex;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import net.shibboleth.shared.security.IdentifierGenerationStrategy;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy.ProviderType;
+import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
+
 /** Unit test for {@link SecureRandomIdentifierGenerationStrategy}. */
 public class SecureRandomIdentifierGenerationStrategyTest {
 
@@ -38,7 +43,7 @@ public class SecureRandomIdentifierGenerationStrategyTest {
      */
     @Test public void testGenerateIdentifier() {
         final Pattern ncNamePattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_\\-\\.]+$");
-        final SecureRandomIdentifierGenerationStrategy strat = new SecureRandomIdentifierGenerationStrategy();
+        final IdentifierGenerationStrategy strat = IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM);
         final int howMany = 1000;
         final Set<String> values = new HashSet<>(1000);
         for (int iteration = 1; iteration <= howMany; iteration++) {
@@ -63,11 +68,13 @@ public class SecureRandomIdentifierGenerationStrategyTest {
      * ID, and that they are all different.
      * 
      * @throws NoSuchAlgorithmException if the SHA1PRNG algorithm is not available
+     * @throws InvalidAlgorithmParameterException 
      */
-    @Test public void testConstructorWithSecureRandom() throws NoSuchAlgorithmException {
+    @Test public void testConstructorWithSecureRandom() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
         final Pattern ncNamePattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_\\-\\.]+$");
-        final SecureRandomIdentifierGenerationStrategy strat =
-                new SecureRandomIdentifierGenerationStrategy(SecureRandom.getInstance("SHA1PRNG"), 16, new Hex());
+        final IdentifierGenerationStrategy strat =
+                IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM,
+                        new RandomIdentifierParameterSpec(SecureRandom.getInstance("SHA1PRNG"), 16, new Hex()));
         final int howMany = 1000;
         final Set<String> values = new HashSet<>(1000);
         for (int iteration = 1; iteration <= howMany; iteration++) {
@@ -86,4 +93,5 @@ public class SecureRandomIdentifierGenerationStrategyTest {
             }
         }
     }
-}
+
+}
\ No newline at end of file

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


More information about the commits mailing list