Skip to content

Commit

Permalink
Fix for hierynomus#437
Browse files Browse the repository at this point in the history
  • Loading branch information
David Solin committed Jul 16, 2021
1 parent 740a492 commit 4971e5b
Showing 1 changed file with 65 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,37 @@
*/
package net.schmizz.sshj.userauth.keyprovider;

import com.hierynomus.sshj.common.KeyDecryptionFailedException;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.userauth.password.PasswordUtils;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.EncryptionException;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.RSAPublicKeySpec;

/** Represents a PKCS8-encoded key file. This is the format used by (old-style) OpenSSH and OpenSSL. */
public class PKCS8KeyFile extends BaseFileKeyProvider {
Expand Down Expand Up @@ -66,7 +82,7 @@ protected KeyPair readKeyPair()
final JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
if (SecurityUtils.getSecurityProvider() != null) {
pemConverter.setProvider(SecurityUtils.getSecurityProvider());
}
}

if (o instanceof PEMEncryptedKeyPair) {
final PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) o;
Expand All @@ -82,15 +98,44 @@ protected KeyPair readKeyPair()
}
} else if (o instanceof PEMKeyPair) {
kp = pemConverter.getKeyPair((PEMKeyPair) o);
} else if (o instanceof PKCS8EncryptedPrivateKeyInfo) {
final PKCS8EncryptedPrivateKeyInfo encryptedInfo = (PKCS8EncryptedPrivateKeyInfo) o;
JceOpenSSLPKCS8DecryptorProviderBuilder decryptorBuilder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
if (SecurityUtils.getSecurityProvider() != null) {
decryptorBuilder.setProvider(SecurityUtils.getSecurityProvider());
}
try {
passphrase = pwdf == null ? null : pwdf.reqPassword(resource);
PrivateKeyInfo pki = encryptedInfo.decryptPrivateKeyInfo(decryptorBuilder.build(passphrase));
kp = getKeyPair(pemConverter, pki);
} catch (OperatorCreationException e) {
throw new IOException(e);
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
} catch (InvalidKeySpecException e) {
throw new IOException(e);
} catch (PKCSException e) {
throw new IOException(e);
} finally {
PasswordUtils.blankOut(passphrase);
}
} else if (o instanceof PrivateKeyInfo) {
try {
kp = getKeyPair(pemConverter, (PrivateKeyInfo)o);
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
} catch (InvalidKeySpecException e) {
throw new IOException(e);
}
} else {
log.debug("Expected PEMEncryptedKeyPair or PEMKeyPair, got: {}", o);
log.debug("Expected PEMEncryptedKeyPair, PEMKeyPair, PKCS8EncryptedPrivateKeyInfo or PrivateKeyInfo, got: {}", o);
}

} catch (EncryptionException e) {
if (pwdf != null && pwdf.shouldRetry(resource))
continue;
else
throw new KeyDecryptionFailedException(e);
throw e;
} finally {
IOUtils.closeQuietly(r);
}
Expand All @@ -106,4 +151,20 @@ protected KeyPair readKeyPair()
public String toString() {
return "PKCS8KeyFile{resource=" + resource + "}";
}

private KeyPair getKeyPair(JcaPEMKeyConverter pemConverter, PrivateKeyInfo pki) throws PEMException, NoSuchAlgorithmException, InvalidKeySpecException {
// get the private key
RSAPrivateKey privateKey = (RSAPrivateKey)pemConverter.getPrivateKey(pki);
BigInteger publicExponent = BigInteger.valueOf(65537);
if (privateKey instanceof RSAPrivateCrtKey) {
publicExponent = ((RSAPrivateCrtKey)privateKey).getPublicExponent();
}

// get the public key
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(privateKey.getModulus(), publicExponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

return new KeyPair(publicKey, privateKey);
}
}

0 comments on commit 4971e5b

Please sign in to comment.