2222import jakarta .xml .bind .JAXBException ;
2323import jakarta .xml .bind .Unmarshaller ;
2424
25+ import java .security .AccessController ;
2526import java .security .NoSuchAlgorithmException ;
27+ import java .security .PrivilegedAction ;
2628import java .security .SecureRandom ;
2729
2830import javax .xml .datatype .DatatypeConfigurationException ;
@@ -43,19 +45,13 @@ public class XMLSecurityConstants {
4345 public static final XMLOutputFactory xmlOutputFactory ;
4446 public static final XMLOutputFactory xmlOutputFactoryNonRepairingNs ;
4547
46- private static final SecureRandom SECURE_RANDOM ;
48+ private static volatile SecureRandom SECURE_RANDOM ;
49+ private static final Object SECURE_RANDOM_LOCK = new Object ();
4750 private static final String RANDOM_ALGORITHM_KEY = "org.apache.xml.security.securerandom.algorithm" ;
4851 private static JAXBContext jaxbContext ;
4952 private static Schema schema ;
5053
5154 static {
52- try {
53- String PrngAlgorithm = System .getProperty (RANDOM_ALGORITHM_KEY );
54- SECURE_RANDOM = PrngAlgorithm != null ? SecureRandom .getInstance (PrngAlgorithm ) : new SecureRandom ();
55- } catch (NoSuchAlgorithmException e ) {
56- throw new RuntimeException (e );
57- }
58-
5955 try {
6056 datatypeFactory = DatatypeFactory .newInstance ();
6157 } catch (DatatypeConfigurationException e ) {
@@ -73,17 +69,36 @@ protected XMLSecurityConstants() {
7369 }
7470
7571 /**
76- * Generate bytes of the given length using the supplied algorithm in RANDOM_ALGORITHM_KEY or,
77- * if not specified, use SecureRandom instance from default constructor. The SecureRandom
72+ * Generate bytes of the given length using the algorithm supplied in {@value # RANDOM_ALGORITHM_KEY} or,
73+ * if not specified, use a {@code SecureRandom} instance from default constructor. The {@code SecureRandom}
7874 * instance that backs this method is cached for efficiency.
7975 *
80- * @return a byte array of the given length
76+ * @return a new byte array of the given length
8177 * @throws XMLSecurityException
8278 */
8379 public static byte [] generateBytes (int length ) throws XMLSecurityException {
80+
81+ SecureRandom rnd = SECURE_RANDOM ;
82+ if (rnd == null ) {
83+ synchronized (SECURE_RANDOM_LOCK ) {
84+ rnd = SECURE_RANDOM ;
85+ if (rnd == null ) {
86+ try {
87+ final String prngAlgorithm = AccessController .doPrivileged (
88+ (PrivilegedAction <String >) () -> System .getProperty (RANDOM_ALGORITHM_KEY ));
89+ SECURE_RANDOM = rnd = prngAlgorithm != null
90+ ? SecureRandom .getInstance (prngAlgorithm )
91+ : new SecureRandom ();
92+ } catch (NoSuchAlgorithmException e ) {
93+ throw new RuntimeException (e );
94+ }
95+ }
96+ }
97+ }
98+
8499 try {
85100 byte [] temp = new byte [length ];
86- SECURE_RANDOM .nextBytes (temp );
101+ rnd .nextBytes (temp );
87102 return temp ;
88103 } catch (Exception ex ) {
89104 throw new XMLSecurityException (ex );
0 commit comments