package votingform;
import java.awt.Color;
import java.awt.Font;
import java.awt.Dimension;
import java.math.BigInteger;
import java.security.SecureRandom;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
public class VotingForm extends javax.swing.JFrame {
// Fields for encryption, voting, and results
private EncryptionUtils encryptionUtils;
private Voter voter1;
private Voter voter2;
private VoteTally voteTally;
private JPanel chartPanel1;
private JPanel chartPanel2;
private long startTime;
private int totalVotesCast;
// Constructor
public VotingForm() {
encryptionUtils = new EncryptionUtils();
encryptionUtils.generateKeys(512); // Generate keys with 512-bit length
voter1 = new Voter("voter1");
voter2 = new Voter("voter2");
voteTally = new VoteTally(encryptionUtils);
totalVotesCast = 0;
initComponents();
}
// Method to initialize components
private void initComponents() {
// Labels, text fields, and buttons
validityCheckLabel = new JLabel("Decryption Validity:");
validityCheckLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
validityCheckTextArea = new JTextArea();
validityCheckTextArea.setEditable(false);
validityCheckTextArea.setPreferredSize(new Dimension(400, 50));
vote1Label = new JLabel("Enter vote for voter1 (1 for yes, 0 for no):");
vote1Label.setFont(new Font("Tahoma", Font.PLAIN, 20));
vote1TextField = new JTextField();
vote1TextField.setPreferredSize(new Dimension(200, 30));
vote2Label = new JLabel("Enter vote for voter2 (1 for yes, 0 for no):");
vote2Label.setFont(new Font("Tahoma", Font.PLAIN, 20));
vote2TextField = new JTextField();
vote2TextField.setPreferredSize(new Dimension(200, 30));
submitVotesButton = new JButton("Submit Votes");
encryptedVote1Label = new JLabel("Voter1's encrypted vote:");
encryptedVote1Label.setFont(new Font("Tahoma", Font.PLAIN, 14));
encryptedVote1TextArea = new JTextArea();
encryptedVote1TextArea.setEditable(false);
encryptedVote1TextArea.setPreferredSize(new Dimension(400, 50));
encryptedVote2Label = new JLabel("Voter2's encrypted vote:");
encryptedVote2Label.setFont(new Font("Tahoma", Font.PLAIN, 14));
encryptedVote2TextArea = new JTextArea();
encryptedVote2TextArea.setEditable(false);
encryptedVote2TextArea.setPreferredSize(new Dimension(400, 50));
encryptedCumulativeVoteLabel = new JLabel("Cumulative encrypted vote:");
encryptedCumulativeVoteLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
encryptedCumulativeVoteTextArea = new JTextArea();
encryptedCumulativeVoteTextArea.setEditable(false);
encryptedCumulativeVoteTextArea.setPreferredSize(new Dimension(400, 50));
finalResultLabel = new JLabel("The final result is:");
finalResultLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
finalResultTextArea = new JTextArea();
finalResultTextArea.setEditable(false);
finalResultTextArea.setPreferredSize(new Dimension(400, 50));
speedLabel = new JLabel("Speed of the Algorithm:");
speedLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
speedTextArea = new JTextArea();
speedTextArea.setEditable(false);
speedTextArea.setPreferredSize(new Dimension(400, 50));
efficiencyLabel = new JLabel("Efficiency of the Algorithm:");
efficiencyLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
efficiencyTextArea = new JTextArea();
efficiencyTextArea.setEditable(false);
efficiencyTextArea.setPreferredSize(new Dimension(400, 50));
totalVotesLabel = new JLabel("Total votes cast:");
totalVotesLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
totalVotesTextArea = new JTextArea();
totalVotesTextArea.setEditable(false);
totalVotesTextArea.setPreferredSize(new Dimension(400, 50));
// Initialize charts
chartPanel1 = createChartPanel("Speed of the Algorithm", "Iterations",
"Speed (ms)");
chartPanel2 = createChartPanel("Efficiency of the Algorithm", "Iterations",
"Efficiency (%)");
// Add action listener to the submit button
submitVotesButton.addActionListener(evt ->
submitVotesActionPerformed(evt));
// Set background colors
getContentPane().setBackground(new Color(240, 240, 240));
submitVotesButton.setBackground(new Color(50, 150, 250));
submitVotesButton.setForeground(Color.WHITE);
// Layout setup (using GroupLayout for simplicity)
javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignm
ent.LEADING)
.addComponent(vote1Label)
.addComponent(vote1TextField,
javax.swing.GroupLayout.PREFERRED_SIZE, 200,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(vote2Label)
.addComponent(vote2TextField,
javax.swing.GroupLayout.PREFERRED_SIZE, 200,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(submitVotesButton)
.addComponent(encryptedVote1Label)
.addComponent(encryptedVote1TextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(encryptedVote2Label)
.addComponent(encryptedVote2TextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(encryptedCumulativeVoteLabel)
.addComponent(encryptedCumulativeVoteTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(finalResultLabel)
.addComponent(finalResultTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(speedLabel)
.addComponent(speedTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(efficiencyLabel)
.addComponent(efficiencyTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(totalVotesLabel)
.addComponent(totalVotesTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, 400,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED
, 50, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignm
ent.LEADING, false)
.addComponent(chartPanel1,
javax.swing.GroupLayout.DEFAULT_SIZE, 600, Short.MAX_VALUE)
.addComponent(chartPanel2,
javax.swing.GroupLayout.DEFAULT_SIZE, 600, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignm
ent.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(vote1Label)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(vote1TextField,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(vote2Label)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(vote2TextField,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(submitVotesButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.UNRELATED)
.addComponent(encryptedVote1Label)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(encryptedVote1TextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(encryptedVote2Label)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(encryptedVote2TextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(encryptedCumulativeVoteLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(encryptedCumulativeVoteTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(finalResultLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(finalResultTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(speedLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(speedTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(efficiencyLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(efficiencyTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(totalVotesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(totalVotesTextArea,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(chartPanel1,
javax.swing.GroupLayout.PREFERRED_SIZE, 300,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
.RELATED)
.addComponent(chartPanel2,
javax.swing.GroupLayout.PREFERRED_SIZE, 300,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(30, Short.MAX_VALUE))
);
pack();
}
// Method to create chart panels
private JPanel createChartPanel(String chartTitle, String xAxisLabel, String
yAxisLabel) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
JFreeChart chart = ChartFactory.createLineChart(chartTitle, xAxisLabel,
yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false);
return new ChartPanel(chart);
}
// Action method for submit button
private void submitVotesActionPerformed(java.awt.event.ActionEvent evt) {
try {
int vote1 = Integer.parseInt(vote1TextField.getText());
int vote2 = Integer.parseInt(vote2TextField.getText());
startTime = System.currentTimeMillis();
voter1.castVote(encryptionUtils, vote1);
voter2.castVote(encryptionUtils, vote2);
voteTally.addVote(voter1.getEncryptedVote());
voteTally.addVote(voter2.getEncryptedVote());
BigInteger decryptedResult =
encryptionUtils.decrypt(voteTally.getCumulativeVote());
long elapsedTime = System.currentTimeMillis() - startTime;
encryptedVote1TextArea.setText(voter1.getEncryptedVote().toString());
encryptedVote2TextArea.setText(voter2.getEncryptedVote().toString());
encryptedCumulativeVoteTextArea.setText(voteTally.getCumulativeVote().toString());
finalResultTextArea.setText(decryptedResult.toString());
speedTextArea.setText(elapsedTime + " ms");
double efficiency = (decryptedResult.doubleValue() / 2) * 100;
efficiencyTextArea.setText(String.format("%.2f %%", efficiency));
totalVotesCast += 2;
totalVotesTextArea.setText(String.valueOf(totalVotesCast));
updateChart(chartPanel1, elapsedTime, totalVotesCast, "Time (ms)");
updateChart(chartPanel2, efficiency, totalVotesCast, "Efficiency (%)");
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Please enter valid votes (1 for
yes, 0 for no).", "Invalid Input", JOptionPane.ERROR_MESSAGE);
}
}
// Method to update chart data
private void updateChart(JPanel chartPanel, double value, int iteration, String
seriesName) {
ChartPanel cp = (ChartPanel) chartPanel;
DefaultCategoryDataset dataset = (DefaultCategoryDataset)
cp.getChart().getCategoryPlot().getDataset();
dataset.addValue(value, seriesName, Integer.toString(iteration));
}
// Main method to start the application
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(() -> {
new VotingForm().setVisible(true);
});
}
// Variables declaration - do not modify
private javax.swing.JButton submitVotesButton;
private javax.swing.JLabel vote1Label;
private javax.swing.JTextField vote1TextField;
private javax.swing.JLabel vote2Label;
private javax.swing.JTextField vote2TextField;
private javax.swing.JLabel encryptedVote1Label;
private javax.swing.JTextArea encryptedVote1TextArea;
private javax.swing.JLabel encryptedVote2Label;
private javax.swing.JTextArea encryptedVote2TextArea;
private javax.swing.JLabel encryptedCumulativeVoteLabel;
private javax.swing.JTextArea encryptedCumulativeVoteTextArea;
private javax.swing.JLabel finalResultLabel;
private javax.swing.JTextArea finalResultTextArea;
private javax.swing.JLabel speedLabel;
private javax.swing.JTextArea speedTextArea;
private javax.swing.JLabel efficiencyLabel;
private javax.swing.JTextArea efficiencyTextArea;
private javax.swing.JLabel totalVotesLabel;
private javax.swing.JTextArea totalVotesTextArea;
private javax.swing.JLabel validityCheckLabel;
private javax.swing.JTextArea validityCheckTextArea;
// private javax.swing.JPanel chartPanel1;
// private javax.swing.JPanel chartPanel2;
// End of variables declaration
}
class PaillierPublicKey {
private final BigInteger n;
private final BigInteger g;
public PaillierPublicKey(BigInteger n, BigInteger g) {
this.n = n;
this.g = g;
}
public BigInteger encrypt(BigInteger m) {
BigInteger r = new BigInteger(n.bitLength(), new SecureRandom());
return g.modPow(m, n.multiply(n)).multiply(r.modPow(n,
n.multiply(n))).mod(n.multiply(n));
}
public BigInteger add(BigInteger c1, BigInteger c2) {
return c1.multiply(c2).mod(n.multiply(n));
}
}
class PaillierPrivateKey {
private final BigInteger lambda;
private final BigInteger n;
public PaillierPrivateKey(BigInteger lambda, BigInteger n) {
this.lambda = lambda;
this.n = n;
}
public BigInteger decrypt(BigInteger c) {
BigInteger u = c.modPow(lambda,
n.multiply(n)).subtract(BigInteger.ONE).divide(n);
return u.multiply(lambda.modInverse(n)).mod(n);
}
}
class PaillierKeyPair {
private final PaillierPublicKey publicKey;
private final PaillierPrivateKey privateKey;
public PaillierKeyPair(PaillierPublicKey publicKey, PaillierPrivateKey
privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public PaillierPublicKey getPublicKey() {
return publicKey;
}
public PaillierPrivateKey getPrivateKey() {
return privateKey;
}
}
class EncryptionUtils {
private PaillierKeyPair keyPair;
public void generateKeys(int bitLength) {
BigInteger p = new BigInteger(bitLength / 2, 100, new SecureRandom());
BigInteger q = new BigInteger(bitLength / 2, 100, new SecureRandom());
BigInteger n = p.multiply(q);
BigInteger lambda =
p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
BigInteger g = n.add(BigInteger.ONE);
PaillierPublicKey publicKey = new PaillierPublicKey(n, g);
PaillierPrivateKey privateKey = new PaillierPrivateKey(lambda, n);
keyPair = new PaillierKeyPair(publicKey, privateKey);
}
public BigInteger encrypt(BigInteger message) {
return keyPair.getPublicKey().encrypt(message);
}
public BigInteger decrypt(BigInteger ciphertext) {
return keyPair.getPrivateKey().decrypt(ciphertext);
}
public BigInteger addEncrypted(BigInteger c1, BigInteger c2) {
return keyPair.getPublicKey().add(c1, c2);
}
public PaillierKeyPair getKeyPair() {
return keyPair;
}
}
class Voter {
private final String id;
private BigInteger encryptedVote;
public Voter(String id) {
this.id = id;
}
public void castVote(EncryptionUtils encryptionUtils, int vote) {
encryptedVote = encryptionUtils.encrypt(BigInteger.valueOf(vote));
}
public BigInteger getEncryptedVote() {
return encryptedVote;
}
}
class VoteTally {
private final EncryptionUtils encryptionUtils;
private BigInteger cumulativeVote;
public VoteTally(EncryptionUtils encryptionUtils) {
this.encryptionUtils = encryptionUtils;
this.cumulativeVote = BigInteger.ONE; // Start with 1 for homomorphic
addition
}
public void addVote(BigInteger encryptedVote) {
cumulativeVote = encryptionUtils.addEncrypted(cumulativeVote,
encryptedVote);
}
public BigInteger getCumulativeVote() {
return cumulativeVote;
}
}