39
39
import net .snowflake .client .log .SFLoggerFactory ;
40
40
import org .apache .commons .codec .binary .Base64 ;
41
41
import org .bouncycastle .asn1 .pkcs .PrivateKeyInfo ;
42
+ import org .bouncycastle .openssl .PEMKeyPair ;
42
43
import org .bouncycastle .openssl .PEMParser ;
43
44
import org .bouncycastle .openssl .jcajce .JcaPEMKeyConverter ;
44
45
import org .bouncycastle .openssl .jcajce .JceOpenSSLPKCS8DecryptorProviderBuilder ;
@@ -67,21 +68,13 @@ class SessionUtilKeyPair {
67
68
68
69
private Provider SecurityProvider = null ;
69
70
70
- private SecretKeyFactory secretKeyFactory = null ;
71
-
72
71
private static final String ISSUER_FMT = "%s.%s.%s" ;
73
72
74
73
private static final String SUBJECT_FMT = "%s.%s" ;
75
74
76
75
private static final int JWT_DEFAULT_AUTH_TIMEOUT = 10 ;
77
76
78
- /** provider name */
79
- private static final String BOUNCY_CASTLE_PROVIDER = "BC" ;
80
-
81
- /** provider name for FIPS */
82
- private static final String BOUNCY_CASTLE_FIPS_PROVIDER = "BCFIPS" ;
83
-
84
- private boolean ENABLE_BOUNCYCASTLE_PROVIDER = true ;
77
+ private boolean isBouncyCastleProviderEnabled = false ;
85
78
86
79
SessionUtilKeyPair (
87
80
PrivateKey privateKey ,
@@ -92,10 +85,14 @@ class SessionUtilKeyPair {
92
85
throws SFException {
93
86
this .userName = userName .toUpperCase ();
94
87
this .accountName = accountName .toUpperCase ();
95
-
88
+ String enableBouncyCastleJvm =
89
+ System .getProperty (SecurityUtil .ENABLE_BOUNCYCASTLE_PROVIDER_JVM );
90
+ if (enableBouncyCastleJvm != null ) {
91
+ isBouncyCastleProviderEnabled = enableBouncyCastleJvm .equalsIgnoreCase ("true" );
92
+ }
96
93
// check if in FIPS mode
97
94
for (Provider p : Security .getProviders ()) {
98
- if (BOUNCY_CASTLE_FIPS_PROVIDER .equals (p .getName ())) {
95
+ if (SecurityUtil . BOUNCY_CASTLE_FIPS_PROVIDER .equals (p .getName ())) {
99
96
this .isFipsMode = true ;
100
97
this .SecurityProvider = p ;
101
98
break ;
@@ -151,11 +148,11 @@ private SecretKeyFactory getSecretKeyFactory(String algorithm) throws NoSuchAlgo
151
148
private PrivateKey extractPrivateKeyFromFile (String privateKeyFile , String privateKeyFilePwd )
152
149
throws SFException {
153
150
154
- if (ENABLE_BOUNCYCASTLE_PROVIDER ) {
151
+ if (isBouncyCastleProviderEnabled ) {
155
152
try {
156
153
return extractPrivateKeyWithBouncyCastle (privateKeyFile , privateKeyFilePwd );
157
154
} catch (IOException | PKCSException | OperatorCreationException e ) {
158
- logger .error ("Could not extract private key using Bouncy Castle provider" );
155
+ logger .error ("Could not extract private key using Bouncy Castle provider" , e );
159
156
throw new SFException (e , ErrorCode .INVALID_OR_UNSUPPORTED_PRIVATE_KEY , e .getCause ());
160
157
}
161
158
} else {
@@ -168,7 +165,8 @@ private PrivateKey extractPrivateKeyFromFile(String privateKeyFile, String priva
168
165
| NullPointerException
169
166
| InvalidKeyException e ) {
170
167
logger .error (
171
- "Could not extract private key. Try setting " + ENABLE_BOUNCYCASTLE_PROVIDER + "=TRUE" );
168
+ "Could not extract private key. Try setting the JVM argument: " + "-D{}" + "=TRUE" ,
169
+ SecurityUtil .ENABLE_BOUNCYCASTLE_PROVIDER_JVM );
172
170
throw new SFException (
173
171
e ,
174
172
ErrorCode .INVALID_OR_UNSUPPORTED_PRIVATE_KEY ,
@@ -246,12 +244,20 @@ private PrivateKey extractPrivateKeyWithBouncyCastle(
246
244
InputDecryptorProvider pkcs8Prov =
247
245
new JceOpenSSLPKCS8DecryptorProviderBuilder ().build (privateKeyFilePwd .toCharArray ());
248
246
privateKeyInfo = encryptedPrivateKeyInfo .decryptPrivateKeyInfo (pkcs8Prov );
247
+ } else if (pemObject instanceof PEMKeyPair ) {
248
+ // PKCS#1 private key
249
+ privateKeyInfo = ((PEMKeyPair ) pemObject ).getPrivateKeyInfo ();
249
250
} else if (pemObject instanceof PrivateKeyInfo ) {
250
251
// Handle the case where the private key is unencrypted.
251
252
privateKeyInfo = (PrivateKeyInfo ) pemObject ;
252
253
}
253
254
pemParser .close ();
254
- JcaPEMKeyConverter converter = new JcaPEMKeyConverter ().setProvider (BOUNCY_CASTLE_PROVIDER );
255
+ JcaPEMKeyConverter converter =
256
+ new JcaPEMKeyConverter ()
257
+ .setProvider (
258
+ isFipsMode
259
+ ? SecurityUtil .BOUNCY_CASTLE_FIPS_PROVIDER
260
+ : SecurityUtil .BOUNCY_CASTLE_PROVIDER );
255
261
return converter .getPrivateKey (privateKeyInfo );
256
262
}
257
263
@@ -260,23 +266,36 @@ private PrivateKey extractPrivateKeyWithJdk(String privateKeyFile, String privat
260
266
String privateKeyContent = new String (Files .readAllBytes (Paths .get (privateKeyFile )));
261
267
if (Strings .isNullOrEmpty (privateKeyFilePwd )) {
262
268
// unencrypted private key file
263
- PemReader pr = new PemReader (new StringReader (privateKeyContent ));
264
- byte [] decoded = pr .readPemObject ().getContent ();
265
- pr .close ();
266
- PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec (decoded );
267
- KeyFactory keyFactory = getKeyFactoryInstance ();
268
- return keyFactory .generatePrivate (encodedKeySpec );
269
+ return generatePrivateKey (false , privateKeyContent , privateKeyFilePwd );
269
270
} else {
270
271
// encrypted private key file
271
- PemReader pr = new PemReader (new StringReader (privateKeyContent ));
272
- byte [] decoded = pr .readPemObject ().getContent ();
273
- pr .close ();
274
- EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo (decoded );
275
- PBEKeySpec keySpec = new PBEKeySpec (privateKeyFilePwd .toCharArray ());
276
- SecretKeyFactory pbeKeyFactory = this .getSecretKeyFactory (pkInfo .getAlgName ());
277
- PKCS8EncodedKeySpec encodedKeySpec = pkInfo .getKeySpec (pbeKeyFactory .generateSecret (keySpec ));
278
- KeyFactory keyFactory = getKeyFactoryInstance ();
279
- return keyFactory .generatePrivate (encodedKeySpec );
272
+ return generatePrivateKey (true , privateKeyContent , privateKeyFilePwd );
273
+ }
274
+ }
275
+
276
+ private PrivateKey generatePrivateKey (
277
+ boolean isEncrypted , String privateKeyContent , String privateKeyFilePwd )
278
+ throws IOException , NoSuchAlgorithmException , InvalidKeySpecException , InvalidKeyException {
279
+ if (isEncrypted ) {
280
+ try (PemReader pr = new PemReader (new StringReader (privateKeyContent ))) {
281
+ byte [] decoded = pr .readPemObject ().getContent ();
282
+ pr .close ();
283
+ EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo (decoded );
284
+ PBEKeySpec keySpec = new PBEKeySpec (privateKeyFilePwd .toCharArray ());
285
+ SecretKeyFactory pbeKeyFactory = this .getSecretKeyFactory (pkInfo .getAlgName ());
286
+ PKCS8EncodedKeySpec encodedKeySpec =
287
+ pkInfo .getKeySpec (pbeKeyFactory .generateSecret (keySpec ));
288
+ KeyFactory keyFactory = getKeyFactoryInstance ();
289
+ return keyFactory .generatePrivate (encodedKeySpec );
290
+ }
291
+ } else {
292
+ try (PemReader pr = new PemReader (new StringReader (privateKeyContent ))) {
293
+ byte [] decoded = pr .readPemObject ().getContent ();
294
+ pr .close ();
295
+ PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec (decoded );
296
+ KeyFactory keyFactory = getKeyFactoryInstance ();
297
+ return keyFactory .generatePrivate (encodedKeySpec );
298
+ }
280
299
}
281
300
}
282
301
}
0 commit comments