tls-psk: second steps
This commit is contained in:
@@ -22,19 +22,19 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.net.PskKeyManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Base64;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@@ -42,7 +42,6 @@ import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
@@ -50,9 +49,8 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
@RequiresApi(api = VERSION_CODES.LOLLIPOP)
|
||||
public class KeyTransferClientInteractor {
|
||||
private static final int SHOW_CONNECTION_DETAILS = 1;
|
||||
private static final int CONNECTION_ESTABLISHED = 2;
|
||||
public static final int CONNECTION_LOST = 3;
|
||||
private static final int CONNECTION_LOST = 3;
|
||||
|
||||
|
||||
private Thread socketThread;
|
||||
@@ -64,6 +62,11 @@ public class KeyTransferClientInteractor {
|
||||
public void connectToServer(final String connectionDetails, KeyTransferClientCallback callback) {
|
||||
this.callback = callback;
|
||||
|
||||
Uri uri = Uri.parse(connectionDetails);
|
||||
final byte[] presharedKey = Base64.decode(uri.getUserInfo(), Base64.URL_SAFE | Base64.NO_PADDING);
|
||||
final String host = uri.getHost();
|
||||
final int port = uri.getPort();
|
||||
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
socketThread = new Thread() {
|
||||
@Override
|
||||
@@ -72,13 +75,10 @@ public class KeyTransferClientInteractor {
|
||||
Socket socket = null;
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
int port = 1336;
|
||||
|
||||
PKM pskKeyManager = new PKM();
|
||||
SSLContext sslContext = null;
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
PKM pskKeyManager = new PKM(presharedKey);
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(new KeyManager[] { pskKeyManager }, new TrustManager[0], null);
|
||||
socket = sslContext.getSocketFactory().createSocket(InetAddress.getByName(connectionDetails), port);
|
||||
socket = sslContext.getSocketFactory().createSocket(InetAddress.getByName(host), port);
|
||||
|
||||
invokeListener(CONNECTION_ESTABLISHED, socket.getInetAddress().toString());
|
||||
|
||||
@@ -169,14 +169,20 @@ public class KeyTransferClientInteractor {
|
||||
}
|
||||
|
||||
private static class PKM extends PskKeyManager implements KeyManager {
|
||||
byte[] presharedKey;
|
||||
|
||||
private PKM(byte[] presharedKey) {
|
||||
this.presharedKey = presharedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey getKey(String identityHint, String identity, Socket socket) {
|
||||
return new SecretKeySpec("swag".getBytes(), "AES");
|
||||
return new SecretKeySpec(presharedKey, "AES");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
|
||||
return new SecretKeySpec("swag".getBytes(), "AES");
|
||||
return new SecretKeySpec(presharedKey, "AES");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,6 +37,7 @@ import android.os.Build.VERSION_CODES;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Base64;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@@ -72,16 +75,20 @@ public class KeyTransferServerInteractor {
|
||||
try {
|
||||
int port = 1336;
|
||||
|
||||
PKM pskKeyManager = new PKM();
|
||||
byte[] presharedKey = generatePresharedKey();
|
||||
PKM pskKeyManager = new PKM(presharedKey);
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(new KeyManager[] { pskKeyManager }, new TrustManager[0], null);
|
||||
serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(port);
|
||||
|
||||
String qrCodeData = getIPAddress(true) + ":" + port + ":" + "swag";
|
||||
String presharedKeyEncoded = Base64.encodeToString(presharedKey, Base64.URL_SAFE | Base64.NO_PADDING);
|
||||
String qrCodeData = presharedKeyEncoded + "@" + getIPAddress(true) + ":" + port;
|
||||
invokeListener(SHOW_CONNECTION_DETAILS, qrCodeData);
|
||||
|
||||
socket = serverSocket.accept();
|
||||
invokeListener(CONNECTION_ESTABLISHED, socket.getInetAddress().toString());
|
||||
Arrays.fill(presharedKey, (byte) 0);
|
||||
|
||||
socket.setSoTimeout(500);
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
@@ -130,6 +137,12 @@ public class KeyTransferServerInteractor {
|
||||
socketThread.start();
|
||||
}
|
||||
|
||||
public byte[] generatePresharedKey() {
|
||||
byte[] presharedKey = new byte[16];
|
||||
new SecureRandom().nextBytes(presharedKey);
|
||||
return presharedKey;
|
||||
}
|
||||
|
||||
public void stopServer() {
|
||||
if (socketThread != null) {
|
||||
socketThread.interrupt();
|
||||
@@ -156,6 +169,9 @@ public class KeyTransferServerInteractor {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
switch (method) {
|
||||
case SHOW_CONNECTION_DETAILS:
|
||||
callback.onServerStarted(arg);
|
||||
@@ -216,14 +232,20 @@ public class KeyTransferServerInteractor {
|
||||
}
|
||||
|
||||
private static class PKM extends PskKeyManager implements KeyManager {
|
||||
byte[] presharedKey;
|
||||
|
||||
private PKM(byte[] presharedKey) {
|
||||
this.presharedKey = presharedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey getKey(String identityHint, String identity, Socket socket) {
|
||||
return new SecretKeySpec("swag".getBytes(), "AES");
|
||||
return new SecretKeySpec(presharedKey, "AES");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
|
||||
return new SecretKeySpec("swag".getBytes(), "AES");
|
||||
return new SecretKeySpec(presharedKey, "AES");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,12 @@ public class TransferPresenter implements KeyTransferServerCallback, KeyTransfer
|
||||
public void onClickScan() {
|
||||
clearConnections();
|
||||
|
||||
view.scanQrCode();
|
||||
}
|
||||
|
||||
public void onQrCodeScanned(String qrCodeContent) {
|
||||
keyTransferClientInteractor = new KeyTransferClientInteractor();
|
||||
keyTransferClientInteractor.connectToServer("10.100.40.126", this);
|
||||
keyTransferClientInteractor.connectToServer(qrCodeContent, this);
|
||||
}
|
||||
|
||||
private void clearConnections() {
|
||||
@@ -73,7 +77,7 @@ public class TransferPresenter implements KeyTransferServerCallback, KeyTransfer
|
||||
|
||||
@Override
|
||||
public void onServerStarted(String qrCodeData) {
|
||||
Bitmap qrCodeBitmap = QrCodeUtils.getQRCodeBitmap(Uri.parse("pgp+transfer:" + qrCodeData), 0);
|
||||
Bitmap qrCodeBitmap = QrCodeUtils.getQRCodeBitmap(Uri.parse("pgp+transfer://" + qrCodeData));
|
||||
view.setQrImage(qrCodeBitmap);
|
||||
}
|
||||
|
||||
@@ -93,5 +97,7 @@ public class TransferPresenter implements KeyTransferServerCallback, KeyTransfer
|
||||
void showWaitingForConnection();
|
||||
|
||||
void setQrImage(Bitmap qrCode);
|
||||
|
||||
void scanQrCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package org.sufficientlysecure.keychain.ui.transfer.view;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
@@ -33,7 +35,9 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewAnimator;
|
||||
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.QrCodeCaptureActivity;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.TransferMvpView;
|
||||
|
||||
@@ -42,10 +46,10 @@ import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.T
|
||||
public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
public static final int VIEW_WAITING = 0;
|
||||
public static final int VIEW_CONNECTED = 1;
|
||||
public static final int REQUEST_CODE_SCAN = 1;
|
||||
|
||||
|
||||
private ImageView vQrCodeImage;
|
||||
private View vScanButton;
|
||||
private TransferPresenter presenter;
|
||||
private ViewAnimator vTransferAnimator;
|
||||
private TextView vConnectionStatusText;
|
||||
@@ -60,8 +64,8 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
vConnectionStatusText = (TextView) view.findViewById(R.id.connection_status);
|
||||
|
||||
vQrCodeImage = (ImageView) view.findViewById(R.id.qr_code_image);
|
||||
vScanButton = view.findViewById(R.id.button_scan);
|
||||
vScanButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
view.findViewById(R.id.button_scan).setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (presenter != null) {
|
||||
@@ -121,4 +125,24 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
});
|
||||
vQrCodeImage.requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scanQrCode() {
|
||||
Intent intent = new Intent(getActivity(), QrCodeCaptureActivity.class);
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_SCAN:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String qrCodeData = data.getStringExtra(Intents.Scan.RESULT);
|
||||
presenter.onQrCodeScanned(qrCodeData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ import java.util.Locale;
|
||||
*/
|
||||
public class QrCodeUtils {
|
||||
|
||||
public static Bitmap getQRCodeBitmap(final Uri uri) {
|
||||
return getQRCodeBitmap(uri.toString(), 0);
|
||||
}
|
||||
|
||||
public static Bitmap getQRCodeBitmap(final Uri uri, final int size) {
|
||||
// for URIs we want alphanumeric encoding to save space, thus make everything upper case!
|
||||
// zxing will then select Mode.ALPHANUMERIC internally
|
||||
|
||||
Reference in New Issue
Block a user