Encrypting/decrypting using RC2

RC2 stands for Rivest’s Code 2. More information can be found on the RSA Security site.

Main.java:

import javax.crypto.spec.*;
import java.security.*;
import javax.crypto.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      String toEncrypt = "The shorter you live, the longer you're dead!";
 
      System.out.println("Encrypting...");
      byte[] encrypted = encrypt(toEncrypt, "password");
 
      System.out.println("Decrypting...");
      String decrypted = decrypt(encrypted, "password");
    
      System.out.println("Decrypted text: " + decrypted);
   } 
 
   public static byte[] encrypt(String toEncrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("RC2");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // create an instance of cipher
      Cipher cipher = Cipher.getInstance("RC2");
 
      // initialize the cipher with the key
      cipher.init(Cipher.ENCRYPT_MODE, sk);
 
      // enctypt!
      byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
 
      return encrypted;
   }
 
   public static String decrypt(byte[] toDecrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("RC2");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // do the decryption with that key
      Cipher cipher = Cipher.getInstance("RC2");
      cipher.init(Cipher.DECRYPT_MODE, sk);
      byte[] decrypted = cipher.doFinal(toDecrypt);
 
      return new String(decrypted);
   }
}

(tested with the BouncyCastle JCE provider, http://www.bouncycastle.org)

Performing authentication with JAAS

Authentication

The authentication component of JAAS can determine who is executing code. It’s against useability to have a user on a system remember different passwords, one for each program where authentication is required. If a user on a system is used to identifying himself by means of a fingerprint device, the ideal situation would be to do the same for your new Java application that requires authentication. JAAS uses a pluggable architecture for authentication called PAM, Pluggable Authentication Module. This allows for integration of existing PAM-enabled authentication mechanisms with your program. So vendors can write authentication modules for different types of login systems. More information about PAM can be found here.

The following example will show how to build an authentication module. The following steps are executed in trying to authenticate a subject:

  1. Instantiate a LoginContext
  2. The LoginContext loads one or more LoginModules described in a Configuration
  3. login() is called on the instantiated LoginContext
  4. The LoginModules are consulted to see if the user can be authenticated and if so, principals and credentials are associated with the subject
  5. If the status of the login is positive, the subject can be retrieved. Otherwise, a LoginException is thrown.

Here is a small example that will ask a user for his username and password and consults a text file to determine if that user has the necessary permissions to continue.

First we create a “database” textfile that contains a list of user entries that can be successfully authenticated in the form username,password.
passwd:

johndoe,sdefujm
janedoe,yuymndee

Then we write our authentication module.

UsernamePasswordLoginModule.java:

import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
import javax.security.auth.*;
import java.security.*;
import java.util.*;
import java.io.*;
 
public class UsernamePasswordLoginModule implements LoginModule {
   private Subject subject;
   private CallbackHandler callbackHandler;
 
   private String username;
   private char[] password;
   private boolean loginSucceeded = false;
   private boolean commitSucceeded = false;
  
   private Principal principal;
 
   public void initialize(Subject subject, CallbackHandler callbackHandler, 
                          Map sharedState, Map options) {
      System.out.println("LoginModule initialize()");
      this.subject = subject;
      this.callbackHandler = callbackHandler;
      username = null;
      clearPassword();
      loginSucceeded = false;
      commitSucceeded = false;
   }
 
   public boolean login() throws LoginException {
      System.out.println("LoginModule login()");
      if (callbackHandler == null) {
         throw new LoginException("No CallbackHandler!");
      }
 
      Callback[] callbacks = new Callback[2];
      callbacks[0] = new NameCallback("Username: ");
      callbacks[1] = new PasswordCallback("Password: ", false);
 
      try {
         callbackHandler.handle(callbacks);
         username = ((NameCallback) callbacks[0]).getName();
         char[] temp = ((PasswordCallback) callbacks[1]).getPassword();
         password = new char[temp.length];
         System.arraycopy(temp, 0, password, 0, temp.length);
 
         BufferedReader br = new BufferedReader(new FileReader("passwd"));
         String line;
         while ((line = br.readLine()) != null) {
            int comma = line.indexOf(',');
            String un = line.substring(0, comma);
            String pw = line.substring(comma+1);
 
            if (username.equals(un) && new String(password).equals(pw)) {
               // succeeded!
               loginSucceeded = true;
               return true;
            }
         }
      }
      catch(IOException e) {
         throw new LoginException(e.toString());
      }
      catch(UnsupportedCallbackException e) {
         throw new LoginException(e.toString());
      }
 
      username = null;
      clearPassword();
      loginSucceeded = false;
 
      throw new FailedLoginException("Incorrect Username/Password");
   }
 
   public boolean commit() throws LoginException {
      System.out.println("LoginModule commit()");

      if (loginSucceeded == false) {
         return false;
      }
 
      principal = new MyPrincipal(username);
      if (!(subject.getPrincipals().contains(principal))) {
         subject.getPrincipals().add(principal);
      }
 
      username = null;
      clearPassword();
      commitSucceeded = true;
       
      return true;
   }
  
   public boolean abort() throws LoginException {
      System.out.println("LoginModule abort()");

      if (!loginSucceeded) {
         return false;
      }
      else if (loginSucceeded && commitSucceeded) {
         loginSucceeded = false;
         username = null;
         clearPassword();
         principal = null;
      }
      else {
         logout();
      }
 
      return true;
   }
 
   public boolean logout() throws LoginException {
      System.out.println("LoginModule logout()");

      subject.getPrincipals().remove(principal);
      loginSucceeded = false;
      commitSucceeded = false;
      username = null;
      clearPassword();
      principal = null;
 
      return true;
   }
 
   private void clearPassword() {
      if (password != null) {
         for (int i=0; i<password.length; i++) {
            password[i] = ' ';
         }
         password = null;
      }
   }
}

This implementation of LoginModule contains the code to check whether a user is permitted to log in or not. You can provide multiple login modules, checking several sources for authentication. Our module checks whether a username and password exists in our database textfile passwd. Its task is to determine if a username/password pair (the subject) should be authenticated and if success it should add principals to that subject. When a user is asked to be authenticated, JAAS calls the methods in our LoginModule in a certain order. initialize() will be called with certain state information, most importantly the subject to be authenticated and an instance of CallbackHandler that is used later on to get the login information from the user.

  • login() first creates a set of Callbacks, one for the username and one for the password. After we call handle() on our CallbackHandler, the username/password pair should be filled in in both of these callback objects. In this case (see below), a Swing dialog will pop up and ask the user for his username and password. But it can be anything else to get the user’s info, for example by using the information on the currently logged in user on a Windows NT domain. After we get the username/password information from the user, we check whether they exist in the passwd file.
  • commit() will be called when login was successful. It should fill up the subject with the associated principals and credentials and clean up the state.
  • abort() will be called to abort the authentication procedure when either one of the login() or the commit() method fails.
  • logout() will be called when a user is ready to log out.

    For more information on how to write a LoginModule, check out JAAS LoginModule’s Developer’s Guide.

    Our Main program looks like this:

    Main.java:

    import com.sun.security.auth.callback.*;
    import javax.security.auth.login.*;
    import javax.security.auth.*;
    import java.security.*;
     
    public class Main {
       public static void main(String []args) throws Exception { 
          try {
             LoginContext loginContext = new LoginContext("MyAuthenticationComponents", 
                                                 new DialogCallbackHandler());
     
             // will throw a LoginException if it fails, falls through otherwise
             loginContext.login();
     
             Subject subject = loginContext.getSubject();
             System.out.println(subject);
     
             loginContext.logout();
          }
          catch(LoginException e) {
             System.out.println("Unauthorized user!");
          } 
     
          // stop AWT thread (DialogCallbackHandler)
          System.exit(0);
       }
    }

    You create an instance of LoginContext, a class able to authenticate subjects. You need to pass in a String that determines the LoginModules that will be used in authenticating a subject. In our example, we use MyAuthenticationComponents (look at the jaas.config file below). If no LoginException was thrown, the subject is printed out. Notice that we use the Sun undocumented class DialogCallbackHandler that will pop up a dialogbox to ask the user for a username and password.

    jaas.config:

    MyAuthenticationComponents {
       UsernamePasswordLoginModule required;
    };

    This configuration file specifies the module that should be used to authenticate the user. The required flag specifies that the result of the module must be successful in order for the entire login to succeed. You may specify several login modules with different flags. Other flags are Requisite, Sufficient and Optional. Check out this article for more information on these flags.

    Finally we have a MyPrincipal object that implements the Principal interface and encapsulates a subject’s identify.

    MyPrincipal.java:

    import java.security.*;
    import java.io.*;
     
    public class MyPrincipal implements Principal, Serializable
    {
       private String name;
    
       public MyPrincipal(String name) {
          this.name = name;
       }
      
       public String getName() {
          return name;
       }
      
       public int hashCode() {
          return name.hashCode();
       }
     
       public String toString() {
          return getName();
       }
     
       public boolean equals(Object obj) {
          if (obj == null) {
             return false;
          }
     
          if (!(obj instanceof MyPrincipal)) {
             return false;
          }
     
          MyPrincipal mp = (MyPrincipal) obj;
          if (name.equals(mp.getName())) {
             return true;
          }
     
          return false;
       }
    }

    To run this code, we need to specify the configuration file to be used. You can do that by specifying the System property java.security.auth.login.config at command line:

     c:jdk1.4binjava -Djava.security.auth.login.config==jaas.config Main

    Alternatively, it can be configured in the java.security properties file. Check out this reference for more information.

    Output with username=johndoe, password=sdefujm:

    LoginModule initialize()
    LoginModule login()
    LoginModule commit()
    Subject:
    	Principal: johndoe
    LoginModule logout()

    Output with username=johndoe, password=abcdefg:

    LoginModule initialize()
    LoginModule login()
    LoginModule abort()
    Unauthorized user!

Getting the number of days in a month in Java

You can set the Calendar instance with the highest number possible for months. If the actual number of days in that month is smaller than that maximum, the Calendar instance will automatically change the month (so for example if you would say “the 40th of January 2000″, Calendar will change this to “the 9th of February 2000″). So roll back the Calendar by one day every time until the member month of calendar turns out to be the month you are looking for.

Main.java:

import java.util.*;
 
public class Main {
   public static void main(String args[]) throws Exception {
      Calendar calendar = Calendar.getInstance();
      calendar.set(2002, Calendar.FEBRUARY, calendar.getMaximum(Calendar.DAY_OF_MONTH));
 
      while (calendar.get(Calendar.MONTH) != Calendar.FEBRUARY) {
         calendar.add(Calendar.DAY_OF_MONTH, -1);
      }
 
      System.out.println("Number of days: " + calendar.get(Calendar.DAY_OF_MONTH));
   }
}

outputs:

Number of days: 28

Creating a java.util.logging.LogRecord

Main.java:

import java.util.logging.*;
import java.io.*;
 
public class Main
{
   public static void main(String argv[]){
      Logger logger = Logger.getLogger("main");
      logger.setUseParentHandlers(false);
      ConsoleHandler ch = new ConsoleHandler();
      ch.setLevel(Level.ALL);
      logger.addHandler(ch);
 
      ch.setFormatter(new XMLFormatter());

      LogRecord logRecord = new LogRecord(Level.SEVERE, "Something went seriously wrong");
      logRecord.setMillis(1000);
      logRecord.setParameters(new Object[] { "param1", "param2" });
      logRecord.setSequenceNumber(123456);
      logRecord.setSourceClassName(Main.class.getName());
      logRecord.setSourceMethodName("main");

      logger.log(logRecord); 
   }
}

outputs:

<? xml version="1.0" encoding="windows-1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>1969-12-31T16:00:01</date>
  <millis>1000</millis>
  <sequence>123456</sequence>
  <level>SEVERE</level>
  <class>Main</class>
  <method>main</method>
  <thread>10</thread>
  <message>Something went seriously wrong</message>
</record>

Listing all System properties in Java

import java.util.*;
 
public class Main
{
   public static void main(String[] args) {
      Properties props = System.getProperties();
      
      Enumeration enum = props.propertyNames();
      while (enum.hasMoreElements()) {
         String prop = (String) enum.nextElement();
         printInColumn(prop, 40);
         printInColumn(System.getProperty(prop), 39);
         System.out.println();
      }
   }
 
   public static void printInColumn(String s, int col) {
      if (s.length() > col-2) s = s.substring(0, col-2);
      System.out.print(s);
      for (int i=s.length(); i<col; ++i)
         System.out.print(" ");
   }
}

outputs:

java.specification.name                 Java Platform API Specification        
awt.toolkit                             sun.awt.windows.WToolkit               
java.version                            1.2.2                                  
java.awt.graphicsenv                    sun.awt.Win32GraphicsEnvironment       
user.timezone                           Europe/Paris                           
java.specification.version              1.2                                    
java.vm.vendor                          Sun Microsystems Inc.                  
user.home                               C:WINDOWS                             
java.vm.specification.version           1.0                                    
os.arch                                 x86                                    
java.awt.fonts                                                                 
java.vendor.url                         http://java.sun.com/                   
user.region                             US                                     
file.encoding.pkg                       sun.io                                 
java.home                               C:JDK1.2.2JRE                        
java.class.path                         ;c:java  
line.separator                          
                                     
java.ext.dirs                           C:JDK1.2.2JRElibext                
java.io.tmpdir                          c:windowsTEMP                       
os.name                                 Windows 95                             
java.vendor                             Sun Microsystems Inc.                  
java.awt.printerjob                     sun.awt.windows.WPrinterJob            
java.library.path                       C:JDK1.2.2BIN;.;C:WINDOWSSYSTEM;C  
java.vm.specification.vendor            Sun Microsystems Inc.                  
sun.io.unicode.encoding                 UnicodeLittle                          
file.encoding                           Cp1252                                 
java.specification.vendor               Sun Microsystems Inc.                  
user.language                           en                                     
user.name                               joris                                  
java.vendor.url.bug                     http://java.sun.com/cgi-bin/bugreport  
java.vm.name                            Classic VM                             
java.class.version                      46.0                                   
java.vm.specification.name              Java Virtual Machine Specification     
sun.boot.library.path                   C:JDK1.2.2JREbin                    
os.version                              4.10                                   
java.vm.version                         1.2.2                                  
java.vm.info                            build JDK-1.2.2_005, native threads,   
java.compiler                           symcjit                                
path.separator                          ;                                      
file.separator                                                                
user.dir                                C:My DocumentsVisual Studio Project  
sun.boot.class.path                     C:JDK1.2.2JRElibrt.jar;C:JDK1.2.  

Listing the files that are contained in a Zip file

Extremely simple! Create an instance of ZipFile and enumerate its ZipEntries:

import java.io.*;
import java.util.*;
import java.util.zip.*;
 
public class Main
{
   public static void main(String[] args) throws IOException 
   {
      if (args.length != 1) {
         System.out.println("Usage: java Main <file.zip>");
         System.exit(1);
      }
 
      listContents(args[0]);
   }
 
   public static void listContents(String zipfilename) throws IOException {
      ZipFile zip = new ZipFile(zipfilename);
 
      for (Enumeration e=zip.entries(); e.hasMoreElements(); ) {
         ZipEntry ze = (ZipEntry) e.nextElement();
         System.out.println(ze.getName());
      }
   }
}

Sample output of esustools.zip:

com/
com/esus/
com/esus/security/
com/esus/security/DES.java
com/esus/security/MD5.java
com/esus/security/MD5.class
com/esus/security/KeyUtils.java
com/esus/security/KeyUtils.class
com/esus/security/DES.class
com/esus/security/CryptException.java
com/esus/security/CryptException.class
...

Retrieving the links in an HTML document in Java

You can use the HTMLEditorKit that includes an HTML parser. Have it parse your HTML and then enumerate the href attribute of all the “A” tags:

import javax.swing.text.html.*;
import javax.swing.text.*;
import java.util.*;
import java.net.*;
import java.io.*;
     
public class Main
{ 
   public static void main(String[] args) throws Exception {
      Vector v = getLinks(new URL("http://www.google.com"));
 
      for (int i=0; i<v.size(); i++) {
         System.out.println(v.elementAt(i));
      }
 
      System.exit(0);
   }
 
   public static Vector getLinks(URL url) throws Exception {
      Vector v = new Vector();
 
      URLConnection conn = url.openConnection();
      Reader r = new BufferedReader(new InputStreamReader(conn.getInputStream()));
      HTMLEditorKit editorKit = new HTMLEditorKit();
      Document doc = editorKit.createDefaultDocument();
 
      // The Document class does not yet handle charset's properly.
      doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
 
      try {
         editorKit.read(r, doc, 0);
 
         // loop through the HTML A tag elements 
         ElementIterator it = new ElementIterator(doc);
         Element elem;
         while ((elem = it.next()) != null) {
            SimpleAttributeSet s = (SimpleAttributeSet) elem.getAttributes().getAttribute(HTML.Tag.A);
            if (s != null) {
               v.addElement(s.getAttribute(HTML.Attribute.HREF));
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
 
      return v;
   }
}

Creating a Menu for a JFrame

This example creates a JFrame, and puts a raised menubar on it, and menu items on the menubar. It also applies acclerators and mnemonics to the menu items and assigns listeners.

MyFrame.java:

import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.border.*;
import javax.swing.KeyStroke;
import javax.swing.JOptionPane;
import java.awt.Component;
 
public class MyFrame extends JFrame {
 
   public static void main(String args[]) {
 
      MyFrame main = new MyFrame();
 
      // center frame on screen
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
      main.setBounds(d.width/2-100, d.height/2-75, 200, 150);
 
      main.pack();
      main.setSize(200, 150); //set frame size
           
      main.setVisible(true);     
   } 
 
   public MyFrame() {
      super("Menu Example");
 
      this.addWindowListener(new WindowEventHandler()); 
         
      Container container = this.getContentPane();
 
      JMenu filemenu = new JMenu("Document");
      filemenu.setMnemonic(KeyEvent.VK_D);
 
      JMenuBar bar = new JMenuBar();
      bar.setBorder(new BevelBorder(BevelBorder.RAISED));
      container.add(bar);
      setJMenuBar(bar);
 
      JMenuItem connect = new JMenuItem("Open");
      connect.addActionListener(new openListener());
      connect.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 
                                         Event.CTRL_MASK, false));
      connect.setMnemonic('O');
 
      JMenuItem exit = new JMenuItem("Exit");
      exit.addActionListener(new exitListener());
      exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, 
                                         Event.CTRL_MASK, false));
      exit.setMnemonic('X');
 
      filemenu.add(connect);
      filemenu.add(exit);
      bar.add(filemenu);
   }
 
   class WindowEventHandler extends WindowAdapter {
      public void windowClosing(WindowEvent evt) {          
         System.exit(0);
      }
   }
 
   class exitListener implements ActionListener {
      public void actionPerformed(ActionEvent l){
         System.exit(0);
      } 
   } 
 
   class openListener implements ActionListener {
      JFrame f = new JFrame();
 
      public void actionPerformed(ActionEvent l){
         JOptionPane.showMessageDialog(f, "OPEN");
      }
   }
}

Force the scrollbars to be there even when they’re not needed

   int hPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS;
   int vPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
 
   JPanel drawSurface = new JPanel();
   JScrollPane editorField;

= = = = = = = = = = = = =
(in constructor….)

   editorField = new JScrollPane(drawSurface);
   editorField.setHorizontalScrollBarPolicy(hPolicy);
   editorField.setVerticalScrollBarPolicy(vPolicy);

= = = = = = = = = = = = = = = = = = = = =
in essence all you need to do is set the individual scroll
bar policies to the constants defined in JScrollPane.