tls-psk: second steps

This commit is contained in:
Vincent Breitmoser
2017-05-29 23:56:30 +02:00
parent a55445f5bb
commit 9b3dd27ffd
5 changed files with 85 additions and 23 deletions

View File

@@ -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");
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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