// Decrypt.java, version 1.08, file created, July 27, 2006. // // Applet for decrypting secret messages with XOR decryption keys. // // This file last updated June 7, 2007, by Rick Wagner. // Copyright 2004 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 Decrypt 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 btnComputeKey = 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 decryption applet, version " + sVerNum + ", by Rick Wagner, copyright 2006,\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; GridBagLayout gbl = null; // GridBagLayout is used for the applet GUI layout. GridBagConstraints gbc = null; this.setBackground(Color.lightGray); 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("Encrypted Text", Label.CENTER); gbc.gridy = 0; gbl.setConstraints(lblOne, gbc); this.add(lblOne); // Add the crypt text box: taCryptText = new TextArea("", 6, 80); // 6 rows and 80 columns. taCryptText.setEditable(true); gbc.gridy = 1; gbl.setConstraints(taCryptText, gbc); this.add(taCryptText); // 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 decrypt button: btnComputeKey = new Button("Decrypt the Text"); // The compute decrypted text button. btnComputeKey.setForeground(Color.black); btnComputeKey.setBackground(Color.lightGray); gbc.gridy = 4; gbl.setConstraints(btnComputeKey, gbc); this.add(btnComputeKey); // Message Label lblMessage = new Label(" Welcome to the XOR decryption applet." + "Type or paste text into the upper two text boxes. ", Label.CENTER); gbc.gridy = 5; gbl.setConstraints(lblMessage, gbc); this.add(lblMessage); // Third Label lblThree = new Label(" Plain (decrypted) Text ", Label.CENTER); gbc.gridy = 6; gbl.setConstraints(lblThree, gbc); this.add(lblThree); // Add the plain text box: taPlainText = new TextArea("", 6, 80); // 6 rows and 80 columns. taPlainText.setEditable(true); gbc.gridy = 7; gbl.setConstraints(taPlainText, gbc); this.add(taPlainText); } // 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 taCryptText.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 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 handleEvent(Event e) { int iLength = 0; if (e.target == btnComputeKey && e.id == Event.ACTION_EVENT) { btnComputeKey.disable(); if (taCryptText.getText().length() == 0) { System.out.println("Cryptext Empty"); lblMessage.setText("Cryptext Empty"); } else { if (taKeyText.getText().length() == 0) { System.out.println("Keytext Empty"); lblMessage.setText("Keytext Empty"); } else { // We can do the key computation decrypt(); } } btnComputeKey.enable(); return true; // Absorb the event; } if (e.target == taCryptText) { if (e.id != Event.GOT_FOCUS) { iLength = taCryptText.getText().length(); lblMessage.setText("Crypt 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 decrypt() { int i = 0; int iCryptLength = 0; int iCryptTextLength = 0; int iKeyLength = 0; int iKeyTextLength = 0; int iDelta = 0; int iTemp = 0; char cTemp = 0; char cTemp0 = 0; String sTemp = null; String sCryptText = null; String sKeyText = null; String sPlainText = null; StringBuffer sbTemp = null; int iCrypt[] = null; int iCryptBuffer[] = null; int iKey[] = null; int iKeyBuffer[] = null; boolean bNumericKey = false; boolean bNumericCrypt = false; sCryptText = taCryptText.getText(); sKeyText = taKeyText.getText(); iCryptTextLength = sCryptText.length(); iKeyTextLength = sKeyText.length(); System.out.println("\n"); // Find out if the crypttext is numeric: if (numericP(iCryptTextLength, sCryptText)) { bNumericCrypt = true; System.out.println("The crypt text is numeric."); // Fill the crypt array: iCrypt = new int[iCryptTextLength]; // More than enough for the crypt integers. i = 0; while (i < iCryptTextLength) { cTemp = 0; sbTemp = new StringBuffer(); while (cTemp != ' ' && i < iCryptTextLength) { try { cTemp = sCryptText.charAt(i); } catch (StringIndexOutOfBoundsException e0) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (crypt)."); } if (cTemp != ' ') { sbTemp.append(cTemp); } i++; } iCrypt[iCryptLength] = Integer.parseInt(sbTemp.toString()); iCryptLength++; } } else { iCryptLength = iCryptTextLength; System.out.println("The crypt text is not numeric, iCryptLength = " + iCryptLength + "."); } // 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]; i = 0; 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 e1a) { System.out.println("Caught NumberFormatException in decrypt() (key)."); break; } iKey[iKeyLength] = iTemp; iKeyLength++; } } else { iKeyLength = iKeyTextLength; System.out.println("The key is not numeric, iKeyLength = " + iKeyLength + "."); } if (iCryptLength < iKeyLength) { if (bNumericCrypt) { System.out.println("Ignoring excess key digits."); } else { System.out.println("Ignoring excess key characters."); } } else { if (iKeyLength < iCryptLength) { System.out.println("Key is shorter than crypttext: repeating the key."); lblMessage.setText("Key is shorter than crypttext: repeating the key."); if (bNumericKey) { // Repeat the key as necessary to make it long enough. 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[iCryptLength]; // Expand the key array. for (i = 0; i < iKeyLength; i++) { iKey[i] = iKeyBuffer[i]; } for (i = iKeyLength; i < iCryptLength; i++) { iKey[i] = iKey[i - iKeyLength]; } } else { sbTemp = new StringBuffer(sKeyText); for (i = iKeyLength; i < iCryptLength; i++) { try { cTemp = sbTemp.charAt(i - iKeyLength); } catch (StringIndexOutOfBoundsException e2) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e2)."); } sbTemp.append(cTemp); } sKeyText = sbTemp.toString(); iKeyLength = sKeyText.length(); } } else { // They are equal in length, do nothing. } } // Begin the decryption. sbTemp = new StringBuffer(); for (i = 0; i < iCryptLength; i++) { if (bNumericKey) { if (bNumericCrypt) { iTemp = iCrypt[i] ^ iKey[i]; } else { try { cTemp = sCryptText.charAt(i); } catch (StringIndexOutOfBoundsException e3) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e3)."); } iTemp = cTemp ^ iKey[i]; } } else { if (bNumericCrypt) { try { cTemp = sKeyText.charAt(i); } catch (StringIndexOutOfBoundsException e4) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e4)."); } iTemp = iCrypt[i] ^ cTemp; } else { try { cTemp = sCryptText.charAt(i); cTemp0 = sKeyText.charAt(i); } catch (StringIndexOutOfBoundsException e5) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e5) , i = " + i + "."); } iTemp = cTemp ^ cTemp0; } } sbTemp.append((char) iTemp); } sTemp = sbTemp.toString(); if (unprintableP(iCryptLength, sTemp)) { System.out.println("Unprintable decrypted text, writing " + iCryptLength + " characters as numeric code."); lblMessage.setText("Unprintable decrypted text, writing " + iCryptLength + " characters as numeric code."); sbTemp = new StringBuffer(); for (i = 0; i < iCryptLength; i++) { try { iTemp = sTemp.charAt(i); } catch (StringIndexOutOfBoundsException e6) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e6)."); } if (i == iCryptLength - 1) { sbTemp.append(iTemp); } else { sbTemp.append(iTemp + " "); } } taPlainText.setText(sbTemp.toString()); } else { System.out.println("Printable decrypted text, writing " + iCryptLength + " characters."); lblMessage.setText("Printable decrypted text, writing " + iCryptLength + " characters."); taPlainText.setText(sTemp); } } // End of decrypt(). 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 unprintableP(int iLength, String sText) { boolean r = false; int i = 0; char cTemp = 0; for (i = 0; i < iLength; i++) { try { cTemp = sText.charAt(i); } catch (StringIndexOutOfBoundsException e8) { System.out.println("Caught StringIndexOutOfBoundsException in decrypt() (e8)."); } if (cTemp < 32 || cTemp == 127) { if (cTemp != 9 && cTemp != 10 && cTemp != 12 && cTemp != 13) { r = true; System.out.println("Unprintable on character " + (int) cTemp); break; // Break out of for loop. } } } return r; } } // End of Applet class Decrypt