JC101-4C: A basic password manager

UPDATED (07/01/08): Fixed compilation bugs.
UPDATED (20/12/11): Fixed the “public” thing.

In this first installment, we will focus on the data structure that will contain the sensitive data, as well as the identifiers. We’ll first look at the basic design, and then we’ll consider the implementation.

Design

The main design decisions are as follows:

  • The identifiers will be stored in fixed-size byte arrays, with a maximum size of 16 bytes.
  • The user names will be stored in fixed-size byte arrays, with a maximum size of 24 bytes.
  • The passwords will be stored in fixed-size byte arrays, with a maximum size of 16 bytes.
  • The elements will be linked through an unordered linked list.
  • Search will only be available on identifiers, and partial search will be available.
  • In order to support deletion, the class will manage a list of available identifiers

The main methods will be as follows:

  • A private constructor, needed to build a new instance of the password storage object when none is available.
  • A static factory method, to be called when an instance is required.
  • A delete method, to recycle an instance.
  • Getter methods for all fields (which copy data in the case of arrays).
  • A search method, which looks for the first instance that satisfies a given search pattern.
  • A search next method, which looks for the next instance that satisfies the last search pattern.

Implementation

The first thing in the implementation is to declare the class:

package com.vetilles.passwords ;

import javacard.framework.* ;

class PasswordEntry
{

We can first start by the fields representing the data of a password entry. They are all instance fields, present in every instance of the class.

  private byte[] id ;
  private byte[] userName ;
  private byte[] password ;

All these fields are byte arrays, because there is no real alternative in Java Card, as the String class is not supported. This means that the Unicode strings stored will need to be encoded in some ways, for instance UTF-8. The encoding is not an issue here, because the only processing performed on these strings are equality comparisons, which are independent of the encoding.

Since our objective is to reuse the PasswordEntry instances, the byte arrays will have a generic length, and it is recommended to store the length of the actual array contents. Since we do not expect these human-managed strings to be very long, a byte is sufficient to store this length (hence limiting the length to 127 bytes):

  private byte idLength ;
  private byte userNameLength ;
  private byte passwordLength ;

Since the fields are private, there is a need to define getter methods to retrieve the values of these fields. The first getter method is as follows:

  byte getId(byte[] buf, short ofs) {
    Util.arrayCopy(id, (short)0, buf, ofs, idLength) ;
    return idLength ;
  }

There are a few interesting things on this method. First, it copies the content instead of returning the reference to the array. This is a consequence of the object encapsulation principle: a class is responsible of ensuring that its objects are safely managed: if the reference was returned, the calling entity would then be able to modify the identifier, and this is not a desirable property.

Then, the method is not declared public. Of course, there is no real need to declare it public, because the entire application will be encapsulated in a single package, so default package visibility is sufficient. In addition, the Java Card firewall guarantees that the method, public or not, cannot be accessible from other application, because it is defined in a package that defines an Applet class. For this reason, it seems better not to declare the methods public, just because it better reflects reality.

The other getter methods are almost identical, except for the field name:

  byte getUserName(byte[] buf, short ofs) {
    Util.arrayCopy(userName, (short)0, buf, ofs, userNameLength) ;
    return userNameLength ;
  }

  byte getPassword(byte[] buf, short ofs) {
    Util.arrayCopy(password, (short)0, buf, ofs, passwordLength) ;
    return passwordLength ;
  }

Other fields are required in order to manage the data structure. They will be described in the next tutorial entry, which focuses on the management of data. The final entry on this data structure will focus on the search items.

3 Comments

  • lexdabear wrote:

    I do not know if I am missing here something or not:

    You mention that the getter method is not declared public. The entry shows it is public. The next thing is that the getters have a return value (byte), but there is no return xx included. Since the content is copied to a byte array, there is no need for a return value. Should it not be:

     public void getId(byte[] buf, short ofs) {
        Util.arrayCopy(id, 0, buf, ofs, idLength) ;
      }
    

    ?

  • First, sorry for the mishap. I have not created the Java project, so I let this very real compilation error go slip through.

    Actually, the idea was rather to make the method return the length of the object. It is quite common in Java to return a value even when it is not strictly required, since return values can easily be ignored. I here chose to return the length, because it may be a useful data, but another commonly used possibility is to return the new offset (the sum of argument ofs and of the length of the thing copied in the buffer). This is very useful to build long sequences of things.

    I have corrected the code in the post.

  • I finally created the project, and I found more compilation errors. This time, it is a missing cast. Gee, I hate those …

    I have once again corrected the post.

    Good resolution for 2008: Create projects and compile (run?) before posting.

Leave a Reply

Your email is never shared.Required fields are marked *