You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2017/08/02 08:14:18 UTC

[1/4] karaf git commit: Reformat ServerKeyVerifierImpl

Repository: karaf
Updated Branches:
  refs/heads/master f75ade9f2 -> f7ea3e0cb


Reformat ServerKeyVerifierImpl


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/f7ea3e0c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/f7ea3e0c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/f7ea3e0c

Branch: refs/heads/master
Commit: f7ea3e0cb3b6d07953c3fea828cb453405d8c6db
Parents: 0bde580
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Tue Aug 1 14:51:15 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Wed Aug 2 10:14:10 2017 +0200

----------------------------------------------------------------------
 .../karaf/shell/ssh/ServerKeyVerifierImpl.java  | 105 +++++++++----------
 1 file changed, 52 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/f7ea3e0c/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
index 0d471b4..9cd3494 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
@@ -32,7 +32,7 @@ public class ServerKeyVerifierImpl implements ServerKeyVerifier {
 	private final boolean quiet;
 
     private final static String keyChangedMessage =
-            		" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
+                    " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
                     " @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!      @ \n" +
                     " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
                     "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" +
@@ -44,60 +44,59 @@ public class ServerKeyVerifierImpl implements ServerKeyVerifier {
                     "RSA host key has changed and you have requested strict checking.\n" +
                     "Host key verification failed.";
 
-	public ServerKeyVerifierImpl(KnownHostsManager knownHostsManager, boolean quiet) {
-		this.knownHostsManager = knownHostsManager;
-		this.quiet = quiet;
-	}
-
-	@Override
-	public boolean verifyServerKey(ClientSession sshClientSession,
-			SocketAddress remoteAddress, PublicKey serverKey) {
-		PublicKey knownKey;
-		try {
-			knownKey = knownHostsManager.getKnownKey(remoteAddress, serverKey.getAlgorithm());
-		} catch (InvalidKeySpecException e) {
-			System.err.println("Invalid key stored for host " + remoteAddress + ". Terminating session.");
-			return false;
-		}
-		if (knownKey == null) {
-			boolean confirm;
-			if (!quiet) {
-				System.out.println("Connecting to unknown server. Add this server to known hosts ? (y/n)");
-				confirm = getConfirmation();
-			} else {
-				System.out.println("Connecting to unknown server. Automatically adding to known hosts.");
-				confirm = true;
-			}
-			if (confirm) {
-				knownHostsManager.storeKeyForHost(remoteAddress, serverKey);
-				System.out.println("Storing the server key in known_hosts.");
-			} else {
-				System.out.println("Aborting connection");
-			}
-			return confirm;
-		}
-		
-		boolean verifed = (knownKey.equals(serverKey));
-		if (!verifed) {
-			System.err.println("Server key for host " + remoteAddress + " does not match the stored key !! Terminating session.");
-            System.err.println(keyChangedMessage);
-		}
-		return verifed;
-	}
+    public ServerKeyVerifierImpl(KnownHostsManager knownHostsManager, boolean quiet) {
+        this.knownHostsManager = knownHostsManager;
+        this.quiet = quiet;
+    }
 
-	private boolean getConfirmation() {
-		int ch;
-		try {
-			do {
-				ch = System.in.read();
-			} while (ch != 'y' && ch != 'n');
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-		boolean confirm = ch == 'y';
-		return confirm;
-	}
+    @Override
+    public boolean verifyServerKey(ClientSession sshClientSession, SocketAddress remoteAddress,
+                                   PublicKey serverKey) {
+        PublicKey knownKey;
+        try {
+            knownKey = knownHostsManager.getKnownKey(remoteAddress, serverKey.getAlgorithm());
+        } catch (InvalidKeySpecException e) {
+            System.err.println("Invalid key stored for host " + remoteAddress + ". Terminating session.");
+            return false;
+        }
+        if (knownKey == null) {
+            boolean confirm;
+            if (!quiet) {
+                System.out.println("Connecting to unknown server. Add this server to known hosts ? (y/n)");
+                confirm = getConfirmation();
+            } else {
+                System.out.println("Connecting to unknown server. Automatically adding to known hosts.");
+                confirm = true;
+            }
+            if (confirm) {
+                knownHostsManager.storeKeyForHost(remoteAddress, serverKey);
+                System.out.println("Storing the server key in known_hosts.");
+            } else {
+                System.out.println("Aborting connection");
+            }
+            return confirm;
+        }
 
+        boolean verifed = (knownKey.equals(serverKey));
+        if (!verifed) {
+            System.err.println("Server key for host " + remoteAddress
+                               + " does not match the stored key !! Terminating session.");
+            System.err.println(keyChangedMessage);
+        }
+        return verifed;
+    }
 
+    private boolean getConfirmation() {
+        int ch;
+        try {
+            do {
+                ch = System.in.read();
+            } while (ch != 'y' && ch != 'n');
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        boolean confirm = ch == 'y';
+        return confirm;
+    }
 
 }


[4/4] karaf git commit: Extract common code

Posted by cs...@apache.org.
Extract common code


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ae75feed
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ae75feed
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ae75feed

Branch: refs/heads/master
Commit: ae75feed11bab347bf7d4e6eb6d48a879189d1cf
Parents: f75ade9
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Tue Aug 1 14:32:47 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Wed Aug 2 10:14:10 2017 +0200

----------------------------------------------------------------------
 .../karaf/shell/ssh/KarafJaasAuthenticator.java | 100 +++++++------------
 1 file changed, 38 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/ae75feed/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
index 94b715c..e1420f4 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
@@ -23,6 +23,7 @@ import java.security.PublicKey;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
@@ -45,48 +46,46 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA
 
     private String realm;
 
-    public KarafJaasAuthenticator() {
-    }
-
     public KarafJaasAuthenticator(String realm) {
         this.realm = realm;
     }
 
-    public String getRealm() {
-        return realm;
+    public boolean authenticate(final String username, final String password, final ServerSession session) {
+        CallbackHandler callbackHandler = callbacks -> {
+            for (Callback callback : callbacks) {
+                if (callback instanceof NameCallback) {
+                    ((NameCallback) callback).setName(username);
+                } else if (callback instanceof PasswordCallback) {
+                    ((PasswordCallback) callback).setPassword(password.toCharArray());
+                } else {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        };
+        return doLogin(session, callbackHandler);
     }
 
-    public void setRealm(String realm) {
-        this.realm = realm;
+    public boolean authenticate(final String username, final PublicKey key, final ServerSession session) {
+        CallbackHandler callbackHandler = callbacks -> {
+            for (Callback callback : callbacks) {
+                if (callback instanceof NameCallback) {
+                    ((NameCallback) callback).setName(username);
+                } else if (callback instanceof PublickeyCallback) {
+                    ((PublickeyCallback) callback).setPublicKey(key);
+                } else {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        };
+        return doLogin(session, callbackHandler);
     }
 
-    public boolean authenticate(final String username, final String password, final ServerSession session) {
+    private boolean doLogin(final ServerSession session, CallbackHandler callbackHandler) {
         try {
             Subject subject = new Subject();
-            LoginContext loginContext = new LoginContext(realm, subject, callbacks -> {
-                for (Callback callback : callbacks) {
-                    if (callback instanceof NameCallback) {
-                        ((NameCallback) callback).setName(username);
-                    } else if (callback instanceof PasswordCallback) {
-                        ((PasswordCallback) callback).setPassword(password.toCharArray());
-                    } else {
-                        throw new UnsupportedCallbackException(callback);
-                    }
-                }
-            });
+            LoginContext loginContext = new LoginContext(realm, subject, callbackHandler);
             loginContext.login();
-
-            int roleCount = 0;
-            for (Principal principal : subject.getPrincipals()) {
-                if (principal instanceof RolePrincipal) {
-                    roleCount++;
-                }
-            }
-
-            if (roleCount == 0) {
-                throw new FailedLoginException("User doesn't have role defined");
-            }
-
+            assertRolePresent(subject);
             session.setAttribute(SUBJECT_ATTRIBUTE_KEY, subject);
             return true;
         } catch (Exception e) {
@@ -95,38 +94,15 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA
         }
     }
 
-    public boolean authenticate(final String username, final PublicKey key, final ServerSession session) {
-        try {
-            Subject subject = new Subject();
-            LoginContext loginContext = new LoginContext(realm, subject, callbacks -> {
-                for (Callback callback : callbacks) {
-                    if (callback instanceof NameCallback) {
-                        ((NameCallback) callback).setName(username);
-                    } else if (callback instanceof PublickeyCallback) {
-                        ((PublickeyCallback) callback).setPublicKey(key);
-                    } else {
-                        throw new UnsupportedCallbackException(callback);
-                    }
-                }
-            });
-            loginContext.login();
-
-            int roleCount = 0;
-            for (Principal principal : subject.getPrincipals()) {
-                if (principal instanceof RolePrincipal) {
-                    roleCount++;
-                }
-            }
-
-            if (roleCount == 0) {
-                throw new FailedLoginException("User doesn't have role defined");
+    private void assertRolePresent(Subject subject) throws FailedLoginException {
+        int roleCount = 0;
+        for (Principal principal : subject.getPrincipals()) {
+            if (principal instanceof RolePrincipal) {
+                roleCount++;
             }
-
-            session.setAttribute(SUBJECT_ATTRIBUTE_KEY, subject);
-            return true;
-        } catch (Exception e) {
-            LOGGER.debug("User authentication failed with " + e.getMessage(), e);
-            return false;
+        }
+        if (roleCount == 0) {
+            throw new FailedLoginException("User doesn't have role defined");
         }
     }
 


[3/4] karaf git commit: Handle warnings

Posted by cs...@apache.org.
Handle warnings


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/0bde5803
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/0bde5803
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/0bde5803

Branch: refs/heads/master
Commit: 0bde58036e51d560484629f4154415dc2dfaa4a9
Parents: 851dc90
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Tue Aug 1 14:48:16 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Wed Aug 2 10:14:10 2017 +0200

----------------------------------------------------------------------
 .../shell/ssh/OpenSSHGeneratorFileKeyProvider.java     |  1 -
 .../java/org/apache/karaf/shell/ssh/SshAction.java     | 13 -------------
 .../main/java/org/apache/karaf/shell/ssh/SshUtils.java |  5 -----
 3 files changed, 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/0bde5803/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/OpenSSHGeneratorFileKeyProvider.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/OpenSSHGeneratorFileKeyProvider.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/OpenSSHGeneratorFileKeyProvider.java
index 4050644..dd17314 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/OpenSSHGeneratorFileKeyProvider.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/OpenSSHGeneratorFileKeyProvider.java
@@ -30,7 +30,6 @@ import java.io.OutputStream;
 import java.nio.file.Paths;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
-import java.security.interfaces.RSAPrivateCrtKey;
 import java.util.ArrayList;
 import java.util.Collection;
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/0bde5803/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
index 8fe85b3..28add82 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
@@ -19,7 +19,6 @@
 package org.apache.karaf.shell.ssh;
 
 import java.io.ByteArrayInputStream;
-import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -36,8 +35,6 @@ import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.console.Signal;
-import org.apache.karaf.shell.api.console.SignalListener;
 import org.apache.karaf.shell.api.console.Terminal;
 import org.apache.sshd.agent.SshAgent;
 import org.apache.sshd.client.channel.ClientChannelEvent;
@@ -354,14 +351,4 @@ public class SshAction implements Action {
         return session;
     }
 
-    private void close(Closeable is) {
-        if (is != null) {
-            try {
-                is.close();
-            } catch (IOException e1) {
-                // Ignore
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/0bde5803/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
index 7985e25..5542f08 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
@@ -26,7 +26,6 @@ import org.apache.sshd.server.ServerBuilder;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.cipher.Cipher;
-import org.apache.sshd.common.compression.Compression;
 import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.mac.Mac;
 
@@ -117,10 +116,6 @@ public class SshUtils {
             return cipherFactories;
         }
 
-        public List<NamedFactory<Compression>> getCompressionFactories() {
-            return compressionFactories;
-        }
-
         public List<NamedFactory<Mac>> getMacFactories() {
             return macFactories;
         }


[2/4] karaf git commit: Reformat

Posted by cs...@apache.org.
Reformat


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/851dc904
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/851dc904
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/851dc904

Branch: refs/heads/master
Commit: 851dc904cba472fb2f5e5f8a006059dd7aead69e
Parents: ae75fee
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Tue Aug 1 14:35:18 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Wed Aug 2 10:14:10 2017 +0200

----------------------------------------------------------------------
 .../karaf/shell/ssh/KnownHostsManager.java      | 187 +++++++++----------
 1 file changed, 93 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/851dc904/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KnownHostsManager.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KnownHostsManager.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KnownHostsManager.java
index ad0ed29..2c73b6d 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KnownHostsManager.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KnownHostsManager.java
@@ -38,105 +38,104 @@ import org.slf4j.LoggerFactory;
 import java.util.Base64;
 
 public class KnownHostsManager {
-	Logger LOG = LoggerFactory.getLogger(KnownHostsManager.class);
-	
-	private final File knownHosts;
+    Logger LOG = LoggerFactory.getLogger(KnownHostsManager.class);
 
-	public KnownHostsManager(File knownHosts) {
-		this.knownHosts = knownHosts;
-		this.knownHosts.getParentFile().mkdirs();
-		if (!this.knownHosts.exists()) {
-			try {
-				knownHosts.createNewFile();
-			} catch (IOException e) {
-				throw new RuntimeException("Error creating file for known hosts at: " + knownHosts);
-			}
-		}
-	}
-	
-	public PublicKey getKnownKey(SocketAddress remoteAddress, String checkAlgorithm) throws InvalidKeySpecException {
-		FileReader fr = null;
-		BufferedReader reader = null;
-		try {
-			fr = new FileReader(knownHosts);
-			reader = new BufferedReader(fr);
-			return getKnownKeyInternal(remoteAddress, checkAlgorithm, reader);
-		} catch (IOException e) {
-			throw new RuntimeException("Error reading known_hosts " + knownHosts, e);
-		} catch (NoSuchAlgorithmException e) {
-			throw new RuntimeException(e);
-		} finally {
-			close(reader);
-			close(fr);
-		}
-	}
+    private final File knownHosts;
 
-	private PublicKey getKnownKeyInternal(SocketAddress remoteAddress,
-			String checkAlgorithm, BufferedReader reader) throws IOException,
-			NoSuchAlgorithmException, InvalidKeySpecException {
-		String checkServerAddress = getAddressString(remoteAddress);
+    public KnownHostsManager(File knownHosts) {
+        this.knownHosts = knownHosts;
+        this.knownHosts.getParentFile().mkdirs();
+        if (!this.knownHosts.exists()) {
+            try {
+                knownHosts.createNewFile();
+            } catch (IOException e) {
+                throw new RuntimeException("Error creating file for known hosts at: " + knownHosts);
+            }
+        }
+    }
 
-		String line = reader.readLine();
-		while (line != null) {
-			String[] lineParts = line.split(" ");
-			String serverAddress = lineParts[0];
-			String algorithm = lineParts[1];
-			if (checkServerAddress.equals(serverAddress) && checkAlgorithm.equals(algorithm)) {
-				byte[] key = Base64.getDecoder().decode(lineParts[2].getBytes());
-				KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
-				X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
-				return keyFactory.generatePublic(keySpec);
-			}
-			line = reader.readLine();
-		}
-		return null;
-	}
-	
-	public void storeKeyForHost(SocketAddress remoteAddress,
-			PublicKey serverKey) {
-		FileWriter ps = null;
-		BufferedWriter bw = null;
-		try {
-			ps = new FileWriter(knownHosts, true);
-			bw = new BufferedWriter(ps);
-			writeKey(bw, remoteAddress, serverKey);
-		} catch (Exception e) {
-			throw new RuntimeException("Error storing key for host" + remoteAddress, e);
-		} finally {
-			close(bw);
-			close(ps);
-		}
-	}
+    public PublicKey getKnownKey(SocketAddress remoteAddress, String checkAlgorithm)
+        throws InvalidKeySpecException {
+        FileReader fr = null;
+        BufferedReader reader = null;
+        try {
+            fr = new FileReader(knownHosts);
+            reader = new BufferedReader(fr);
+            return getKnownKeyInternal(remoteAddress, checkAlgorithm, reader);
+        } catch (IOException e) {
+            throw new RuntimeException("Error reading known_hosts " + knownHosts, e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        } finally {
+            close(reader);
+            close(fr);
+        }
+    }
 
-	private void writeKey(BufferedWriter bw, SocketAddress remoteAddress,
-			PublicKey serverKey) throws IOException {
-		bw.append(getAddressString(remoteAddress));
-		bw.append(" ");
-		bw.append(serverKey.getAlgorithm());
-		bw.append(" ");
-		serverKey.getEncoded();
-		bw.append(new String(Base64.getEncoder().encode(serverKey.getEncoded()), "UTF-8"));
+    private PublicKey getKnownKeyInternal(SocketAddress remoteAddress, String checkAlgorithm,
+                                          BufferedReader reader)
+        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
+        String checkServerAddress = getAddressString(remoteAddress);
+
+        String line = reader.readLine();
+        while (line != null) {
+            String[] lineParts = line.split(" ");
+            String serverAddress = lineParts[0];
+            String algorithm = lineParts[1];
+            if (checkServerAddress.equals(serverAddress) && checkAlgorithm.equals(algorithm)) {
+                byte[] key = Base64.getDecoder().decode(lineParts[2].getBytes());
+                KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
+                return keyFactory.generatePublic(keySpec);
+            }
+            line = reader.readLine();
+        }
+        return null;
+    }
+
+    public void storeKeyForHost(SocketAddress remoteAddress, PublicKey serverKey) {
+        FileWriter ps = null;
+        BufferedWriter bw = null;
+        try {
+            ps = new FileWriter(knownHosts, true);
+            bw = new BufferedWriter(ps);
+            writeKey(bw, remoteAddress, serverKey);
+        } catch (Exception e) {
+            throw new RuntimeException("Error storing key for host" + remoteAddress, e);
+        } finally {
+            close(bw);
+            close(ps);
+        }
+    }
+
+    private void writeKey(BufferedWriter bw, SocketAddress remoteAddress, PublicKey serverKey)
+        throws IOException {
+        bw.append(getAddressString(remoteAddress));
+        bw.append(" ");
+        bw.append(serverKey.getAlgorithm());
+        bw.append(" ");
+        serverKey.getEncoded();
+        bw.append(new String(Base64.getEncoder().encode(serverKey.getEncoded()), "UTF-8"));
         bw.append("\n");
-	}
+    }
+
+    String getAddressString(SocketAddress address) {
+        if (address instanceof InetSocketAddress) {
+            InetSocketAddress inetAddress = (InetSocketAddress)address;
+            return String.format("%s,%s:%s", inetAddress.getHostName(),
+                                 inetAddress.getAddress().getHostAddress(), inetAddress.getPort());
+        }
+        return "";
+    }
 
-	String getAddressString(SocketAddress address) {
-		if (address instanceof InetSocketAddress) {
-			InetSocketAddress inetAddress = (InetSocketAddress) address;
-			return String.format("%s,%s:%s", inetAddress.getHostName(),
-					inetAddress.getAddress().getHostAddress(),
-					inetAddress.getPort());
-		}
-		return "";
-	}
-	
-	private void close(Closeable closeable) {
-		if (closeable != null) {
-			try {
-				closeable.close();
-			} catch (IOException e) {
-				LOG.warn("Error closing: " + e.getMessage(), e);
-			}
-		}
-	}
+    private void close(Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                LOG.warn("Error closing: " + e.getMessage(), e);
+            }
+        }
+    }
 
 }