package sslify;

import com.google.common.base.CharMatcher;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

public class SshPublicKey {
    public static final String SSH_RSA_PREFIX = "ssh-rsa";

    enum Type {RSA}

    private Type type;
    private PublicKey key;
    private String comment;
    private String fingerprint;

    public Type getType() {
        return type;
    }

    public PublicKey getKey() {
        return key;
    }

    public String getComment() {
        return comment;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("type", type).add("fingerprint", fingerprint).add("comment", comment).toString();
    }

    private static BigInteger readMPInt(ByteArrayDataInput source) {
        int length = source.readInt();
        byte[] dest = new byte[length];
        source.readFully(dest, 0, length);
        return new BigInteger(dest);
    }

    private static String readString(ByteArrayDataInput source) {
        int length = source.readInt();
        byte[] dest = new byte[length];
        source.readFully(dest, 0, length);
        return new String(dest);
    }

    public SshPublicKey(String description) throws InvalidKeySpecException, NoSuchAlgorithmException {
        String[] parts = Iterables.toArray(Splitter.on(CharMatcher.JAVA_WHITESPACE).split(description), String.class);
        String encoded_key;

        if (parts.length == 1) {
            comment = "no comment";
            encoded_key = description;
        } else if (parts.length == 3) {
            comment = parts[2];
            encoded_key = parts[1];
        } else {
            throw new IllegalStateException("Key format is unreadable");
        }

        byte[] decoded_key = Base64.decodeBase64(encoded_key);

        MessageDigest sha1dg = MessageDigest.getInstance("SHA-1");
        sha1dg.update(decoded_key);
        fingerprint = new BigInteger(sha1dg.digest()).toString(16);

        final ByteArrayDataInput keyInput = ByteStreams.newDataInput(decoded_key);
        final String type_string = readString(keyInput);

        if (!type_string.equals(SSH_RSA_PREFIX)) {
            throw new IllegalStateException("Not an RSA key");
        } else {
            type = Type.RSA;
            final BigInteger exp = readMPInt(keyInput);
            final BigInteger mod = readMPInt(keyInput);
            key = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(mod, exp));
        }
    }

    static SshPublicKey fromRepo(String name) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        return FSDataSource.getInstance().getSshPublicKey(name);
    }
}

@@ -651,61 +651,477 @@
    p
-ublic static final String SSH_RSA_PREFIX = %22ssh-rsa%22;
+rivate static final String NO_COMMENT_AVAILABLE = %22unavailable%22;%0A    public static final String SSH_RSA_PREFIX = %22ssh-rsa%22;%0A%0A    public static class UnreadableKey extends IllegalStateException %7B%0A        final public static String INVALID_FORMAT = %22Invalid format%22;%0A        final public static String INVALID_KEY_TYPE = %22Invalid key type%22;%0A%0A        public UnreadableKey(final String s) %7B%0A            super(s);%0A        %7D%0A%0A        private UnreadableKey() %7B%0A        %7D%0A    %7D
 %0A%0A  
@@ -1651,16 +1651,22 @@
 adMPInt(
+final 
 ByteArra
@@ -1686,32 +1686,38 @@
 urce) %7B%0A        
+final 
 int length = sou
@@ -1731,32 +1731,38 @@
 dInt();%0A        
+final 
 byte%5B%5D dest = ne
@@ -1901,16 +1901,22 @@
 dString(
+final 
 ByteArra
@@ -1944,16 +1944,22 @@
         
+final 
 int leng
@@ -1981,32 +1981,38 @@
 dInt();%0A        
+final 
 byte%5B%5D dest = ne
@@ -2134,16 +2134,22 @@
 blicKey(
+final 
 String d
@@ -2208,32 +2208,47 @@
 gorithmException
+, UnreadableKey
  %7B%0A        Strin
@@ -2238,24 +2238,30 @@
 y %7B%0A        
+final 
 String%5B%5D par
@@ -2447,20 +2447,28 @@
 t = 
-%22no comment%22
+NO_COMMENT_AVAILABLE
 ;%0A  
@@ -2655,56 +2655,50 @@
 new 
-IllegalStateException(%22Key format is unreadable%22
+UnreadableKey(UnreadableKey.INVALID_FORMAT
 );%0A 
@@ -3161,46 +3161,52 @@
 new 
-IllegalStateException(%22Not an RSA key%22
+UnreadableKey(UnreadableKey.INVALID_KEY_TYPE
 );%0A 

clean ups here and there, new exception