Generate base64 encoded client challenge
This commit is contained in:
parent
779fb6dc43
commit
64a12a816f
@ -9,6 +9,7 @@ import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import dslab.ComponentFactory;
|
||||
@ -16,6 +17,7 @@ import dslab.util.Config;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class MessageClient implements IMessageClient, Runnable {
|
||||
private static final Logger logger = Logger.getLogger(MessageClient.class.getName());
|
||||
@ -38,6 +40,8 @@ public class MessageClient implements IMessageClient, Runnable {
|
||||
private PrintWriter dmapOut;
|
||||
private BufferedReader dmapIn;
|
||||
|
||||
private Cipher aesCipher;
|
||||
|
||||
/**
|
||||
* Creates a new client instance.
|
||||
*
|
||||
@ -80,7 +84,6 @@ public class MessageClient implements IMessageClient, Runnable {
|
||||
logger.severe("Could not connect to MailboxHost " + this.mailboxHost + " on port " + this.mailboxPort);
|
||||
shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void startSecure() throws IOException {
|
||||
@ -94,8 +97,8 @@ public class MessageClient implements IMessageClient, Runnable {
|
||||
componentId = input.split("\\s+")[1];
|
||||
try {
|
||||
// Attempt to read server public key from file called <component-id>_pub.der
|
||||
byte[] keyBytes = Files.readAllBytes(Paths.get(componentId + "_pub.der"));
|
||||
logger.info("Read bytes from path " + Paths.get(componentId + ".der") + ": " + Arrays.toString(keyBytes));
|
||||
byte[] keyBytes = Files.readAllBytes(Paths.get("keys", "client", componentId + "_pub.der"));
|
||||
logger.info("Read bytes from path " + Paths.get("keys", "client", componentId + "_pub.der") + ": " + Arrays.toString(keyBytes));
|
||||
// Create X509 spec object from key
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
|
||||
// Create generator for RSA scheme
|
||||
@ -103,7 +106,7 @@ public class MessageClient implements IMessageClient, Runnable {
|
||||
// Make generator generate public key from X509 spec
|
||||
serverPublicKey = kf.generatePublic(spec);
|
||||
logger.info("Server's Public Key: " + serverPublicKey);
|
||||
String clientChallenge = generateChallenge(serverPublicKey);
|
||||
String clientChallenge = generateChallengeMessage(serverPublicKey);
|
||||
// TODO send clientChallenge to server
|
||||
// TODO Receive AES encrypted message saying "ok <client-challenge>"
|
||||
// TODO Compare received client challenge with generated client challenge
|
||||
@ -116,39 +119,80 @@ public class MessageClient implements IMessageClient, Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKey generateSecretKey() throws NoSuchAlgorithmException {
|
||||
private SecretKeySpec generateSecretKey() {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(256);
|
||||
return keyGenerator.generateKey();
|
||||
keyGenerator.init(256, SecureRandom.getInstanceStrong());
|
||||
return new SecretKeySpec(keyGenerator.generateKey().getEncoded(), "AES");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.severe("This should not be happening!");
|
||||
e.printStackTrace();
|
||||
shutdown();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[] generateIv() {
|
||||
private IvParameterSpec generateIv() {
|
||||
// Size of IV corresponds to AES block size (=128bits=16bytes)
|
||||
byte[] iv = new byte[16];
|
||||
new SecureRandom().nextBytes(iv);
|
||||
return new IvParameterSpec(iv).getIV();
|
||||
return new IvParameterSpec(iv);
|
||||
}
|
||||
|
||||
private String generateChallenge(PublicKey serverPublicKey) {
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
private void setAesCipher(SecretKeySpec secretKey, IvParameterSpec iv) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, serverPublicKey);
|
||||
this.aesCipher = Cipher.getInstance("AES/CTR/NoPadding");
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
logger.severe("This should not be happening!");
|
||||
e.printStackTrace();
|
||||
shutdown();
|
||||
}
|
||||
|
||||
try {
|
||||
this.aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||
logger.severe("This should not be happening!");
|
||||
e.printStackTrace();
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] generateChallenge(PublicKey serverPublicKey) {
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
// Generate new random 32 byte challenge
|
||||
byte[] clearTextChallenge = new byte[32];
|
||||
secureRandom.nextBytes(clearTextChallenge);
|
||||
// Generate secretKey and initialization vector
|
||||
String secretKey = "";
|
||||
String IV = "";
|
||||
// Encrypt "ok <clearTextChallenge> <secretKey> <IV>"
|
||||
cipher.update(("ok " + (new String(clearTextChallenge)) + " " + secretKey + " " + IV).getBytes(StandardCharsets.UTF_8));
|
||||
return clearTextChallenge;
|
||||
}
|
||||
|
||||
private String generateChallengeMessage(PublicKey serverPublicKey) {
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
byte[] clearTextChallenge = generateChallenge(serverPublicKey);
|
||||
SecretKeySpec secretKeySpec = generateSecretKey();
|
||||
assert secretKeySpec != null;
|
||||
IvParameterSpec iv = generateIv();
|
||||
// Save AES cipher for subsequent communication
|
||||
setAesCipher(secretKeySpec, iv);
|
||||
// Concatenate challenge, secretKey and IV
|
||||
byte[] concatenated = new byte[80];
|
||||
System.arraycopy(clearTextChallenge, 0, concatenated, 0, 32);
|
||||
System.arraycopy(secretKeySpec.getEncoded(), 0, concatenated, 32, 32);
|
||||
System.arraycopy(iv.getIV(), 0, concatenated, 64, 16);
|
||||
String base64Encoded = Base64.getEncoder().encodeToString(concatenated);
|
||||
// Encrypt "ok <base64Encoded>"
|
||||
Cipher cipher = null;
|
||||
try {
|
||||
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, serverPublicKey);
|
||||
cipher.update(("ok " + base64Encoded).getBytes(StandardCharsets.UTF_8));
|
||||
byte[] cipherTextChallenge = cipher.doFinal();
|
||||
return (new String(cipherTextChallenge, StandardCharsets.UTF_8));
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
|
||||
logger.severe(e.getMessage());
|
||||
logger.severe("This should not be happening!");
|
||||
e.printStackTrace();
|
||||
shutdown();
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user