mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-07 07:40:55 +03:00
Android Compability, again ;-) (#392)
* Rework SecurityUtils and PKCS8KeyFile for usage with SpongyCastle. * Specifying providerName for registration is unneccessary. * Update AndroidConfig, fix imports. * Workaround for Android 5.0 bug when SpongyCastle is the default JCE provider. On Android 5.0 reading the version from the jar does throw a SecurityException due to a bug in Android (see https://issuetracker.google.com/issues/36993752). Including that Exception in the catch provides a workaround for that issue.
This commit is contained in:
committed by
Jeroen van Erp
parent
d55eb6d02e
commit
39b72eed62
@@ -23,6 +23,9 @@ import net.schmizz.sshj.signature.SignatureRSA;
|
|||||||
import net.schmizz.sshj.transport.random.JCERandom;
|
import net.schmizz.sshj.transport.random.JCERandom;
|
||||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers SpongyCastle as JCE provider.
|
||||||
|
*/
|
||||||
public class AndroidConfig
|
public class AndroidConfig
|
||||||
extends DefaultConfig {
|
extends DefaultConfig {
|
||||||
|
|
||||||
@@ -30,13 +33,6 @@ public class AndroidConfig
|
|||||||
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidConfig(){
|
|
||||||
super();
|
|
||||||
initKeyExchangeFactories(true);
|
|
||||||
initRandomFactory(true);
|
|
||||||
initFileKeyProviderFactories(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't add ECDSA
|
// don't add ECDSA
|
||||||
protected void initSignatureFactories() {
|
protected void initSignatureFactories() {
|
||||||
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory(),
|
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory(),
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class DefaultConfig
|
|||||||
properties.load(DefaultConfig.class.getClassLoader().getResourceAsStream("sshj.properties"));
|
properties.load(DefaultConfig.class.getClassLoader().getResourceAsStream("sshj.properties"));
|
||||||
String property = properties.getProperty("sshj.version");
|
String property = properties.getProperty("sshj.version");
|
||||||
return "SSHJ_" + property.replace('-', '_'); // '-' is a disallowed character, see RFC-4253#section-4.2
|
return "SSHJ_" + property.replace('-', '_'); // '-' is a disallowed character, see RFC-4253#section-4.2
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
log.error("Could not read the sshj.properties file, returning an 'unknown' version as fallback.");
|
log.error("Could not read the sshj.properties file, returning an 'unknown' version as fallback.");
|
||||||
return "SSHJ_VERSION_UNKNOWN";
|
return "SSHJ_VERSION_UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,21 @@ package net.schmizz.sshj.common;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
|
import java.security.Provider;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.security.Signature;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.KeyAgreement;
|
import javax.crypto.KeyAgreement;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
@@ -37,12 +47,17 @@ public class SecurityUtils {
|
|||||||
*/
|
*/
|
||||||
public static final String BOUNCY_CASTLE = "BC";
|
public static final String BOUNCY_CASTLE = "BC";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for the BouncyCastle JCE provider
|
||||||
|
*/
|
||||||
|
public static final String SPONGY_CASTLE = "SC";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Security provider identifier. null = default JCE
|
* Security provider identifier. null = default JCE
|
||||||
*/
|
*/
|
||||||
private static String securityProvider = null;
|
private static String securityProvider = null;
|
||||||
|
|
||||||
// relate to BC registration
|
// relate to BC registration (or SpongyCastle on Android)
|
||||||
private static Boolean registerBouncyCastle;
|
private static Boolean registerBouncyCastle;
|
||||||
private static boolean registrationDone;
|
private static boolean registrationDone;
|
||||||
|
|
||||||
@@ -82,6 +97,8 @@ public class SecurityUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static synchronized Cipher getCipher(String transformation)
|
public static synchronized Cipher getCipher(String transformation)
|
||||||
throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
|
throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
|
||||||
register();
|
register();
|
||||||
@@ -222,11 +239,11 @@ public class SecurityUtils {
|
|||||||
* Attempts registering BouncyCastle as security provider if it has not been previously attempted and returns
|
* Attempts registering BouncyCastle as security provider if it has not been previously attempted and returns
|
||||||
* whether the registration succeeded.
|
* whether the registration succeeded.
|
||||||
*
|
*
|
||||||
* @return whether BC registered
|
* @return whether BC (or SC on Android) registered
|
||||||
*/
|
*/
|
||||||
public static synchronized boolean isBouncyCastleRegistered() {
|
public static synchronized boolean isBouncyCastleRegistered() {
|
||||||
register();
|
register();
|
||||||
return BOUNCY_CASTLE.equals(securityProvider);
|
return BOUNCY_CASTLE.equals(securityProvider) || SPONGY_CASTLE.equals(securityProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void setRegisterBouncyCastle(boolean registerBouncyCastle) {
|
public static synchronized void setRegisterBouncyCastle(boolean registerBouncyCastle) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package net.schmizz.sshj.userauth.keyprovider;
|
package net.schmizz.sshj.userauth.keyprovider;
|
||||||
|
|
||||||
import net.schmizz.sshj.common.IOUtils;
|
import net.schmizz.sshj.common.IOUtils;
|
||||||
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
||||||
import org.bouncycastle.openssl.EncryptionException;
|
import org.bouncycastle.openssl.EncryptionException;
|
||||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
||||||
@@ -62,12 +63,12 @@ public class PKCS8KeyFile extends BaseFileKeyProvider {
|
|||||||
final Object o = r.readObject();
|
final Object o = r.readObject();
|
||||||
|
|
||||||
final JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
|
final JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
|
||||||
pemConverter.setProvider("BC");
|
pemConverter.setProvider(SecurityUtils.getSecurityProvider());
|
||||||
|
|
||||||
if (o instanceof PEMEncryptedKeyPair) {
|
if (o instanceof PEMEncryptedKeyPair) {
|
||||||
final PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) o;
|
final PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) o;
|
||||||
JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
|
JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
|
||||||
decryptorBuilder.setProvider("BC");
|
decryptorBuilder.setProvider(SecurityUtils.getSecurityProvider());
|
||||||
try {
|
try {
|
||||||
passphrase = pwdf == null ? null : pwdf.reqPassword(resource);
|
passphrase = pwdf == null ? null : pwdf.reqPassword(resource);
|
||||||
kp = pemConverter.getKeyPair(encryptedKeyPair.decryptKeyPair(decryptorBuilder.build(passphrase)));
|
kp = pemConverter.getKeyPair(encryptedKeyPair.decryptKeyPair(decryptorBuilder.build(passphrase)));
|
||||||
|
|||||||
Reference in New Issue
Block a user