Mercurial > 510Connectbot
annotate src/com/five_ten_sg/connectbot/service/AuthAgentService.java @ 313:1d400fd78e4a ganymed
add ecdsa key support everywhere
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 30 Jul 2014 16:19:33 -0700 |
parents | c1f929cb3dd0 |
children | b40bc65fa09a |
rev | line source |
---|---|
0 | 1 package com.five_ten_sg.connectbot.service; |
2 | |
3 import java.io.IOException; | |
4 import java.security.SecureRandom; | |
5 import java.security.KeyPair; | |
6 import java.security.PrivateKey; | |
7 import java.security.PublicKey; | |
8 import java.security.interfaces.DSAPrivateKey; | |
9 import java.security.interfaces.DSAPublicKey; | |
10 import java.security.interfaces.ECPrivateKey; | |
11 import java.security.interfaces.ECPublicKey; | |
12 import java.security.interfaces.RSAPrivateKey; | |
13 import java.security.interfaces.RSAPublicKey; | |
14 import java.util.HashMap; | |
15 import java.util.Map; | |
16 import java.util.Map.Entry; | |
17 import java.util.concurrent.locks.Condition; | |
18 import java.util.concurrent.locks.Lock; | |
19 import java.util.concurrent.locks.ReentrantLock; | |
20 | |
21 import com.five_ten_sg.connectbot.service.TerminalManager; | |
22 import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; | |
23 import android.app.Service; | |
24 import android.content.ComponentName; | |
25 import android.content.Intent; | |
26 import android.content.ServiceConnection; | |
27 import android.os.IBinder; | |
28 import android.os.RemoteException; | |
29 import android.util.Log; | |
30 | |
31 import com.madgag.ssh.android.authagent.AndroidAuthAgent; | |
273
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
32 import ch.ethz.ssh2.signature.DSASHA1Verify; |
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
33 import ch.ethz.ssh2.signature.ECDSASHA2Verify; |
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
34 import ch.ethz.ssh2.signature.RSASHA1Verify; |
0 | 35 |
36 public class AuthAgentService extends Service { | |
37 private static final String TAG = "ConnectBot.AuthAgentService"; | |
38 protected TerminalManager manager; | |
39 final Lock lock = new ReentrantLock(); | |
40 final Condition managerReady = lock.newCondition(); | |
41 | |
42 private ServiceConnection connection = new ServiceConnection() { | |
43 public void onServiceConnected(ComponentName className, IBinder service) { | |
44 Log.d(TAG, "Terminal manager available! Hurrah"); | |
45 manager = ((TerminalManager.TerminalBinder) service).getService(); | |
46 lock.lock(); | |
47 | |
48 try { | |
49 managerReady.signal(); | |
50 } | |
51 finally { | |
52 lock.unlock(); | |
53 } | |
54 } | |
55 public void onServiceDisconnected(ComponentName className) { | |
56 manager = null; | |
57 Log.d(TAG, "Terminal manager gone..."); | |
58 } | |
59 }; | |
60 | |
61 @Override | |
62 public IBinder onBind(Intent intent) { | |
63 Log.d(TAG, "onBind() called"); | |
64 bindService(new Intent(this, TerminalManager.class), connection, BIND_AUTO_CREATE); | |
65 return mBinder; | |
66 } | |
67 | |
68 private final AndroidAuthAgent.Stub mBinder = new AndroidAuthAgent.Stub() { | |
69 public Map getIdentities() throws RemoteException { | |
70 Log.d(TAG, "getIdentities() called"); | |
71 waitForTerminalManager(); | |
72 Log.d(TAG, "getIdentities() manager.loadedKeypairs : " + manager.loadedKeypairs); | |
73 return sshEncodedPubKeysFrom(manager.loadedKeypairs); | |
74 } | |
75 public byte[] sign(byte[] publicKey, byte[] data) throws RemoteException { | |
76 Log.d(TAG, "sign() called"); | |
77 waitForTerminalManager(); | |
78 KeyPair pair = keyPairFor(publicKey); | |
79 Log.d(TAG, "sign() - signing keypair found : " + pair); | |
80 | |
81 if (pair == null) { | |
82 return null; | |
83 } | |
84 | |
85 PrivateKey privKey = pair.getPrivate(); | |
86 | |
87 if (privKey instanceof RSAPrivateKey) { | |
88 return sshEncodedSignatureFor(data, (RSAPrivateKey) privKey); | |
89 } | |
90 else if (privKey instanceof DSAPrivateKey) { | |
91 return sshEncodedSignatureFor(data, (DSAPrivateKey) privKey); | |
92 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
93 else if (privKey instanceof ECPrivateKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
94 return sshEncodedSignatureFor(data, (ECPrivateKey) privKey); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
95 } |
0 | 96 |
97 return null; | |
98 } | |
99 private void waitForTerminalManager() throws RemoteException { | |
100 lock.lock(); | |
101 | |
102 try { | |
103 while (manager == null) { | |
104 Log.d(TAG, "Waiting for TerminalManager..."); | |
105 managerReady.await(); | |
106 } | |
107 } | |
108 catch (InterruptedException e) { | |
109 throw new RemoteException(); | |
110 } | |
111 finally { | |
112 lock.unlock(); | |
113 } | |
114 | |
115 Log.d(TAG, "Got TerminalManager : " + manager); | |
116 } | |
117 private Map<String, byte[]> sshEncodedPubKeysFrom(Map<String, KeyHolder> keypairs) { | |
118 Map<String, byte[]> pubkeys = new HashMap<String, byte[]> (keypairs.size()); | |
119 | |
120 for (Entry<String, KeyHolder> entry : keypairs.entrySet()) { | |
121 byte[] encodedKey = sshEncodedPubKeyFrom(entry.getValue().pair); | |
122 | |
123 if (encodedKey != null) { | |
124 pubkeys.put(entry.getKey(), encodedKey); | |
125 } | |
126 } | |
127 | |
128 return pubkeys; | |
129 } | |
130 private byte[] sshEncodedPubKeyFrom(KeyPair pair) { | |
131 try { | |
132 PrivateKey privKey = pair.getPrivate(); | |
133 | |
134 if (privKey instanceof RSAPrivateKey) { | |
135 RSAPublicKey pubkey = (RSAPublicKey)pair.getPublic(); | |
136 return RSASHA1Verify.encodeSSHRSAPublicKey(pubkey); | |
137 } | |
138 else if (privKey instanceof DSAPrivateKey) { | |
139 DSAPublicKey pubkey = (DSAPublicKey)pair.getPublic(); | |
140 return DSASHA1Verify.encodeSSHDSAPublicKey(pubkey); | |
141 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
142 else if (privKey instanceof ECPrivateKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
143 ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
144 return ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
145 } |
0 | 146 } |
147 catch (IOException e) { | |
148 Log.e(TAG, "Couldn't encode " + pair, e); | |
149 } | |
150 | |
151 return null; | |
152 } | |
153 private byte[] sshEncodedSignatureFor(byte[] data, RSAPrivateKey privKey) { | |
154 try { | |
155 byte[] signature = RSASHA1Verify.generateSignature(data, privKey); | |
156 return RSASHA1Verify.encodeSSHRSASignature(signature); | |
157 } | |
158 catch (IOException e) { | |
159 throw new RuntimeException(e); | |
160 } | |
161 } | |
162 private byte[] sshEncodedSignatureFor(byte[] data, DSAPrivateKey privKey) { | |
163 try { | |
164 byte[] signature = DSASHA1Verify.generateSignature(data, privKey, new SecureRandom()); | |
165 return DSASHA1Verify.encodeSSHDSASignature(signature); | |
166 } | |
167 catch (IOException e) { | |
168 throw new RuntimeException(e); | |
169 } | |
170 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
171 private byte[] sshEncodedSignatureFor(byte[] data, ECPrivateKey privKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
172 try { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
173 byte[] signature = ECDSASHA2Verify.generateSignature(data, privKey); |
297
c1f929cb3dd0
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
296
diff
changeset
|
174 return ECDSASHA2Verify.encodeSSHECDSASignature(signature, privKey.getParams()); |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
175 } |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
176 catch (IOException e) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
177 throw new RuntimeException(e); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
178 } |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
179 } |
0 | 180 private KeyPair keyPairFor(byte[] publicKey) { |
181 String nickname = manager.getKeyNickname(publicKey); | |
182 | |
183 if (nickname == null) { | |
184 Log.w(TAG, "No key-pair found for public-key."); | |
185 return null; | |
186 } | |
187 | |
188 // check manager.loadedKeypairs.get(nickname).bean.isConfirmUse() and promptForPubkeyUse(nickname) ? | |
189 return manager.getKey(nickname); | |
190 } | |
191 }; | |
192 } |