James Moger
2014-03-22 bcc8a015ae552726742b4f437b2cb9e809270f96
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.gitblit.transport.ssh;
 
import java.io.Serializable;
import java.security.PublicKey;
 
import org.apache.commons.codec.binary.Base64;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.util.Buffer;
import org.eclipse.jgit.lib.Constants;
 
import com.gitblit.utils.StringUtils;
 
/**
 * Class that encapsulates a public SSH key and it's metadata.
 *
 * @author James Moger
 *
 */
public class SshKey implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    private String rawData;
 
    private PublicKey publicKey;
 
    private String comment;
 
    private String fingerprint;
 
    public SshKey(String data) {
        this.rawData = data;
    }
 
    public SshKey(PublicKey key) {
        this.publicKey = key;
        this.comment = "";
    }
 
    public PublicKey getPublicKey() {
        if (publicKey == null && rawData != null) {
            // instantiate the public key from the raw key data
            final String[] parts = rawData.split(" ", 3);
            if (comment == null && parts.length == 3) {
                comment = parts[2];
            }
            final byte[] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1]));
            try {
                publicKey = new Buffer(bin).getRawPublicKey();
            } catch (SshException e) {
                e.printStackTrace();
            }
        }
        return publicKey;
    }
 
    public String getAlgorithm() {
        return getPublicKey().getAlgorithm();
    }
 
    public String getComment() {
        if (comment == null && rawData != null) {
            // extract comment from the raw data
            final String[] parts = rawData.split(" ", 3);
            if (parts.length == 3) {
                comment = parts[2];
            }
        }
        return comment;
    }
 
    public void setComment(String comment) {
        this.comment = comment;
    }
 
    public String getRawData() {
        if (rawData == null && publicKey != null) {
            // build the raw data manually from the public key
            Buffer buf = new Buffer();
 
            // 1: identify the algorithm
            buf.putRawPublicKey(publicKey);
            String alg = buf.getString();
 
            // 2: encode the key
            buf.clear();
            buf.putPublicKey(publicKey);
            String b64 = Base64.encodeBase64String(buf.getBytes());
 
            String c = getComment();
            rawData = alg + " " + b64 + (StringUtils.isEmpty(c) ? "" : (" " + c));
        }
        return rawData;
    }
 
    public String getFingerprint() {
        if (fingerprint == null) {
            StringBuilder sb = new StringBuilder();
            // TODO append the keysize
            int keySize = 0;
            if (keySize > 0) {
                sb.append(keySize).append(' ');
            }
 
            // append the key hash as colon-separated pairs
            String hash;
            if (rawData != null) {
                final String[] parts = rawData.split(" ", 3);
                final byte [] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1]));
                hash = StringUtils.getMD5(bin);
            } else {
                // TODO get hash from publickey
                hash = "todo";
            }
            for (int i = 0; i < hash.length(); i += 2) {
                sb.append(hash.charAt(i)).append(hash.charAt(i + 1)).append(':');
            }
            sb.setLength(sb.length() - 1);
 
            // append the comment
            String c = getComment();
            if (!StringUtils.isEmpty(c)) {
                sb.append(' ');
                sb.append(c);
            }
 
            // append the algorithm
            String alg = getAlgorithm();
            if (!StringUtils.isEmpty(alg)) {
                sb.append(" (").append(alg).append(")");
            }
            fingerprint = sb.toString();
        }
        return fingerprint;
    }
 
    @Override
    public boolean equals(Object o) {
        if (o instanceof PublicKey) {
            return getPublicKey().equals(o);
        } else if (o instanceof SshKey) {
            return getPublicKey().equals(((SshKey) o).getPublicKey());
        }
        return false;
    }
 
    @Override
    public int hashCode() {
        return getPublicKey().hashCode();
    }
 
    @Override
    public String toString() {
        return getFingerprint();
    }
}