mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 07:10:53 +03:00
Merge pull request #271 from joval/master
Gracefully load OpenSSH known_hosts without requiring BouncyCastle
This commit is contained in:
@@ -426,8 +426,7 @@ public class Buffer<T extends Buffer<T>> {
|
||||
public PublicKey readPublicKey()
|
||||
throws BufferException {
|
||||
try {
|
||||
final String type = readString();
|
||||
return KeyType.fromString(type).readPubKeyFromBuffer(type, this);
|
||||
return KeyType.fromString(readString()).readPubKeyFromBuffer(this);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public enum KeyType {
|
||||
/** SSH identifier for RSA keys */
|
||||
RSA("ssh-rsa") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
final BigInteger e, n;
|
||||
try {
|
||||
@@ -77,7 +77,7 @@ public enum KeyType {
|
||||
/** SSH identifier for DSA keys */
|
||||
DSA("ssh-dss") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
BigInteger p, q, g, y;
|
||||
try {
|
||||
@@ -114,8 +114,11 @@ public enum KeyType {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
||||
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + sType);
|
||||
}
|
||||
try {
|
||||
// final String algo = buf.readString(); it has been already read
|
||||
final String curveName = buf.readString();
|
||||
@@ -127,7 +130,7 @@ public enum KeyType {
|
||||
buf.readRawBytes(y);
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
|
||||
type,
|
||||
sType,
|
||||
curveName,
|
||||
keyLen,
|
||||
x04,
|
||||
@@ -176,14 +179,14 @@ public enum KeyType {
|
||||
ED25519("ssh-ed25519") {
|
||||
private final Logger log = LoggerFactory.getLogger(KeyType.class);
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf) throws GeneralSecurityException {
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException {
|
||||
try {
|
||||
final int keyLen = buf.readUInt32AsInt();
|
||||
final byte[] p = new byte[keyLen];
|
||||
buf.readRawBytes(p);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("Key algo: %s, Key curve: 25519, Key Len: %s\np: %s",
|
||||
type,
|
||||
sType,
|
||||
keyLen,
|
||||
Arrays.toString(p))
|
||||
);
|
||||
@@ -213,9 +216,9 @@ public enum KeyType {
|
||||
/** Unrecognized */
|
||||
UNKNOWN("unknown") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
throw new UnsupportedOperationException("Don't know how to decode key:" + type);
|
||||
throw new UnsupportedOperationException("Don't know how to decode key:" + sType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,7 +241,7 @@ public enum KeyType {
|
||||
this.sType = type;
|
||||
}
|
||||
|
||||
public abstract PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
public abstract PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
public abstract void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf);
|
||||
@@ -263,5 +266,4 @@ public enum KeyType {
|
||||
public String toString() {
|
||||
return sType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class OpenSSHKnownHosts
|
||||
try {
|
||||
// Read in the file, storing each line as an entry
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
while ((line = br.readLine()) != null) {
|
||||
try {
|
||||
HostEntry entry = entryFactory.parseEntry(line);
|
||||
if (entry != null) {
|
||||
@@ -65,7 +65,10 @@ public class OpenSSHKnownHosts
|
||||
}
|
||||
} catch (SSHException ignore) {
|
||||
log.debug("Bad line ({}): {} ", ignore.toString(), line);
|
||||
} catch (SSHRuntimeException ignore) {
|
||||
log.debug("Failed to process line ({}): {} ", ignore.toString(), line);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(br);
|
||||
}
|
||||
@@ -207,7 +210,7 @@ public class OpenSSHKnownHosts
|
||||
|
||||
if (type != KeyType.UNKNOWN) {
|
||||
final String sKey = split[i++];
|
||||
key = getKey(sKey);
|
||||
key = new Buffer.PlainBuffer(Base64.decode(sKey)).readPublicKey();
|
||||
} else if (isBits(sType)) {
|
||||
type = KeyType.RSA;
|
||||
// int bits = Integer.valueOf(sType);
|
||||
@@ -232,11 +235,6 @@ public class OpenSSHKnownHosts
|
||||
}
|
||||
}
|
||||
|
||||
private PublicKey getKey(String sKey)
|
||||
throws IOException {
|
||||
return new Buffer.PlainBuffer(Base64.decode(sKey)).readPublicKey();
|
||||
}
|
||||
|
||||
private boolean isBits(String type) {
|
||||
try {
|
||||
Integer.parseInt(type);
|
||||
|
||||
@@ -194,31 +194,31 @@ public class PKCS5KeyFile
|
||||
throw new FormatException("PKCS5 header not found");
|
||||
}
|
||||
ASN1Data asn = new ASN1Data(data = decrypt(Base64.decode(sb.toString()), cipher, iv));
|
||||
switch(type) {
|
||||
case RSA: {
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
asn.readNext();
|
||||
BigInteger modulus = asn.readNext();
|
||||
BigInteger pubExp = asn.readNext();
|
||||
BigInteger prvExp = asn.readNext();
|
||||
PublicKey pubKey = factory.generatePublic(new RSAPublicKeySpec(modulus, pubExp));
|
||||
PrivateKey prvKey = factory.generatePrivate(new RSAPrivateKeySpec(modulus, prvExp));
|
||||
return new KeyPair(pubKey, prvKey);
|
||||
}
|
||||
case DSA: {
|
||||
KeyFactory factory = KeyFactory.getInstance("DSA");
|
||||
asn.readNext();
|
||||
BigInteger p = asn.readNext();
|
||||
BigInteger q = asn.readNext();
|
||||
BigInteger g = asn.readNext();
|
||||
BigInteger pub = asn.readNext();
|
||||
BigInteger prv = asn.readNext();
|
||||
PublicKey pubKey = factory.generatePublic(new DSAPublicKeySpec(pub, p, q, g));
|
||||
PrivateKey prvKey = factory.generatePrivate(new DSAPrivateKeySpec(prv, p, q, g));
|
||||
return new KeyPair(pubKey, prvKey);
|
||||
}
|
||||
default:
|
||||
throw new IOException("Unrecognized PKCS5 key type: " + type);
|
||||
switch (type) {
|
||||
case RSA: {
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
asn.readNext();
|
||||
BigInteger modulus = asn.readNext();
|
||||
BigInteger pubExp = asn.readNext();
|
||||
BigInteger prvExp = asn.readNext();
|
||||
PublicKey pubKey = factory.generatePublic(new RSAPublicKeySpec(modulus, pubExp));
|
||||
PrivateKey prvKey = factory.generatePrivate(new RSAPrivateKeySpec(modulus, prvExp));
|
||||
return new KeyPair(pubKey, prvKey);
|
||||
}
|
||||
case DSA: {
|
||||
KeyFactory factory = KeyFactory.getInstance("DSA");
|
||||
asn.readNext();
|
||||
BigInteger p = asn.readNext();
|
||||
BigInteger q = asn.readNext();
|
||||
BigInteger g = asn.readNext();
|
||||
BigInteger pub = asn.readNext();
|
||||
BigInteger prv = asn.readNext();
|
||||
PublicKey pubKey = factory.generatePublic(new DSAPublicKeySpec(pub, p, q, g));
|
||||
PrivateKey prvKey = factory.generatePrivate(new DSAPrivateKeySpec(prv, p, q, g));
|
||||
return new KeyPair(pubKey, prvKey);
|
||||
}
|
||||
default:
|
||||
throw new IOException("Unrecognized PKCS5 key type: " + type);
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IOException(e);
|
||||
|
||||
Reference in New Issue
Block a user