fast-rsa-engine 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2ed544a9d28bd7365fdcbd7c50f2cb63fb392e2
4
- data.tar.gz: cfb32076a0af898feff65321293ab3d060e4caae
3
+ metadata.gz: c32af2a6b806c2fe21ff6e5d3e03dcc619cb9f67
4
+ data.tar.gz: 9ae54f9430e6af503e118c559c9e73162e85244f
5
5
  SHA512:
6
- metadata.gz: 8c8e2bf005a8e87adc68a92c08fb8c20eed6f090d86543e85a20c140d1d45c0c2f6a6520d43550304b4149b31fd739fce0a8efe6f605a69f36ea64d7a17e50f7
7
- data.tar.gz: 0e09174832e23b1a369b64e6babf1323ea1dee83d69848a4ff254822036b3870ac4e7a5a6ebaca881d866acaf866790c4deaf9238d8d9dc5541190aa1d2f5cb8
6
+ metadata.gz: 34aa3287105f83c29a4cac01a2b1b87cebf83b082ff7a8acbac1d3fc13d1621b56cf5fb426b82c584f850a5e0f9d858535b382d1e9d8685c3a0460973ff8dca4
7
+ data.tar.gz: a777404a39c025b20d357527382b8714df3e325eaedd0739375aa82d98abc155eba480a3a40c2c4060a2bb2dd0fd56cde4d8269d87c1ad74ba1ee03e3da442f9
data/.travis.yml CHANGED
@@ -1,9 +1,5 @@
1
1
  language: ruby
2
2
  install: gem install bundler -v '~>1.10'; bundle install
3
- gemfile:
4
- - Gemfile
5
- - Gemfile096
6
- - Gemfile098
7
3
  rvm:
8
4
  - jruby-1.7.19
9
5
  - jruby-1.7.21
@@ -14,5 +10,4 @@ jdk:
14
10
  matrix:
15
11
  include:
16
12
  - rvm: 1.9.3
17
- gemfile: Gemfile
18
13
  jdk: openjdk7
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'fast-rsa-engine'
5
- s.version = '0.2.1'
5
+ s.version = '0.3.0'
6
6
  s.author = 'Christian Meier'
7
7
  s.email = [ 'christian.meier@lookout.com', 'rtyler.croy@lookout.com' ]
8
8
 
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.requirements << "pom org.jruby:jruby-core, 1.7.21, :scope => :provided"
28
28
 
29
29
  s.add_runtime_dependency 'jar-dependencies', '~> 0.1'
30
+ s.add_runtime_dependency 'jruby-openssl', '~> 0.9.10'
30
31
  s.add_development_dependency 'ruby-maven', '~> 3.3'
31
32
  end
32
33
 
@@ -1,31 +1,21 @@
1
1
  if RUBY_PLATFORM == 'java'
2
2
  require 'fast-rsa-engine_jars.rb'
3
- begin
4
- Java::OrgJrubyExtOpenssl::SecurityHelper
5
- warn 'openssl loaded before fast-rsa-engine'
6
- rescue NameError
7
- require 'fast-rsa-engine.jar'
8
- end
3
+ require 'fast-rsa-engine.jar'
9
4
  require 'openssl'
10
5
 
11
- # lexical compare is sufficient here
12
- if Jopenssl::Version::VERSION > '0.9.5'
13
- # keep the default name space clean and use tap
14
- tap do
15
- sign_names = [ "MD2", "MD4", "MD5",
16
- "RIPEMD128", "RIPEMD160", "RIPEMD256",
17
- "SHA1", "SHA224", "SHA256", "SHA384", "SHA512" ]
18
- sign_names.each do |name|
19
- full = "#{name}WITHRSA"
20
- clazz = JRuby.runtime.jruby_class_loader.load_class( "com.github.lookout.fastrsa.FastDigestSignatureSpi$#{name}" )
21
- Java::OrgJrubyExtOpenssl::SecurityHelper.add_signature(full, clazz)
22
- end
23
-
24
- Java::OrgJrubyExtOpenssl::SecurityHelper.add_cipher('RSA',
25
- com.github.lookout.fastrsa.FastCipherSpi::NoPadding.java_class)
6
+ # keep the default name space clean and use tap
7
+ tap do
8
+ sign_names = [ "MD2", "MD4", "MD5",
9
+ "RIPEMD128", "RIPEMD160", "RIPEMD256",
10
+ "SHA1", "SHA224", "SHA256", "SHA384", "SHA512" ]
11
+ sign_names.each do |name|
12
+ full = "#{name}WITHRSA"
13
+ clazz = JRuby.runtime.jruby_class_loader.load_class( "com.github.lookout.fastrsa.FastDigestSignatureSpi$#{name}" )
14
+ Java::OrgJrubyExtOpenssl::SecurityHelper.add_signature(full, clazz)
26
15
  end
27
- else
28
- warn "jruby-openssl gem #{Jopenssl::Version::VERSION} is too old"
16
+
17
+ Java::OrgJrubyExtOpenssl::SecurityHelper.add_cipher('RSA',
18
+ com.github.lookout.fastrsa.FastCipherSpi::NoPadding.java_class)
29
19
  end
30
20
  else
31
21
  warn "fast-rsa-engine does not affect MRI"
data/spec/cipher_spec.rb CHANGED
@@ -18,7 +18,6 @@ describe 'Cipher' do
18
18
  let( :rounds ) { 100 }
19
19
 
20
20
  it 'is faster the regular cipher' do
21
- skip( 'jruby too old' ) if too_old
22
21
  # clear the fast engines
23
22
  engines.clear
24
23
 
@@ -3,7 +3,6 @@ require_relative 'setup'
3
3
  describe 'SecurityHelper' do
4
4
 
5
5
  it 'registers signatures with SecurityHelper' do
6
- skip( 'jruby too old' ) if too_old
7
6
  # clear the fast engines
8
7
  engines.clear
9
8
  # setup the fast engines - this creates a warning
data/spec/setup.rb CHANGED
@@ -1,15 +1,12 @@
1
+ unless defined? JRUBY_VERSION
2
+ exit
3
+ end
4
+
1
5
  $: << File.expand_path( '../../lib', __FILE__ )
2
6
  require 'fast-rsa-engine'
3
7
 
4
- def too_old
5
- if defined? Jopenssl::Version
6
- Jopenssl::Version::VERSION < '0.9.6'
7
- else
8
- true # we are in MRI
9
- end
10
- end
11
8
  def engines
12
9
  engines = Java::OrgJrubyExtOpenssl::SecurityHelper.java_class.declared_field 'implEngines'
13
10
  engines.accessible = true
14
11
  engines.value( Java::OrgJrubyExtOpenssl::SecurityHelper )
15
- end unless too_old
12
+ end
@@ -11,7 +11,6 @@ describe 'Signature' do
11
11
  let( :rounds ) { 10 }
12
12
 
13
13
  it 'is faster the regular signature' do
14
- skip( 'jruby too old' ) if too_old
15
14
  # clear the fast engines
16
15
  engines.clear
17
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast-rsa-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Meier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-17 00:00:00.000000000 Z
11
+ date: 2015-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -50,10 +50,6 @@ files:
50
50
  - ".gitignore"
51
51
  - ".travis.yml"
52
52
  - Gemfile
53
- - Gemfile096
54
- - Gemfile096.lock
55
- - Gemfile098
56
- - Gemfile098.lock
57
53
  - LICENSE
58
54
  - README.md
59
55
  - Rakefile
@@ -73,7 +69,6 @@ files:
73
69
  - spec/signature_spec.rb
74
70
  - src/main/java/com/github/lookout/fastrsa/FastCipherSpi.java
75
71
  - src/main/java/com/github/lookout/fastrsa/FastDigestSignatureSpi.java
76
- - src/main/java/org/jruby/ext/openssl/SecurityHelper.java
77
72
  homepage: https://github.com/lookout/fast-rsa-engine
78
73
  licenses:
79
74
  - MIT
@@ -100,3 +95,4 @@ specification_version: 4
100
95
  summary: replaces the RSA signature and RSA ciphers from jruby-openssl by a faster
101
96
  implementation of them
102
97
  test_files: []
98
+ has_rdoc:
data/Gemfile096 DELETED
@@ -1,7 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
-
4
- gemspec
5
-
6
- gem 'jruby-openssl', '0.9.6'
7
-
data/Gemfile098 DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
-
4
- gemspec
5
-
6
- gem 'jruby-openssl', '0.9.8'
@@ -1,751 +0,0 @@
1
- /*
2
- * The MIT License
3
- *
4
- * Copyright 2014 Karol Bucek.
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a copy
7
- * of this software and associated documentation files (the "Software"), to deal
8
- * in the Software without restriction, including without limitation the rights
9
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the Software is
11
- * furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be included in
14
- * all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- * THE SOFTWARE.
23
- */
24
- package org.jruby.ext.openssl;
25
-
26
- import java.io.IOException;
27
- import java.lang.reflect.Constructor;
28
- import java.lang.reflect.Field;
29
- import java.lang.reflect.InvocationTargetException;
30
- import java.lang.reflect.Method;
31
- import java.math.BigInteger;
32
- import java.security.InvalidKeyException;
33
- import java.security.KeyFactory;
34
- import java.security.KeyFactorySpi;
35
- import java.security.KeyPairGenerator;
36
- import java.security.KeyPairGeneratorSpi;
37
- import java.security.KeyStore;
38
- import java.security.KeyStoreException;
39
- import java.security.MessageDigest;
40
- import java.security.MessageDigestSpi;
41
- import java.security.NoSuchAlgorithmException;
42
- import java.security.Provider;
43
- import java.security.PublicKey;
44
- import java.security.SecureRandom;
45
- import java.security.SecureRandomSpi;
46
- import java.security.Security;
47
- import java.security.Signature;
48
- import java.security.SignatureException;
49
- import java.security.SignatureSpi;
50
- import java.security.cert.CRLException;
51
- import java.security.cert.CertificateException;
52
- import java.security.cert.CertificateFactory;
53
- import java.security.cert.CertificateFactorySpi;
54
- import java.security.cert.X509CRL;
55
- import java.security.interfaces.DSAParams;
56
- import java.security.interfaces.DSAPublicKey;
57
- import java.security.interfaces.RSAPublicKey;
58
- import java.util.Locale;
59
- import java.util.Map;
60
- import java.util.StringTokenizer;
61
- import java.util.concurrent.ConcurrentHashMap;
62
-
63
- import javax.crypto.Cipher;
64
- import javax.crypto.CipherSpi;
65
- import javax.crypto.KeyGenerator;
66
- import javax.crypto.KeyGeneratorSpi;
67
- import javax.crypto.Mac;
68
- import javax.crypto.MacSpi;
69
- import javax.crypto.NoSuchPaddingException;
70
- import javax.crypto.SecretKeyFactory;
71
- import javax.crypto.SecretKeyFactorySpi;
72
- import javax.net.ssl.SSLContext;
73
-
74
- import com.sun.crypto.provider.CipherWithWrappingSpi;
75
- import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
76
- import org.bouncycastle.asn1.x509.CertificateList;
77
- import org.bouncycastle.cert.CertException;
78
- import org.bouncycastle.cert.X509CRLHolder;
79
- import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
80
- import org.bouncycastle.crypto.params.DSAParameters;
81
- import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
82
- import org.bouncycastle.crypto.params.RSAKeyParameters;
83
- import org.bouncycastle.jce.provider.X509CRLObject;
84
- import org.bouncycastle.operator.ContentVerifierProvider;
85
- import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
86
- import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder;
87
- import org.bouncycastle.operator.OperatorException;
88
- import org.bouncycastle.operator.bc.BcDSAContentVerifierProviderBuilder;
89
- import org.bouncycastle.operator.bc.BcRSAContentVerifierProviderBuilder;
90
-
91
- /**
92
- * Java Security (and JCE) helpers.
93
- *
94
- * @author kares
95
- */
96
- public abstract class SecurityHelper {
97
-
98
- private static String BC_PROVIDER_CLASS = "org.bouncycastle.jce.provider.BouncyCastleProvider";
99
- static boolean setBouncyCastleProvider = true; // (package access for tests)
100
- static Provider securityProvider; // 'BC' provider (package access for tests)
101
- private static Boolean registerProvider = null;
102
- private static final Map<String, Class> implEngines = new ConcurrentHashMap<String, Class>(16, 0.75f, 1);
103
-
104
- public static void addCipher(String name, Class<? extends CipherSpi> clazz) {
105
- implEngines.put("Cipher:" + name, clazz);
106
- tryCipherInternal = true;
107
- }
108
-
109
- public static void addSignature(String name, Class<? extends SignatureSpi> clazz) {
110
- implEngines.put("Signature:" + name, clazz);
111
- }
112
-
113
- public static Provider getSecurityProvider() {
114
- if ( setBouncyCastleProvider && securityProvider == null ) {
115
- synchronized(SecurityHelper.class) {
116
- if ( setBouncyCastleProvider && securityProvider == null ) {
117
- setBouncyCastleProvider(); setBouncyCastleProvider = false;
118
- }
119
- }
120
- }
121
- doRegisterProvider();
122
- return securityProvider;
123
- }
124
-
125
- public static synchronized void setSecurityProvider(final Provider provider) {
126
- securityProvider = provider;
127
- }
128
-
129
- static synchronized void setBouncyCastleProvider() {
130
- setSecurityProvider( newBouncyCastleProvider() );
131
- }
132
-
133
- private static Provider newBouncyCastleProvider() {
134
- try {
135
- return (Provider) Class.forName(BC_PROVIDER_CLASS).newInstance();
136
- }
137
- catch (Throwable ignored) { /* no bouncy castle available */ }
138
- return null;
139
- }
140
-
141
- public static synchronized void setRegisterProvider(boolean register) {
142
- registerProvider = Boolean.valueOf(register); doRegisterProvider();
143
- }
144
-
145
- static boolean isProviderAvailable(final String name) {
146
- return Security.getProvider(name) != null;
147
- }
148
-
149
- static boolean isProviderRegistered() {
150
- if ( securityProvider == null ) return false;
151
- return Security.getProvider(securityProvider.getName()) != null;
152
- }
153
-
154
- private static void doRegisterProvider() {
155
- if ( registerProvider != null ) {
156
- synchronized(SecurityHelper.class) {
157
- if ( registerProvider != null && registerProvider.booleanValue() ) {
158
- if ( securityProvider != null ) {
159
- Security.addProvider(securityProvider);
160
- }
161
- }
162
- }
163
- registerProvider = null;
164
- }
165
- }
166
-
167
- /**
168
- * @note code calling this should not assume BC provider internals !
169
- */
170
- public static CertificateFactory getCertificateFactory(final String type)
171
- throws CertificateException {
172
- try {
173
- final Provider provider = getSecurityProvider();
174
- if ( provider != null ) return getCertificateFactory(type, provider);
175
- }
176
- catch (CertificateException e) { }
177
- return CertificateFactory.getInstance(type);
178
- }
179
-
180
- static CertificateFactory getCertificateFactory(final String type, final Provider provider)
181
- throws CertificateException {
182
- final CertificateFactorySpi spi = (CertificateFactorySpi) getImplEngine("CertificateFactory", type);
183
- if ( spi == null ) throw new CertificateException(type + " not found");
184
- return newInstance(CertificateFactory.class,
185
- new Class[]{ CertificateFactorySpi.class, Provider.class, String.class },
186
- new Object[]{ spi, provider, type }
187
- );
188
- }
189
-
190
- /**
191
- * @note code calling this should not assume BC provider internals !
192
- */
193
- public static KeyFactory getKeyFactory(final String algorithm)
194
- throws NoSuchAlgorithmException {
195
- try {
196
- final Provider provider = getSecurityProvider();
197
- if ( provider != null ) return getKeyFactory(algorithm, provider);
198
- }
199
- catch (NoSuchAlgorithmException e) { }
200
- return KeyFactory.getInstance(algorithm);
201
- }
202
-
203
- static KeyFactory getKeyFactory(final String algorithm, final Provider provider)
204
- throws NoSuchAlgorithmException {
205
- KeyFactorySpi spi = (KeyFactorySpi) getImplEngine("KeyFactory", algorithm);
206
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " not found");
207
- return newInstance(KeyFactory.class,
208
- new Class[] { KeyFactorySpi.class, Provider.class, String.class },
209
- new Object[] { spi, provider, algorithm }
210
- );
211
- }
212
-
213
- /**
214
- * @note code calling this should not assume BC provider internals !
215
- */
216
- public static KeyPairGenerator getKeyPairGenerator(final String algorithm)
217
- throws NoSuchAlgorithmException {
218
- try {
219
- final Provider provider = getSecurityProvider();
220
- if ( provider != null ) return getKeyPairGenerator(algorithm, provider);
221
- }
222
- catch (NoSuchAlgorithmException e) { }
223
- return KeyPairGenerator.getInstance(algorithm);
224
- }
225
-
226
- @SuppressWarnings("unchecked")
227
- static KeyPairGenerator getKeyPairGenerator(final String algorithm, final Provider provider)
228
- throws NoSuchAlgorithmException {
229
- final Object spi = getImplEngine("KeyPairGenerator", algorithm);
230
- if ( spi == null ) {
231
- throw new NoSuchAlgorithmException(algorithm + " KeyPairGenerator not available");
232
- }
233
-
234
- final KeyPairGenerator keyPairGenerator;
235
- if ( spi instanceof KeyPairGenerator ) {
236
- keyPairGenerator = (KeyPairGenerator) spi;
237
- }
238
- else {
239
- final Class<? extends KeyPairGenerator> delegate;
240
- try {
241
- delegate = (Class<? extends KeyPairGenerator>)
242
- Class.forName(KeyPairGenerator.class.getName() + "$Delegate");
243
- } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
244
-
245
- keyPairGenerator = newInstance(delegate,
246
- new Class[] { KeyPairGeneratorSpi.class, String.class }, spi, algorithm
247
- );
248
- }
249
- setField(keyPairGenerator, KeyPairGenerator.class, "provider", provider);
250
- return keyPairGenerator;
251
- }
252
-
253
- /**
254
- * @note code calling this should not assume BC provider internals !
255
- */
256
- public static KeyStore getKeyStore(final String type)
257
- throws KeyStoreException {
258
- try {
259
- final Provider provider = getSecurityProvider();
260
- if ( provider != null ) return getKeyStore(type, provider);
261
- }
262
- catch (KeyStoreException e) { }
263
- return KeyStore.getInstance(type);
264
- }
265
-
266
- static KeyStore getKeyStore(final String type, final Provider provider)
267
- throws KeyStoreException {
268
- return KeyStore.getInstance(type, provider);
269
- }
270
-
271
- /**
272
- * @note code calling this should not assume BC provider internals !
273
- */
274
- public static MessageDigest getMessageDigest(final String algorithm) throws NoSuchAlgorithmException {
275
- try {
276
- final Provider provider = getSecurityProvider();
277
- if ( provider != null ) return getMessageDigest(algorithm, provider);
278
- }
279
- catch (NoSuchAlgorithmException e) { }
280
- return MessageDigest.getInstance(algorithm);
281
- }
282
-
283
- @SuppressWarnings("unchecked")
284
- static MessageDigest getMessageDigest(final String algorithm, final Provider provider)
285
- throws NoSuchAlgorithmException {
286
- final Object spi = getImplEngine("MessageDigest", algorithm);
287
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " not found");
288
-
289
- final MessageDigest messageDigest;
290
- if ( spi instanceof MessageDigest ) {
291
- messageDigest = (MessageDigest) spi;
292
- }
293
- else {
294
- final Class<? extends MessageDigest> delegate;
295
- try {
296
- delegate = (Class<? extends MessageDigest>)
297
- Class.forName(MessageDigest.class.getName() + "$Delegate");
298
- } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
299
-
300
- messageDigest = newInstance(delegate,
301
- new Class[] { MessageDigestSpi.class, String.class }, spi, algorithm
302
- );
303
- }
304
- setField(messageDigest, MessageDigest.class, "provider", provider);
305
- return messageDigest;
306
- }
307
-
308
- public static SecureRandom getSecureRandom() {
309
- try {
310
- final Provider provider = getSecurityProvider();
311
- if ( provider != null ) {
312
- final String algorithm = getSecureRandomAlgorithm(provider);
313
- if ( algorithm != null ) {
314
- return getSecureRandom(algorithm, provider);
315
- }
316
- }
317
- }
318
- catch (NoSuchAlgorithmException e) { }
319
- return new SecureRandom(); // likely "SHA1PRNG" from SPI sun.security.provider.SecureRandom
320
- }
321
-
322
- private static SecureRandom getSecureRandom(final String algorithm, final Provider provider)
323
- throws NoSuchAlgorithmException {
324
- final SecureRandomSpi spi = (SecureRandomSpi) getImplEngine("SecureRandom", algorithm);
325
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " not found");
326
-
327
- return newInstance(SecureRandom.class,
328
- new Class[] { SecureRandomSpi.class, Provider.class, String.class },
329
- new Object[] { spi, provider, algorithm }
330
- );
331
- }
332
-
333
- // NOTE: none (at least for BC 1.47)
334
- private static String getSecureRandomAlgorithm(final Provider provider) {
335
- for ( Provider.Service service : provider.getServices() ) {
336
- if ( "SecureRandom".equals( service.getType() ) ) {
337
- return service.getAlgorithm();
338
- }
339
- }
340
- return null;
341
- }
342
-
343
- static void debugStackTrace(Exception e){
344
- e.printStackTrace();
345
- }
346
- private static Boolean tryCipherInternal = Boolean.FALSE;
347
-
348
- /**
349
- * @note code calling this should not assume BC provider internals !
350
- */
351
- public static Cipher getCipher(final String transformation)
352
- throws NoSuchAlgorithmException, NoSuchPaddingException {
353
- try {
354
- if ( tryCipherInternal == Boolean.FALSE ) {
355
- final Provider provider = getSecurityProvider();
356
- if ( provider != null ) {
357
- return getCipher(transformation, provider);
358
- }
359
- }
360
- }
361
- catch (NoSuchAlgorithmException e) { }
362
- catch (NoSuchPaddingException e) { }
363
- catch (SecurityException e) {
364
- // java.lang.SecurityException: JCE cannot authenticate the provider BC
365
- if ( tryCipherInternal != null ) tryCipherInternal = Boolean.TRUE;
366
- debugStackTrace(e);
367
- }
368
- if ( tryCipherInternal == Boolean.TRUE ) {
369
- try {
370
- final Provider provider = getSecurityProvider();
371
- if ( provider != null ) {
372
- return getCipherInternal(transformation, provider);
373
- }
374
- }
375
- catch (NoSuchAlgorithmException e) { }
376
- catch (RuntimeException e) {
377
- // likely javax.crypto.JceSecurityManager.isCallerTrusted gets
378
- // us a NPE from javax.crypto.Cipher.<init>(Cipher.java:264)
379
- tryCipherInternal = null; // do not try BC at all
380
- debugStackTrace(e);
381
- }
382
- }
383
- return Cipher.getInstance(transformation);
384
- }
385
-
386
- static Cipher getCipher(final String transformation, final Provider provider)
387
- throws NoSuchAlgorithmException, NoSuchPaddingException {
388
- return Cipher.getInstance(transformation, provider);
389
- }
390
-
391
- private static final Class<?>[] STRING_PARAM = { String.class };
392
-
393
- private static Cipher getCipherInternal(String transformation, final Provider provider)
394
- throws NoSuchAlgorithmException {
395
- CipherSpi spi = (CipherSpi) getImplEngine("Cipher", transformation);
396
- if ( spi == null ) {
397
- //
398
- // try the long way
399
- //
400
- StringTokenizer tok = new StringTokenizer(transformation, "/");
401
- final String algorithm = tok.nextToken();
402
-
403
- spi = (CipherSpi) getImplEngine("Cipher", algorithm);
404
- if ( spi == null ) {
405
- // if ( silent ) return null;
406
- throw new NoSuchAlgorithmException(transformation + " not found");
407
- }
408
-
409
- //
410
- // make sure we don't get fooled by a "//" in the string
411
- //
412
- if ( tok.hasMoreTokens() && ! transformation.regionMatches(algorithm.length(), "//", 0, 2) ) {
413
- // spi.engineSetMode(tok.nextToken()) :
414
- invoke(spi, CipherSpi.class, "engineSetMode", STRING_PARAM, tok.nextToken());
415
- }
416
- if ( tok.hasMoreTokens() ) {
417
- // spi.engineSetPadding(tok.nextToken()) :
418
- invoke(spi, CipherSpi.class, "engineSetPadding", STRING_PARAM, tok.nextToken());
419
- }
420
-
421
- }
422
- try {
423
- return newInstance(Cipher.class,
424
- new Class[] { CipherSpi.class, Provider.class, String.class },
425
- new Object[] { spi, provider, transformation }
426
- );
427
- }
428
- catch( IllegalStateException e ) {
429
- // this can be due to trusted check in Cipher constructor
430
- if (e.getCause().getClass() == NullPointerException.class) {
431
- Cipher cipher = newInstance(Cipher.class,
432
- new Class[] { CipherSpi.class, String.class },
433
- new Object[] { spi, transformation }
434
- );
435
- setField(cipher, Cipher.class, "provider", provider);
436
- return cipher;
437
- }
438
- throw e;
439
- }
440
- }
441
-
442
- /**
443
- * @note code calling this should not assume BC provider internals !
444
- */
445
- public static Signature getSignature(final String algorithm) throws NoSuchAlgorithmException {
446
- try {
447
- final Provider provider = getSecurityProvider();
448
- if ( provider != null ) return getSignature(algorithm, provider);
449
- }
450
- catch (NoSuchAlgorithmException e) { }
451
- return Signature.getInstance(algorithm);
452
- }
453
-
454
- @SuppressWarnings("unchecked")
455
- static Signature getSignature(final String algorithm, final Provider provider)
456
- throws NoSuchAlgorithmException {
457
- final Object spi = getImplEngine("Signature", algorithm);
458
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " Signature not available");
459
-
460
- final Signature signature;
461
- if ( spi instanceof Signature ) {
462
- signature = (Signature) spi;
463
- } else {
464
- final Class<? extends Signature> delegate;
465
- try {
466
- delegate = (Class<? extends Signature>)
467
- Class.forName(Signature.class.getName() + "$Delegate");
468
- } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
469
-
470
- signature = newInstance(delegate,
471
- new Class[] { SignatureSpi.class, String.class }, spi, algorithm
472
- );
473
- }
474
- setField(signature, Signature.class, "provider", provider);
475
- return signature;
476
- }
477
-
478
- /**
479
- * @note code calling this should not assume BC provider internals !
480
- */
481
- public static Mac getMac(final String algorithm) throws NoSuchAlgorithmException {
482
- Mac mac = null;
483
- final Provider provider = getSecurityProvider();
484
- if ( provider != null ) {
485
- mac = getMac(algorithm, provider, true);
486
- }
487
- if ( mac == null ) mac = Mac.getInstance(algorithm);
488
- return mac;
489
- }
490
-
491
- static Mac getMac(final String algorithm, final Provider provider)
492
- throws NoSuchAlgorithmException {
493
- return getMac(algorithm, provider, false);
494
- }
495
-
496
- private static Mac getMac(final String algorithm, final Provider provider, boolean silent)
497
- throws NoSuchAlgorithmException {
498
- MacSpi spi = (MacSpi) getImplEngine("Mac", algorithm);
499
- if ( spi == null ) {
500
- if ( silent ) return null;
501
- throw new NoSuchAlgorithmException(algorithm + " not found");
502
- }
503
- return newInstance(Mac.class,
504
- new Class[] { MacSpi.class, Provider.class, String.class },
505
- new Object[] { spi, provider, algorithm }
506
- );
507
- }
508
-
509
- /**
510
- * @note code calling this should not assume BC provider internals !
511
- */
512
- public static KeyGenerator getKeyGenerator(final String algorithm) throws NoSuchAlgorithmException {
513
- try {
514
- final Provider provider = getSecurityProvider();
515
- if ( provider != null ) return getKeyGenerator(algorithm, provider);
516
- }
517
- catch (NoSuchAlgorithmException e) { }
518
- catch (SecurityException e) { debugStackTrace(e); }
519
- return KeyGenerator.getInstance(algorithm);
520
- }
521
-
522
- static KeyGenerator getKeyGenerator(final String algorithm, final Provider provider)
523
- throws NoSuchAlgorithmException {
524
- final KeyGeneratorSpi spi = (KeyGeneratorSpi) getImplEngine("KeyGenerator", algorithm);
525
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " not found");
526
-
527
- return newInstance(KeyGenerator.class,
528
- new Class[] { KeyGeneratorSpi.class, Provider.class, String.class },
529
- new Object[] { spi, provider, algorithm }
530
- );
531
- }
532
-
533
- /**
534
- * @note code calling this should not assume BC provider internals !
535
- */
536
- public static SecretKeyFactory getSecretKeyFactory(final String algorithm) throws NoSuchAlgorithmException {
537
- try {
538
- final Provider provider = getSecurityProvider();
539
- if ( provider != null ) return getSecretKeyFactory(algorithm, provider);
540
- }
541
- catch (NoSuchAlgorithmException e) { }
542
- catch (SecurityException e) { debugStackTrace(e); }
543
- return SecretKeyFactory.getInstance(algorithm);
544
- }
545
-
546
- static SecretKeyFactory getSecretKeyFactory(final String algorithm, final Provider provider)
547
- throws NoSuchAlgorithmException {
548
- final SecretKeyFactorySpi spi = (SecretKeyFactorySpi) getImplEngine("SecretKeyFactory", algorithm);
549
- if ( spi == null ) throw new NoSuchAlgorithmException(algorithm + " not found");
550
-
551
- return newInstance(SecretKeyFactory.class,
552
- new Class[] { SecretKeyFactorySpi.class, Provider.class, String.class },
553
- new Object[] { spi, provider, algorithm }
554
- );
555
- }
556
-
557
- private static boolean providerSSLContext = false; // BC does not implement + JDK default is fine
558
-
559
- public static SSLContext getSSLContext(final String protocol)
560
- throws NoSuchAlgorithmException {
561
- try {
562
- if ( providerSSLContext ) {
563
- final Provider provider = getSecurityProvider();
564
- if ( provider != null ) {
565
- return getSSLContext(protocol, provider);
566
- }
567
- }
568
- }
569
- catch (NoSuchAlgorithmException e) { }
570
- return SSLContext.getInstance(protocol);
571
- }
572
-
573
- private static SSLContext getSSLContext(final String protocol, final Provider provider)
574
- throws NoSuchAlgorithmException {
575
- return SSLContext.getInstance(protocol, provider);
576
- }
577
-
578
- public static boolean verify(final X509CRL crl, final PublicKey publicKey)
579
- throws NoSuchAlgorithmException, CRLException, InvalidKeyException, SignatureException {
580
- return verify(crl, publicKey, false);
581
- }
582
-
583
- static boolean verify(final X509CRL crl, final PublicKey publicKey, final boolean silent)
584
- throws NoSuchAlgorithmException, CRLException, InvalidKeyException, SignatureException {
585
-
586
- if ( crl instanceof X509CRLObject ) {
587
- final CertificateList crlList = (CertificateList) getCertificateList(crl);
588
- final AlgorithmIdentifier tbsSignatureId = crlList.getTBSCertList().getSignature();
589
- if ( ! crlList.getSignatureAlgorithm().equals(tbsSignatureId) ) {
590
- if ( silent ) return false;
591
- throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList.");
592
- }
593
-
594
- final Signature signature = getSignature(crl.getSigAlgName(), securityProvider);
595
-
596
- signature.initVerify(publicKey);
597
- signature.update(crl.getTBSCertList());
598
-
599
- if ( ! signature.verify( crl.getSignature() ) ) {
600
- if ( silent ) return false;
601
- throw new SignatureException("CRL does not verify with supplied public key.");
602
- }
603
- return true;
604
- }
605
- else {
606
- try {
607
- final DigestAlgorithmIdentifierFinder digestAlgFinder = new DefaultDigestAlgorithmIdentifierFinder();
608
- final ContentVerifierProvider verifierProvider;
609
- if ( "DSA".equalsIgnoreCase( publicKey.getAlgorithm() )) {
610
- BigInteger y = ((DSAPublicKey) publicKey).getY();
611
- DSAParams params = ((DSAPublicKey) publicKey).getParams();
612
- DSAParameters parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
613
- AsymmetricKeyParameter dsaKey = new DSAPublicKeyParameters(y, parameters);
614
- verifierProvider = new BcDSAContentVerifierProviderBuilder(digestAlgFinder).build(dsaKey);
615
- }
616
- else {
617
- BigInteger mod = ((RSAPublicKey) publicKey).getModulus();
618
- BigInteger exp = ((RSAPublicKey) publicKey).getPublicExponent();
619
- AsymmetricKeyParameter rsaKey = new RSAKeyParameters(false, mod, exp);
620
- verifierProvider = new BcRSAContentVerifierProviderBuilder(digestAlgFinder).build(rsaKey);
621
- }
622
- return new X509CRLHolder(crl.getEncoded()).isSignatureValid( verifierProvider );
623
- }
624
- catch (OperatorException e) {
625
- throw new SignatureException(e);
626
- }
627
- catch (CertException e) {
628
- throw new SignatureException(e);
629
- }
630
- // can happen if the input is DER but does not match expected strucure
631
- catch (ClassCastException e) {
632
- throw new SignatureException(e);
633
- }
634
- catch (IOException e) {
635
- throw new SignatureException(e);
636
- }
637
- }
638
- }
639
-
640
- private static Object getCertificateList(final Object crl) { // X509CRLObject
641
- try { // private CertificateList c;
642
- final Field cField = X509CRLObject.class.getDeclaredField("c");
643
- cField.setAccessible(true);
644
- return cField.get(crl);
645
- }
646
- catch (NoSuchFieldException e) {
647
- debugStackTrace(e); return null;
648
- }
649
- catch (IllegalAccessException e) { return null; }
650
- catch (SecurityException e) { return null; }
651
- }
652
-
653
- // these are BC JCE (@see javax.crypto.JCEUtil) inspired internals :
654
- // https://github.com/bcgit/bc-java/blob/master/jce/src/main/java/javax/crypto/JCEUtil.java
655
-
656
- private static Object getImplEngine(String baseName, String algorithm) {
657
- Object engine = findImplEngine(baseName, algorithm.toUpperCase(Locale.ENGLISH));
658
- if (engine == null) {
659
- engine = findImplEngine(baseName, algorithm);
660
- }
661
- return engine;
662
- }
663
-
664
- private static Object findImplEngine(final String baseName, String algorithm) {
665
- Class implEngineClass = implEngines.get(baseName + ":" + algorithm);
666
-
667
- if (implEngineClass == null) {
668
- final Provider bcProvider = securityProvider;
669
- String alias;
670
- while ((alias = bcProvider.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) {
671
- algorithm = alias;
672
- }
673
- final String className = bcProvider.getProperty(baseName + "." + algorithm);
674
- if (className != null) {
675
- try {
676
- ClassLoader loader = bcProvider.getClass().getClassLoader();
677
- if (loader != null) {
678
- implEngineClass = loader.loadClass(className);
679
- } else {
680
- implEngineClass = Class.forName(className);
681
- }
682
- implEngineClass.newInstance(); // this instance is thrown away to test newInstance, but only once
683
- } catch (ClassNotFoundException e) {
684
- throw new IllegalStateException("algorithm " + algorithm + " in provider " + bcProvider.getName() + " but no class \"" + className + "\" found!");
685
- } catch (Exception e) {
686
- throw new IllegalStateException("algorithm " + algorithm + " in provider " + bcProvider.getName() + " but class \"" + className + "\" inaccessible!");
687
- }
688
- } else {
689
- return null;
690
- }
691
-
692
- implEngines.put(baseName + ":" + algorithm, implEngineClass);
693
- }
694
-
695
- try {
696
- return implEngineClass.newInstance();
697
- } catch (Exception e) {
698
- final Provider bcProvider = securityProvider;
699
- String className = implEngineClass.getName();
700
- throw new IllegalStateException("algorithm " + algorithm + " in provider " + bcProvider.getName() + " but class \"" + className + "\" inaccessible!");
701
- }
702
- }
703
-
704
- // the obligratory "reflection crap" :
705
-
706
- private static <T> T newInstance(Class<T> klass, Class<?>[] paramTypes, Object... params) {
707
- final Constructor<T> constructor;
708
- try {
709
- constructor = klass.getDeclaredConstructor(paramTypes);
710
- constructor.setAccessible(true);
711
- return constructor.newInstance(params);
712
- } catch (NoSuchMethodException e) {
713
- throw new IllegalStateException(e.getMessage(), e);
714
- } catch (InvocationTargetException e) {
715
- throw new IllegalStateException(e.getTargetException());
716
- } catch (InstantiationException e) {
717
- throw new IllegalStateException(e);
718
- } catch (IllegalAccessException e) {
719
- throw new IllegalStateException(e);
720
- }
721
- }
722
-
723
- @SuppressWarnings("unchecked")
724
- private static <T> T invoke(Object object, Class<?> klass, String methodName, Class<?>[] paramTypes, Object... params) {
725
- final Method method;
726
- try {
727
- method = klass.getDeclaredMethod(methodName, paramTypes);
728
- method.setAccessible(true);
729
- return (T) method.invoke(object, params);
730
- } catch (NoSuchMethodException e) {
731
- throw new IllegalStateException(e.getMessage(), e);
732
- } catch (InvocationTargetException e) {
733
- throw new IllegalStateException(e.getTargetException());
734
- } catch (IllegalAccessException e) {
735
- throw new IllegalStateException(e);
736
- }
737
- }
738
-
739
- private static void setField(Object obj, Class<?> fieldOwner, String fieldName, Object value) {
740
- final Field field;
741
- try {
742
- field = fieldOwner.getDeclaredField(fieldName);
743
- field.setAccessible(true);
744
- field.set(obj, value);
745
- } catch (NoSuchFieldException e) {
746
- throw new IllegalStateException("no field '" + fieldName + "' declared in " + fieldOwner + "", e);
747
- } catch (IllegalAccessException e) {
748
- throw new IllegalStateException(e);
749
- }
750
- }
751
- }