Skip to content

Commit 31d9bdc

Browse files
committed
Remove reflective calls to security getInstance(algorithm) methods
Simplify this setup a little. We always know what kind of security entity we want to create, so there is no need for some convoluted reflective way to create factories.
1 parent 04fe313 commit 31d9bdc

5 files changed

Lines changed: 291 additions & 231 deletions

File tree

sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java

Lines changed: 200 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -19,169 +19,218 @@
1919

2020
package org.apache.sshd.common.util.security;
2121

22-
import java.lang.reflect.Method;
2322
import java.security.GeneralSecurityException;
23+
import java.security.KeyFactory;
24+
import java.security.KeyPairGenerator;
25+
import java.security.MessageDigest;
26+
import java.security.NoSuchAlgorithmException;
2427
import java.security.Provider;
25-
import java.util.Objects;
28+
import java.security.SecureRandom;
29+
import java.security.Signature;
30+
import java.security.cert.CertificateFactory;
31+
32+
import javax.crypto.Cipher;
33+
import javax.crypto.KeyAgreement;
34+
import javax.crypto.Mac;
2635

27-
import org.apache.sshd.common.util.ExceptionUtils;
2836
import org.apache.sshd.common.util.ValidateUtils;
2937

3038
/**
31-
* @param <T> Type of security entity being generated by this factory
32-
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
39+
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
3340
*/
34-
public interface SecurityEntityFactory<T> {
35-
Class<T> getEntityType();
36-
37-
T getInstance(String algorithm) throws GeneralSecurityException;
38-
39-
/**
40-
* Uses reflection in order to wrap the {@code getInstance} method(s) as a security entity factory.
41-
*
42-
* @param <F> Type of entity being generated by the factor
43-
* @param entityType The entity type class
44-
* @param registrar The {@code SecurityProviderRegistrar} to use - if {@code null} then default
45-
* provider is used (if specified).
46-
* @param defaultProvider Default provider choice to use if no registrar provided. If
47-
* {@code null}/empty then JCE default is used
48-
* @return The {@link SecurityEntityFactory} for the entity
49-
* @throws ReflectiveOperationException If failed to create the factory
50-
* @see #toDefaultFactory(Class)
51-
* @see #toNamedProviderFactory(Class, String)
52-
* @see #toProviderInstanceFactory(Class, Provider)
53-
* @see SecurityProviderChoice#isNamedProviderUsed()
54-
* @see SecurityProviderChoice#getSecurityProvider()
55-
*/
56-
static <F> SecurityEntityFactory<F> toFactory(
57-
Class<F> entityType, SecurityProviderChoice registrar, SecurityProviderChoice defaultProvider)
58-
throws ReflectiveOperationException {
59-
if (registrar == null) {
60-
if ((defaultProvider == null) || (defaultProvider == SecurityProviderChoice.EMPTY)) {
61-
return toDefaultFactory(entityType);
62-
}
63-
return defaultProvider.getFactory(entityType);
64-
}
65-
return registrar.getFactory(entityType);
41+
public interface SecurityEntityFactory {
42+
43+
default CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
44+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
45+
}
46+
47+
default Cipher createCipher(String algorithm) throws GeneralSecurityException {
48+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
49+
}
50+
51+
default KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
52+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
53+
}
54+
55+
default KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
56+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
57+
}
58+
59+
default KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
60+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
6661
}
6762

68-
static <F> SecurityEntityFactory<F> toDefaultFactory(Class<F> entityType)
69-
throws ReflectiveOperationException {
70-
Method m = entityType.getDeclaredMethod("getInstance", String.class);
71-
return new SecurityEntityFactory<F>() {
72-
private final String s = SecurityEntityFactory.class.getSimpleName()
73-
+ "[" + entityType.getSimpleName() + "]"
74-
+ "[default]";
75-
76-
@Override
77-
public Class<F> getEntityType() {
78-
return entityType;
79-
}
80-
81-
@Override
82-
public F getInstance(String algorithm) throws GeneralSecurityException {
83-
try {
84-
Object value = m.invoke(null, algorithm);
85-
return entityType.cast(value);
86-
} catch (ReflectiveOperationException t) {
87-
Throwable e = ExceptionUtils.peelException(t);
88-
if (e instanceof GeneralSecurityException) {
89-
throw (GeneralSecurityException) e;
90-
} else if (e instanceof RuntimeException) {
91-
throw (RuntimeException) e;
92-
} else if (e instanceof Error) {
93-
throw (Error) e;
94-
} else {
95-
throw new GeneralSecurityException(e);
96-
}
97-
}
98-
}
99-
100-
@Override
101-
public String toString() {
102-
return s;
103-
}
104-
};
63+
default Mac createMac(String algorithm) throws GeneralSecurityException {
64+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
10565
}
10666

107-
static <F> SecurityEntityFactory<F> toNamedProviderFactory(Class<F> entityType, String name)
108-
throws ReflectiveOperationException {
109-
ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified");
110-
Method m = entityType.getDeclaredMethod("getInstance", String.class, String.class);
111-
return new SecurityEntityFactory<F>() {
112-
private final String s = SecurityEntityFactory.class.getSimpleName()
113-
+ "[" + entityType.getSimpleName() + "]"
114-
+ "[" + name + "]";
115-
116-
@Override
117-
public Class<F> getEntityType() {
118-
return entityType;
119-
}
120-
121-
@Override
122-
public F getInstance(String algorithm) throws GeneralSecurityException {
123-
try {
124-
Object value = m.invoke(null, algorithm, name);
125-
return entityType.cast(value);
126-
} catch (ReflectiveOperationException t) {
127-
Throwable e = ExceptionUtils.peelException(t);
128-
if (e instanceof GeneralSecurityException) {
129-
throw (GeneralSecurityException) e;
130-
} else if (e instanceof RuntimeException) {
131-
throw (RuntimeException) e;
132-
} else if (e instanceof Error) {
133-
throw (Error) e;
134-
} else {
135-
throw new GeneralSecurityException(e);
136-
}
137-
}
138-
}
139-
140-
@Override
141-
public String toString() {
142-
return s;
143-
}
144-
};
67+
default MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
68+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
69+
}
70+
71+
default Signature createSignature(String algorithm) throws GeneralSecurityException {
72+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
73+
}
74+
75+
default SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
76+
throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
77+
}
78+
79+
class Named implements SecurityEntityFactory {
80+
81+
private final String name;
82+
83+
public Named(String name) {
84+
this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "Security provider name must not be empty");
85+
}
86+
87+
@Override
88+
public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
89+
return CertificateFactory.getInstance(algorithm, name);
90+
}
91+
92+
@Override
93+
public Cipher createCipher(String algorithm) throws GeneralSecurityException {
94+
return Cipher.getInstance(algorithm, name);
95+
}
96+
97+
@Override
98+
public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
99+
return KeyAgreement.getInstance(algorithm, name);
100+
}
101+
102+
@Override
103+
public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
104+
return KeyFactory.getInstance(algorithm, name);
105+
}
106+
107+
@Override
108+
public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
109+
return KeyPairGenerator.getInstance(algorithm, name);
110+
}
111+
112+
@Override
113+
public Mac createMac(String algorithm) throws GeneralSecurityException {
114+
return Mac.getInstance(algorithm, name);
115+
}
116+
117+
@Override
118+
public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
119+
return MessageDigest.getInstance(algorithm, name);
120+
}
121+
122+
@Override
123+
public Signature createSignature(String algorithm) throws GeneralSecurityException {
124+
return Signature.getInstance(algorithm, name);
125+
}
126+
127+
@Override
128+
public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
129+
return SecureRandom.getInstance(algorithm, name);
130+
}
145131
}
146132

147-
static <F> SecurityEntityFactory<F> toProviderInstanceFactory(Class<F> entityType, Provider provider)
148-
throws ReflectiveOperationException {
149-
Objects.requireNonNull(provider, "No provider instance");
150-
Method m = entityType.getDeclaredMethod("getInstance", String.class, Provider.class);
151-
return new SecurityEntityFactory<F>() {
152-
private final String s = SecurityEntityFactory.class.getSimpleName()
153-
+ "[" + entityType.getSimpleName() + "]"
154-
+ "[" + Provider.class.getSimpleName() + "]"
155-
+ "[" + provider.getName() + "]";
156-
157-
@Override
158-
public Class<F> getEntityType() {
159-
return entityType;
160-
}
161-
162-
@Override
163-
public F getInstance(String algorithm) throws GeneralSecurityException {
164-
try {
165-
Object value = m.invoke(null, algorithm, provider);
166-
return entityType.cast(value);
167-
} catch (ReflectiveOperationException t) {
168-
Throwable e = ExceptionUtils.peelException(t);
169-
if (e instanceof GeneralSecurityException) {
170-
throw (GeneralSecurityException) e;
171-
} else if (e instanceof RuntimeException) {
172-
throw (RuntimeException) e;
173-
} else if (e instanceof Error) {
174-
throw (Error) e;
175-
} else {
176-
throw new GeneralSecurityException(e);
177-
}
178-
}
179-
}
180-
181-
@Override
182-
public String toString() {
183-
return s;
184-
}
185-
};
133+
class ByProvider implements SecurityEntityFactory {
134+
135+
private final Provider provider;
136+
137+
public ByProvider(Provider name) {
138+
this.provider = ValidateUtils.checkNotNull(name, "Security provider must not be null");
139+
}
140+
141+
@Override
142+
public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
143+
return CertificateFactory.getInstance(algorithm, provider);
144+
}
145+
146+
@Override
147+
public Cipher createCipher(String algorithm) throws GeneralSecurityException {
148+
return Cipher.getInstance(algorithm, provider);
149+
}
150+
151+
@Override
152+
public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
153+
return KeyAgreement.getInstance(algorithm, provider);
154+
}
155+
156+
@Override
157+
public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
158+
return KeyFactory.getInstance(algorithm, provider);
159+
}
160+
161+
@Override
162+
public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
163+
return KeyPairGenerator.getInstance(algorithm, provider);
164+
}
165+
166+
@Override
167+
public Mac createMac(String algorithm) throws GeneralSecurityException {
168+
return Mac.getInstance(algorithm, provider);
169+
}
170+
171+
@Override
172+
public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
173+
return MessageDigest.getInstance(algorithm, provider);
174+
}
175+
176+
@Override
177+
public Signature createSignature(String algorithm) throws GeneralSecurityException {
178+
return Signature.getInstance(algorithm, provider);
179+
}
180+
181+
@Override
182+
public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
183+
return SecureRandom.getInstance(algorithm, provider);
184+
}
185+
}
186+
187+
enum Default implements SecurityEntityFactory {
188+
189+
INSTANCE;
190+
191+
@Override
192+
public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
193+
return CertificateFactory.getInstance(algorithm);
194+
}
195+
196+
@Override
197+
public Cipher createCipher(String algorithm) throws GeneralSecurityException {
198+
return Cipher.getInstance(algorithm);
199+
}
200+
201+
@Override
202+
public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
203+
return KeyAgreement.getInstance(algorithm);
204+
}
205+
206+
@Override
207+
public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
208+
return KeyFactory.getInstance(algorithm);
209+
}
210+
211+
@Override
212+
public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
213+
return KeyPairGenerator.getInstance(algorithm);
214+
}
215+
216+
@Override
217+
public Mac createMac(String algorithm) throws GeneralSecurityException {
218+
return Mac.getInstance(algorithm);
219+
}
220+
221+
@Override
222+
public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
223+
return MessageDigest.getInstance(algorithm);
224+
}
225+
226+
@Override
227+
public Signature createSignature(String algorithm) throws GeneralSecurityException {
228+
return Signature.getInstance(algorithm);
229+
}
230+
231+
@Override
232+
public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
233+
return SecureRandom.getInstance(algorithm);
234+
}
186235
}
187236
}

sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ default String getProviderName() {
7171
return getName();
7272
}
7373

74-
default <F> SecurityEntityFactory<F> getFactory(Class<F> entityType) throws ReflectiveOperationException {
74+
default SecurityEntityFactory getFactory() {
7575
if (isNamedProviderUsed()) {
76-
return SecurityEntityFactory.toNamedProviderFactory(entityType, getProviderName());
76+
return new SecurityEntityFactory.Named(getProviderName());
7777
}
78-
return SecurityEntityFactory.toProviderInstanceFactory(entityType, getSecurityProvider());
78+
return new SecurityEntityFactory.ByProvider(getSecurityProvider());
7979
}
8080

8181
/**

0 commit comments

Comments
 (0)