// Encrypt.java, version 1.08. This file was created on July 28, 2006. // // Applet for encrypting secret messages with XOR private encryption keys. // // This file last updated June 6, 2007, by Rick Wagner. // Copyright 2006 by Rick Wagner, all rights reserved. // // Use of this source code is authorized for educational purposes only. No use without // proper attribution to Rick Wagner (http://iris.usc.edu/home/iris/rwagner/ // e-mail: Richard.J.Wagner@gmail.com). // // The prefix naming convention used here is a modified Hungarian notation. // "s" is string, "sf" is single precision floating point, "i" is integer, "b" is boolean, // and "d" is dimension. import java.applet.*; import java.awt.*; public class Encrypt extends Applet { // Applet instance variables: private final String sVerNum = "1.08"; // Only constructors can run here ("" is a constructor). private final String sCompiledDate = "June 7, 2007"; // Compiled date. private Dimension dApplet = null; // The applet panel size (set in calling html). private Image imOffScreen = null; // Offscreen image for double buffering. private Graphics grOffScreen = null; // Offscreen graphics for double buffering. private Button btnRandomKey = null; private Button btnEncrypt = null; private TextArea taCryptText = null; private TextArea taPlainText = null; private TextArea taKeyText = null; private Label lblOne = null; // First label. private Label lblTwo = null; // Second label. private Label lblThree = null; // Third label. private Label lblMessage = null; // Message label. // To allow browsers to get information about the applet (not yet implemented in Netscape nor in MSIE): public String getAppletInfo() { return "XOR encryption applet, version " + sVerNum + ", by Rick Wagner, copyright 2007,\nall rights reserved.\n\n" + "Compiled " + sCompiledDate + ". Source code use authorized for\n" + "educational purposes only. No use without attribution.\n"; } // Initialize the applet public void init() { int i = 0; this.setBackground(Color.lightGray); GridBagLayout gbl = null; // GridBagLayout is used for the applet GUI layout. GridBagConstraints gbc = null; dApplet = this.size(); gbl = new GridBagLayout(); this.setLayout(gbl); gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 10, 5, 10); // top, left, bottom, right. gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.gridx = 0; // First Label lblOne = new Label("Plain Text", Label.CENTER); gbc.gridy = 0; gbl.setConstraints(lblOne, gbc); this.add(lblOne); // Add the plain text box: taPlainText = new TextArea("", 6, 80); // 6 rows and 80 columns. taPlainText.setEditable(true); gbc.gridy = 1; gbl.setConstraints(taPlainText, gbc); this.add(taPlainText); // Second Label lblTwo = new Label("Key Text", Label.CENTER); gbc.gridy = 2; gbl.setConstraints(lblTwo, gbc); this.add(lblTwo); // Add the Key text box: taKeyText = new TextArea("", 6, 80); // 6 rows and 80 columns. taKeyText.setEditable(true); gbc.gridy = 3; gbl.setConstraints(taKeyText, gbc); this.add(taKeyText); // Add the random button: btnRandomKey = new Button("Generate Random Key"); // The random key generation button. btnRandomKey.setForeground(Color.black); btnRandomKey.setBackground(Color.lightGray); gbc.gridy = 4; gbl.setConstraints(btnRandomKey, gbc); this.add(btnRandomKey); // Message Label lblMessage = new Label(" Welcome to the XOR encryption applet." + "Type or paste text into the upper two text boxes. ", Label.CENTER); gbc.gridy = 5; gbl.setConstraints(lblMessage, gbc); this.add(lblMessage); // Add the encrypt button: btnEncrypt = new Button("Encrypt the Text"); // The compute crypttext button. btnEncrypt.setForeground(Color.black); btnEncrypt.setBackground(Color.lightGray); gbc.gridy = 6; gbl.setConstraints(btnEncrypt, gbc); this.add(btnEncrypt); // Third Label lblThree = new Label("Encrypted Text", Label.CENTER); gbc.gridy = 7; gbl.setConstraints(lblThree, gbc); this.add(lblThree); // Add the crypt text box: taCryptText = new TextArea("", 6, 80); // 6 rows and 80 columns. taCryptText.setEditable(true); gbc.gridy = 8; gbl.setConstraints(taCryptText, gbc); this.add(taCryptText); } // End of init() // Execute this code after initialization public void start() { System.out.println("\n" + this.getAppletInfo()); // Identify self to the Java console-aware user taPlainText.requestFocus(); } // End of start() // Implements double buffering public void update(Graphics g) { if (imOffScreen == null) { // Make sure the offscreen and graphics exist: imOffScreen = this.createImage(dApplet.width, dApplet.height); grOffScreen = imOffScreen.getGraphics(); grOffScreen.clearRect(0, 0, dApplet.width, dApplet.height); } this.paint(grOffScreen); g.drawImage(imOffScreen, 0, 0, null); } // The applet frame painting function public void paint(Graphics g) { // Code for displaying images or drawing in the applet frame (called by the OS). g.clearRect(0, 0, dApplet.width, dApplet.height); // Needed for double buffering. this.setBackground(Color.lightGray); // Ditto. drawFrame(g); // Draw the frame abound the applet. } // End of function paint() private void drawFrame(Graphics g) { // Draw a recessed frame around the applet border. Designed for gray-on-gray browser background. g.setColor(Color.black); g.drawLine(0, 0, dApplet.width - 1, 0); g.drawLine(0, 0, 0, dApplet.height - 1); g.setColor(Color.white); g.drawLine(0, dApplet.height - 1, dApplet.width - 1, dApplet.height - 1); g.drawLine(dApplet.width - 1, 1, dApplet.width - 1, dApplet.height - 1); } public boolean action(Event e, Object o) { if (e.target == btnEncrypt) { btnEncrypt.disable(); if (taPlainText.getText().length() == 0) { System.out.println("Plaintext Empty"); lblMessage.setText("Plaintext Empty"); } else { if (taKeyText.getText().length() == 0) { System.out.println("Keytext Empty"); lblMessage.setText("Keytext Empty"); } else { // We can do the key computation encrypt(); } } btnEncrypt.enable(); } if (e.target == btnRandomKey) { int i = 0; int iTemp = 0; int iPlainLength = 0; StringBuffer sbTemp = null; sbTemp = new StringBuffer(); iPlainLength = taPlainText.getText().length(); if (iPlainLength > 0) { for (i = 0; i < iPlainLength; i++) { iTemp = (int) (128 * Math.random()); sbTemp.append(iTemp); if (i < iPlainLength - 1) { sbTemp.append(' '); } } taKeyText.setText(sbTemp.toString()); lblMessage.setText("Generated random key of " + iPlainLength + " characters."); } else { taKeyText.setText(""); lblMessage.setText("Need some plaintext to generate a key."); } } return true; // Absorb the event; } // End of action(). public boolean handleEvent(Event e) { int iLength = 0; if (e.target == btnEncrypt && e.id == Event.ACTION_EVENT) { btnEncrypt.disable(); if (taPlainText.getText().length() == 0) { System.out.println("Plaintext Empty"); lblMessage.setText("Plaintext Empty"); } else { if (taKeyText.getText().length() == 0) { System.out.println("Keytext Empty"); lblMessage.setText("Keytext Empty"); } else { // We can do the key computation encrypt(); } } btnEncrypt.enable(); return true; } if (e.target == btnRandomKey && e.id == Event.ACTION_EVENT) { int i = 0; int iTemp = 0; int iPlainLength = 0; StringBuffer sbTemp = null; sbTemp = new StringBuffer(); iPlainLength = taPlainText.getText().length(); if (iPlainLength > 0) { for (i = 0; i < iPlainLength; i++) { iTemp = (int) (128 * Math.random()); sbTemp.append(iTemp); if (i < iPlainLength - 1) { sbTemp.append(' '); } } taKeyText.setText(sbTemp.toString()); lblMessage.setText("Generated random key of " + iPlainLength + " characters."); } else { taKeyText.setText(""); lblMessage.setText("Need some plaintext to generate a key."); } return true; } if (e.target == taPlainText) { if (e.id != Event.GOT_FOCUS) { iLength = taPlainText.getText().length(); lblMessage.setText("Plain text is " + iLength + " characters long."); } } if (e.target == taKeyText) { if (e.id != Event.GOT_FOCUS) { iLength = taKeyText.getText().length(); lblMessage.setText("Key text is " + iLength + " characters long."); } } return false; } private void encrypt() { int i = 0; int iPlainLength = 0; int iKeyLength = 0; int iKeyTextLength = 0; int iDelta = 0; int iTemp = 0; char cTemp = 0; String sTemp = null; String sPlainText = null; String sKeyText = null; String sCryptText = null; StringBuffer sbTemp = null; int iKey[] = null; int iKeyBuffer[] = null; boolean bNumericKey = false; sPlainText = taPlainText.getText(); sKeyText = taKeyText.getText(); iPlainLength = sPlainText.length(); iKeyTextLength = sKeyText.length(); System.out.println("\n"); // Find out if the key is numeric: if (numericP(iKeyTextLength, sKeyText)) { bNumericKey = true; System.out.println("The key is numeric."); // Fill the key array: iKey = new int[iKeyTextLength]; while (i < iKeyTextLength) { cTemp = 0; sbTemp = new StringBuffer(); while (cTemp != ' ' && i < iKeyTextLength) { try { cTemp = sKeyText.charAt(i); } catch (StringIndexOutOfBoundsException e1) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (key)."); } if (cTemp != ' ') { sbTemp.append(cTemp); } i++; } try { iTemp = Integer.parseInt(sbTemp.toString()); } catch (NumberFormatException e2) { System.out.println("Caught NumberFormatException in decrypt() (key)."); break; } iKey[iKeyLength] = iTemp; iKeyLength++; } } else { System.out.println("The key is not numeric."); iKeyLength = iKeyTextLength; } if (iPlainLength < iKeyLength) { // Pad out the crypttext. System.out.println("Key is longer than plaintext: padding plaintext with spaces."); lblMessage.setText("Key is longer than plaintext: padding plaintext with spaces."); sbTemp = new StringBuffer(); iDelta = iKeyLength - iPlainLength; for (i = 0; i < iDelta; i++) { sbTemp.append(" "); } sPlainText = sPlainText + sbTemp.toString(); taPlainText.setText(sPlainText); iPlainLength = sPlainText.length(); } else { if (iKeyLength < iPlainLength) { // Repeat the key as necessary to make it long enough. System.out.println("Key is shorter than plaintext: repeating the key."); lblMessage.setText("Key is shorter than plaintext: repeating the key."); if (bNumericKey) { iKeyBuffer = new int[iKeyLength]; // Need to stash the key characters someplace for (i = 0; i < iKeyLength; i++) // while we get more memory for the array. { iKeyBuffer[i] = iKey[i]; } iKey = new int[iPlainLength]; // Expand the key array. for (i = 0; i < iKeyLength; i++) { iKey[i] = iKeyBuffer[i]; } for (i = iKeyLength; i < iPlainLength; i++) { iKey[i] = iKey[i - iKeyLength]; } } else { // The key is printable text: sbTemp = new StringBuffer(sKeyText); for (i = iKeyLength; i < iPlainLength; i++) { sbTemp.append(sbTemp.charAt(i - iKeyLength)); } sKeyText = sbTemp.toString(); iKeyLength = sKeyText.length(); } } else { // They are equal in length, do nothing. } } // Begin the encryption. sbTemp = new StringBuffer(); for (i = 0; i < iPlainLength; i++) { if (bNumericKey) { iTemp = sPlainText.charAt(i) ^ iKey[i]; // XOR encryption } else { iTemp = sPlainText.charAt(i) ^ sKeyText.charAt(i); // XOR encryption } sbTemp.append((char) iTemp); } sTemp = sbTemp.toString(); if (unprintableP(iPlainLength, sTemp)) { System.out.println("Unprintable encrypted text, writing " + iPlainLength + " characters as numeric code."); lblMessage.setText("Unprintable encrypted text, writing " + iPlainLength + " characters as numeric code."); sbTemp = new StringBuffer(); for (i = 0; i < iPlainLength; i++) { iTemp = sTemp.charAt(i); if (i == iPlainLength - 1) { sbTemp.append(iTemp); } else { sbTemp.append(iTemp + " "); } } taCryptText.setText(sbTemp.toString()); } else { System.out.println("Printable encrypted text, writing " + iPlainLength + " characters."); lblMessage.setText("Printable encrypted text, writing " + iPlainLength + " characters."); taCryptText.setText(sTemp); } } // End of function encrypt(). boolean numericP(int iTextLength, String sText) { boolean r = true; int i = 0; char cTemp = 0; int iRunLength = 0; int iMaxRunLength = 0; for (i = 0; i < iTextLength; i++) { try { cTemp = sText.charAt(i); } catch (StringIndexOutOfBoundsException e7) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e7)."); } if (cTemp != ' ') { if (cTemp < 48 || cTemp > 57) { r = false; break; // Break out of for loop. } else { if (cTemp > 47 && cTemp < 58) { // We have a decimal digit. iRunLength++; } } } else { // We have a space: // Detect delimiting spaces if (iRunLength > iMaxRunLength) { iMaxRunLength = iRunLength; } iRunLength = 0; } } // End of for. if (iRunLength > iMaxRunLength) // Catch the case where the space { // comes at the end of the string. iMaxRunLength = iRunLength; } if (iMaxRunLength > 3) // It's not text that happens to to be { // a string (or strings) of digits. r = false; } return r; } boolean numericKeyP(int iKeyTextLength, String sKeyText) { boolean r = true; int i = 0; char cTemp = 0; for (i = 0; i < iKeyTextLength; i++) { cTemp = sKeyText.charAt(i); if (cTemp != ' ') { if (cTemp < 48 || cTemp > 57) { r = false; break; // Break out of for loop. } } } return r; } boolean unprintableP(int iLength, String sText) { boolean r = false; int i = 0; char cTemp = 0; for (i = 0; i < iLength; i++) { cTemp = sText.charAt(i); if (cTemp < 32 || cTemp == 127) { if (cTemp != 9 && cTemp != 10 && cTemp != 12 && cTemp != 13) { r = true; break; // Break out of for loop. } } } return r; } } // End of Applet class Encrypt