/** * RSA Public/Private Key Generator * * * */ import java.math.BigInteger; import java.awt.*; import java.awt.event.*; import java.applet.Applet; import java.util.Random; import java.util.Date; import java.io.*; public class GenKey extends Applet implements ActionListener { static final int WIDTH = 600; static final int MARGIN = 5; static final int DY = 40; static final int VSKIP = 4; static final int HSKIP = 4; static final int CERTAINTY = 64; static final int NUM_ATTEMPTS = 32; static final int MAX_DIGITS = 500; Random rnd = new Random(new Date().getTime()); BigInteger module; BigInteger euler; BigInteger p, q; BigInteger e; BigInteger d; int numDigits; TextField numDigitsTxt; TextField moduleTxt; TextField publicKeyTxt; TextField privateKeyTxt; Button genButton; Button writeButton; TextField fileName; Label message; public static void main(String[] args) { Frame f = new Frame("RSA Public/Private Key Generator"); WindowAdapter wa = new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }; f.addWindowListener(wa); f.setFont(new Font("Helvetica", Font.PLAIN, 14)); // Add menu bar final MenuBar mb = new MenuBar(); f.setMenuBar(mb); final Menu fileMenu = new Menu("File"); final MenuItem quitItem = new MenuItem("Quit"); fileMenu.add(quitItem); mb.add(fileMenu); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { // System.out.println("Action " + e); if (e.getActionCommand().equals("Quit")) { System.exit(0); } } }; fileMenu.addActionListener(al); GenKey gk = new GenKey(); f.add("Center", gk); gk.init(); gk.start(); // f.pack(); f.setSize( WIDTH + 24, 6 * (DY + VSKIP) + 2 * MARGIN + 50 // Menu bar ); f.setVisible(true); } public GenKey() { } public void init() { setLayout(null); setBackground(Color.lightGray); int y = MARGIN; int x0 = MARGIN; int x1 = 90; int x2 = 120; int w = WIDTH - MARGIN - x1; setFont(new Font("Helvetica", Font.PLAIN, 14)); Label l = new Label("Number of digits:"); add(l); l.setBounds(x0, y, 110, DY); numDigitsTxt = new TextField(""); add(numDigitsTxt); numDigitsTxt.setBounds(x2, y, 60, DY); y += DY + VSKIP; l = new Label("Module:"); add(l); l.setBounds(x0, y, 80, DY); moduleTxt = new TextField(""); add(moduleTxt); moduleTxt.setBounds(x1, y, w, DY); y += DY + VSKIP; l = new Label("Public key:"); add(l); l.setBounds(x0, y, 80, DY); publicKeyTxt = new TextField(""); add(publicKeyTxt); publicKeyTxt.setBounds(x1, y, w, DY); y += DY + VSKIP; l = new Label("Private key:"); add(l); l.setBounds(x0, y, 80, DY); privateKeyTxt = new TextField(""); add(privateKeyTxt); privateKeyTxt.setBounds(x1, y, w, DY); y += DY + VSKIP; genButton = new Button("Generate"); add(genButton); genButton.setBounds(x0, y, 80, DY); genButton.addActionListener(this); writeButton = new Button("Write to file"); add(writeButton); writeButton.setBounds(x1, y, 80, DY); writeButton.addActionListener(this); l = new Label("File name:"); add(l); l.setBounds(x1 + 90, y, 70, DY); fileName = new TextField("KeyPair.dat"); add(fileName); fileName.setBounds( x1 + 90 + 70, y, WIDTH - (x1 + 90 + 70) - MARGIN, DY ); y += DY + VSKIP; message = new Label(""); add(message); message.setBounds(x0, y, WIDTH - 2 * MARGIN, DY); message.setForeground(Color.blue); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == genButton) { onGenerate(); } else if (source == writeButton) { onWrite(); } } void onGenerate() { String num = numDigitsTxt.getText(); if (num == "") return; message.setText(""); try { numDigits = Integer.parseInt(num); } catch (NumberFormatException e) { message.setText("Illegal number of digits."); return; } int binaryDigits = (int)( numDigits * 0.5 * Math.log(10.) / Math.log(2.) ); if (binaryDigits < 2 || numDigits > MAX_DIGITS) { message.setText("Illegal number of digits (maximum " + MAX_DIGITS + ")."); return; } message.setText("Please, wait..."); p = new BigInteger( binaryDigits, CERTAINTY, rnd ); boolean ok = false; for (int t = 0; t < NUM_ATTEMPTS; t++) { q = new BigInteger( binaryDigits, CERTAINTY, rnd ); if (!p.equals(q)) { ok = true; break; } } if (!ok) { message.setText("Alas, cannot generate..."); System.out.println("Alas, cannot generate..."); return; } module = p.multiply(q); euler = p.subtract(BigInteger.valueOf(1)).multiply( q.subtract(BigInteger.valueOf(1)) ); moduleTxt.setText("" + module); System.out.println("p = " + p); System.out.println("q = " + q); System.out.println("m = pq = " + module); System.out.println("Euler function(m) = " + euler); ok = false; for (int t = 0; t < NUM_ATTEMPTS; t++) { e = new BigInteger( binaryDigits*15/8, CERTAINTY, rnd ); System.out.println("e = "+e); if (e.gcd(euler).equals(BigInteger.valueOf(1))) { ok = true; break; } } if (!ok) { message.setText("Alas, cannot generate..."); System.out.println("Alas, cannot generate..."); return; } d = e.modInverse(euler); System.out.println("d = " + d); publicKeyTxt.setText("" + e); privateKeyTxt.setText("" + d); message.setText("RSA key pair is generated."); } void onWrite() { String filnam = fileName.getText(); if (filnam.equals("")) { message.setText("Please, write a file name."); return; } try { FileOutputStream fos = new FileOutputStream(filnam); DataOutputStream dos = new DataOutputStream(fos); dos.writeBytes("RSA Public/Private Key Pair\n"); dos.writeBytes("prime p = " + p + "\n"); dos.writeBytes("prime q = " + q + "\n"); dos.writeBytes("module pq = " + module + "\n"); dos.writeBytes("public key e = " + e + "\n"); dos.writeBytes("private key d = " + d + "\n"); fos.close(); message.setText("Key pair is written to the file \"" + filnam + "\""); } catch (IOException e) { message.setText("Cannot write to the file."); System.out.println("Cannot write to file.\n" + e); } catch (SecurityException e) { message.setText("Cannot write to the file by security reasons."); System.out.println("Cannot write to file by security reasons.\n" + e); } } }