/**
* Copyright (c) 2014 Matthias Jaenicke <matthias.jaenicke@student.kit.edu>,
* Matthias Plappert <undkc@student.kit.edu>,
* Julien Duman <uncyc@student.kit.edu>,
* Christian Dreher <uaeef@student.kit.edu>,
* Wasilij Beskorovajnov <uajkm@student.kit.edu> and
* Aydin Tekin <aydin.tekin@student.kit.edu>
*
* Released under the MIT license (refer to LICENSE.md)
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package edu.kit.iks.Cryptographics.DiffieHellman.Experiment;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.xnap.commons.i18n.I18n;
import edu.kit.iks.CryptographicsLib.Configuration;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.ColorChannel;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.ColorChooser;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.ColorMix;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.LabelExplanation;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.Navigation;
import edu.kit.iks.Cryptographics.DiffieHellman.Demonstration.NextStepCallback;
public class DHExperimentView extends JPanel {
/**
* Localization instance
*/
private static I18n i18n = Configuration.getInstance().getI18n(DHExperimentView.class);
private static final long serialVersionUID = 5764374133753732451L;
private String explanation1 = i18n.tr("Now it is your turn! Choose a public color, which " +
"will be the basis for the coming operations. When you're are done, " +
"click the 'send color' button to send it to Bob.");
private String explanation2 = i18n.tr("Now you can choose a private color which you can mix with the " +
"public color you previously send to Bob. When you're done, click " +
"the 'Mix with public color' button.");
private String explanation3 = i18n.tr("The next step is to send the right color to Bob, as " +
"shown in the demonstration. You have three possible colors to send and " +
"one is the right color. If you need help click the 'Help' button.");
private String wrongPrivate = i18n.tr("Oh no. You chose the private color. This color " +
"is meant to be private. If you had sent this color, Eve would be able " +
"to get the secret too, afterwards. " +
"Please try again, by choosing another color and clicking " +
"the 'send color' button.");
private String wrongPublic = i18n.tr("Oh no. You chose the public color. While Eve " +
"won't be able to get the secret shared color, you still didn't follow " +
"the protocol instructions. Try again by choosing another color.");
private String rightColor = i18n.tr("Good. You sent your mixture to Bob. This is " +
"the right choice.");
private String bobsTurn = i18n.tr("Now it is Bobs turn. Click the continue button, so that " +
"Bob will choose his private color and send you his mixture.");
private String finalSecret = i18n.tr("This is the last step in the protocol. " +
"Choose the right colors to produce the final secret, just like " +
"how it was explained at the demonstration.");
private String congrats = i18n.tr("Congratulations, you chose the right colors to mix, " +
"you and Bob established a shared secret that Eve does not know.");
/*
* the current help String
*/
private String help;
private String help1 = i18n.tr("You have to choose a public color, " +
"to choose a different color you have to click the '->' or " +
"'<-' Button. You can't do much wrong. When you are ready " +
"click the 'send color' button.");
private String help2 = i18n.tr("You have to choose a private color, which " +
"is not the same as the public color. To choose a color, " +
"you have to click the '->' or the '<-' Button. You can't do " +
"much wrong. When you are ready, click the 'mix colors' button.");
private String help3 = i18n.tr("You have to send the right color, the right color is the " +
"one you have not already sent, and the one you don't want to keep private. " +
"If you still have no clue, try the three different colors.");
private String help4 = i18n.tr("Just click the continue button and Bob will mix his color " +
"and will send it to you.");
private String help5 = i18n.tr("You have to choose the two colors that will be mixed to " +
"the final shared secret. Tip: Why can't Eve compute the secret. Right, " +
"you have a color that Eve does not have, so you have to use that one. It is the color " +
"with the label SA. The other color is the one you got from Bob which is the mixture of Bob, " +
"MB");
private String mix = i18n.tr("Mix with public color");
private String mixFinal = i18n.tr("Mix colors to final secret");
private String contin = i18n.tr("Continue");
private String notSame = i18n.tr("The private color can't be the same" +
" as the public color");
private String send = i18n.tr("Send color");
private String wrongColor = i18n.tr("You chose the wrong colors, try again");
private JLabel explainLbl;
private JButton multiBtn;
private ColorChannel cc;
private ColorMix cm;
private ColorChooser chooser, chooser2;
private GridBagConstraints gbc;
private Color[] toChooseFrom = {Color.BLUE, Color.GREEN, Color.YELLOW,
Color.RED,
};
private Color[] rememberColors = toChooseFrom;
private ActionListener remember;
private Navigation n;
/**
* Build the used objects and lay them out
*/
public DHExperimentView() {
super();
help = help1; //the first help text
gbc = new GridBagConstraints();
GridBagLayout layout = new GridBagLayout();
this.setLayout(layout);
gbc.weightx = 0.1;
gbc.weighty = 0.0;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
n = new Navigation(i18n.tr("Back to Demonstration"), i18n.tr("Skip the Experiment"));
this.add(n, gbc);
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
this.explainLbl = new JLabel();
this.explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + explanation1 + "</div></html>");
gbc.weightx = 0.1;
gbc.weighty = 0.1;
gbc.gridx = 1;
gbc.gridy = 3;
this.add(explainLbl, gbc);
this.cc = new ColorChannel(new Dimension(700, 200), 50);
gbc.weightx = 0.2;
gbc.weighty = 0.2;
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.BOTH;
this.add(this.cc, gbc);
this.cm = new ColorMix(50, new Dimension(200, 200));
gbc.weightx = 0.1;
gbc.weighty = 0.1;
gbc.gridx = 0;
gbc.gridy = 1;
this.add(this.cm, gbc);
this.chooser = new ColorChooser(new Dimension(50, 50), Color.BLUE, toChooseFrom);
gbc.weightx = 0.1;
gbc.weighty = 0.1;
gbc.gridx = 0;
gbc.gridy = 2;
this.add(this.chooser, gbc);
this.multiBtn = new JButton("Send Color");
this.multiBtn.setPreferredSize(new Dimension(250, 40));
gbc.weightx = 0.1;
gbc.weighty = 0.1;
gbc.gridx = 2;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.NONE;
this.add(this.multiBtn, gbc);
this.multiBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(ActionListener al : multiBtn.getActionListeners()) {
multiBtn.removeActionListener(al);
}
sendPublicColor();
}
});
gbc.weightx = 0.1;
gbc.weighty = 0.1;
gbc.gridx = 2;
gbc.gridy = 2;
this.add(new LabelExplanation(), gbc);
validate();
}
private void sendPublicColor() {
this.cc.setRepeat(false);
this.cc.setKeepColor(true);
this.cc.choosePublicColor(this.chooser.getCurrentColor());
this.cc.sendPublicColor(new NextStepCallback() {
@Override
public void callback() {
help = help2;
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + explanation2 + "</div></html>");
multiBtn.setText(mix);
multiBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!chooser.getCurrentColor().equals(cc.getPublicColor())) {
for(ActionListener al : multiBtn.getActionListeners()) {
multiBtn.removeActionListener(al);
}
mixPrivateColorStep();
} else {
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + notSame + "</div></html>");
}
}
});
}
});
}
private void mixPrivateColorStep() {
cc.chooseAlicePrivateColor(chooser.getCurrentColor());
cc.mixAlicePrivatePublic();
cm.setEllipColor(0, cc.getPublicColor());
cm.setEllipColor(1, cc.getAlicePrivateColor());
cm.setComputeFinalMix(false);
cm.mixColors(true, false, new NextStepCallback() {
@Override
public void callback() {
help = help3;
chooser.setToChooseFrom(new Color[]{cc.getPublicColor(), cc.getAlicePrivateColor(),
cm.getMixedColor()
});
toChooseFrom = chooser.getToChooseFrom();
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + explanation3 + "</div></html>");
multiBtn.setText(send);
multiBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMixedColor();
}
});
}
});
}
private void sendMixedColor() {
if(chooser.getCurrentColor().equals(cc.getAliceMixedColor())) {
for(ActionListener al : multiBtn.getActionListeners()) {
multiBtn.removeActionListener(al);
}
chooser.setHide(true);
revalidate();
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + rightColor + "</div></html>");
cc.sendAliceMixedColorToBob(new NextStepCallback() {
@Override
public void callback() {
help = help4;
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + bobsTurn + "</div></html>");
multiBtn.setText(contin);
multiBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
for(ActionListener al : multiBtn.getActionListeners()) {
multiBtn.removeActionListener(al);
}
sendBobMixedColor();
}
});
}
});
} else {
if(chooser.getCurrentColor().equals(cc.getAlicePrivateColor())) {
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + wrongPrivate + "</div></html>");
} else {
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + wrongPublic + "</div></html>");
}
}
}
private void sendBobMixedColor() {
cc.chooseBobPrivateColor(randomColor());
cm.setEllipColor(1, cc.getBobPrivateColor());
cm.mixColors(true, false, new NextStepCallback() {
@Override
public void callback() {
cc.sendBobMixedColorToAlice(new NextStepCallback() {
@Override
public void callback() {
help = help5;
Color[] param = new Color[]{cc.getPublicColor(),
cc.getAlicePrivateColor(), cc.getAliceMixedColor(),
cc.getBobMixedColor()};
chooser2 = new ColorChooser(new Dimension(50, 50), param[0], param);
gbc.gridx = 0;
gbc.gridy = 3;
add(chooser2, gbc);
chooser.setToChooseFrom(param);
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + finalSecret + "</div></html>");
multiBtn.setText(mixFinal);
validate();
chooser.setHide(false);
revalidate();
multiBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mixFinalColors();
}
});
}
});
}
});
}
private void mixFinalColors() {
if((chooser.getCurrentColor().equals(cc.getAlicePrivateColor())
&& chooser2.getCurrentColor().equals(cc.getBobMixedColor()))
|| (chooser.getCurrentColor().equals(cc.getBobMixedColor())
&& chooser2.getCurrentColor().equals(cc.getAlicePrivateColor()))) {
//chose the right colors
for(ActionListener al : multiBtn.getActionListeners()) {
multiBtn.removeActionListener(al);
}
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" + congrats + "</div></html>");
cc.mixAliceFinalSecret(new NextStepCallback() {
@Override
public void callback() {
cc.mixBobFinalSecret(new NextStepCallback() {
@Override
public void callback() {
multiBtn.setText(contin);
chooser.setHide(true);
chooser2.setHide(true);
revalidate();
multiBtn.addActionListener(remember);
}
});
}
});
} else {
explainLbl.setText("<html><div style=\"width:300px; height:100px\">" +
wrongColor + "</div></html>");
validate();
}
}
/*
* randomColor from remember - toChooseFrom
*/
private Color randomColor() {
Color randColor = rememberColors[randInt(0, rememberColors.length-1)];
while(in(randColor, toChooseFrom)) {
randColor = rememberColors[randInt(0, rememberColors.length-1)];
}
return randColor;
}
private boolean in(Color rand, Color[] colors) {
for(int i=0; i < colors.length; i++) {
if(rand.equals(colors[i])) {
return true;
}
}
return false;
}
private int randInt(int min, int max) {
Random rand = new Random();
int randNum = rand.nextInt((max-min) + 1) + min;
return randNum;
}
/**
* remember an actionlistener
* @param remember remember this actionlistener
*/
public void setRemember(ActionListener remember) {
this.remember = remember;
}
/** return help string */
public String getHelp() {
return help;
}
public JButton getSkipButton() {
return n.getForward();
}
public JButton getReturnButton() {
return n.getBack();
}
}