samedi 6 octobre 2018

java design pattern for enforcing a class prerrequisite

I am wondering what is the best design for a class-wide prerrequisite be enforced at construction time.

Let me put a simplified example.

I have a class representing a secure string, for example a Password. Passwords are only stored as their hash representation. Passwords cannot be inspected, but only checked against an attempted value.

class Password {
  private String passwordHash;
  private Password(){};
  public Password(String aPassword) {
    setPassword(aPassword);
  }
  public void setPassword(String aPassword) {
     passwordHash = hash(aPassword); 
  }
  public boolean checkPassword(String attempt) {
     return verify(attempt, passwordHash);
  }

}

The question is how to design the selection of the hashing algorithm. The client code must be able to choose from different hash algorithms. And, in a given application all passwords must use the same hash algorithm.

So, I define class wide static hasher object.

I declare a Hasher interface,

interface Hasher {
  String hash(String password);
  boolean verify(String attempt, String hash);
}

There might be different XxxxHasher implementations.

class SimpleHasher implements Hasher {
  public String hash(String password) {  // native java String.hashCode()  
    return Integer.toString(password.hashCode(),16);
  }
  public boolean verify(String attempt, String hash) {
    return attempt.hashCode()==Integer.valueOf(hash, 16);
  }  
}

class SecureHasher implements Hasher {
  public String hash(String password) {  // Secure SCrypt hash
    return com.lambdaworks.crypto.SCryptUtil.scrypt(password,16384,8,1);
  }
  public boolean verify(String attempt, String hash) {
    return com.lambdaworks.crypto.SCryptUtil.check(attempt,hash);
  }
}

The client code must choose an implementation and set the hasher. Until then, no one can instantiate a Password. And once set, the hasher cannot be changed.

Here is the design decision.

Currently, I declare a static private variable, so the hasher is the same for all Password instances; and a setter that enforces that it cannot be changed once is set.

class Password {
  static private Hasher hasher = null;;
  static public void setHasher(Hasher ahasher) throws Exception {
    if (hasher!=null) throw new Exception("hasher cannot be changed");
    hasher = ahasher
  } 
  ....      

and the constructor ensures that hasher is set

class Password {
   ...    
   public Password(String aPassword) throws Exception {
     if (hasher==null) throw new Exception("no hasher set yet");  
     setPassword(aPassword);
   } 
   ...       

so far, so good. But, in my opinion, it doesn't look quite nice. I wonder if there is some common pattern to solve this problem. So my question is if such a pattern exists and how it can be implemented in my case.

Aucun commentaire:

Enregistrer un commentaire