[Webfunds-commits] java/webfunds/token/algorithm AbstractBlindedToken.java AbstractPrivateTokenData.java AbstractProtoToken.java AbstractPublicTokenData.java AbstractToken.java ChaumBlindedToken.java ChaumPrivateTokenData.java ChaumProtoToken.java ChaumPublicTokenData.java ChaumToken.java RandomBlindedToken.java RandomPrivateTokenData.java RandomProtoToken.java RandomPublicTokenData.java RandomToken.java

Edwin Woudt edwin@cypherpunks.ai
Thu, 28 Dec 2000 18:13:00 -0400 (AST)


edwin       00/12/28 18:13:00

  Added:       webfunds/token DataFormatException.java
                        UnsupportedVersionException.java
               webfunds/token/algorithm AbstractBlindedToken.java
                        AbstractPrivateTokenData.java
                        AbstractProtoToken.java
                        AbstractPublicTokenData.java AbstractToken.java
                        ChaumBlindedToken.java ChaumPrivateTokenData.java
                        ChaumProtoToken.java ChaumPublicTokenData.java
                        ChaumToken.java RandomBlindedToken.java
                        RandomPrivateTokenData.java RandomProtoToken.java
                        RandomPublicTokenData.java RandomToken.java
  Log:
  Initial part of a general purpose token library for webfunds, which provides
  an abstraction layer for token payments, such that webfunds can support
  different token protocols with minimal effort.
  
  On top of the basic algorithms, it will also provide database functions for:
  local coin storage, temporary protocoin storage, double-spent databases and
  other data that needs to be stored. Most of the database management will happen
  automagically and invisible to the application. At first, a simple coin
  management algorithm will be implemented, while later on more sophisticated
  algorithms can be implemented that better protect against traffic analysis.
  
  It will NOT contain any data transport related stuff: the application should
  provide reliable and secure data transport between server and client. SOX is a
  good candidate for this.
  
  Ideally, while it does control the data in the database, it will also not
  contain the database itself. These should be provided by the application as the
  application needs to control where the files are stored. It looks like the
  classes in webfunds.store are the ideal choice for this function, but I'll
  have to look closer to be sure.
  
  Only the core algorithmic classes are here now. When finished, this library
  will contain three packages:
  - webfunds.token
  - webfunds.token.algorithm
  - webfunds.token.database
  The application will only need to call webfunds.token classes: These classes
  will invoke the right classes in the other two packages.
  
  Current status: far from done and untested (though it does compile), but
  committed here to seek comments.

Revision  Changes    Path
1.1                  java/webfunds/token/DataFormatException.java

Index: DataFormatException.java
===================================================================
/* $Id: DataFormatException.java,v 1.1 2000/12/28 22:12:56 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token;

/**
 * Thrown when invalid data is decoded.
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public class DataFormatException extends Exception {

    public DataFormatException() {
        super();
    }

    public DataFormatException(String msg) {
        super(msg);
    }

}



1.1                  java/webfunds/token/UnsupportedVersionException.java

Index: UnsupportedVersionException.java
===================================================================
/* $Id: UnsupportedVersionException.java,v 1.1 2000/12/28 22:12:56 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token;

/**
 * Thrown when an unsupported version is encountered.
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public class UnsupportedVersionException extends DataFormatException {

    public UnsupportedVersionException() {
        super();
    }

    public UnsupportedVersionException(String msg) {
        super(msg);
    }

}



1.1                  java/webfunds/token/algorithm/AbstractBlindedToken.java

Index: AbstractBlindedToken.java
===================================================================
/* $Id: AbstractBlindedToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public abstract class AbstractBlindedToken {


// Init methods
//.............................................................................

    public abstract void decode(byte[] data, int start, int len);


// Information retrieval methods
//.............................................................................

    public abstract long getSeries();
    
    public abstract long getValue(AbstractPrivateTokenData privdata);
    

// Processing methods
//.............................................................................

    public abstract void sign(SecureRandom sr, 
                              AbstractPrivateTokenData privdata);


// Output methods
//.............................................................................

    public abstract byte[] encode();
    

// Challenge/response methods
//.............................................................................
    
    public boolean needsClientChallenge() { return false; }
    public boolean needsServerChallenge() { return false; }

    public byte[] getClientChallenge(SecureRandom sr, 
                                     AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "getClientChallenge method, while "+
                                   "needsClientChallenge returns true.");
    }

    public boolean verifyClientResponse(byte[] response, SecureRandom sr,
                                        AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "verifyClientResponse method, while "+
                                   "needsClientChallenge returns true.");
    }
    
    public byte[] getServerResponse(byte[] challenge, SecureRandom sr,
                                    AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "getServerResponse method, while "+
                                   "needsServerChallenge returns true.");
    }


}



1.1                  java/webfunds/token/algorithm/AbstractPrivateTokenData.java

Index: AbstractPrivateTokenData.java
===================================================================
/* $Id: AbstractPrivateTokenData.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;

import java.util.Date;

import webfunds.token.DataFormatException;
import webfunds.token.UnsupportedVersionException;

/**
 * Abstraction for private (key) data.
 *
 * <p>
 * This class (and it's sister AbstractPublicTokenData) provide an abstraction
 * for series-wide data used by the blinding protocol. This is usually somewhat
 * related to cryptographic keys, but it can be any information the particular
 * protocol needs.
 * </p><p>
 * For each series of tokens a pair of AbstractPrivateTokenData and 
 * AbstractPublicTokenData objects will be created. The private object is kept
 * at the server and used to sign the tokens, the public object is sent to the
 * client and used by the client to construct the protocoins and to verify that
 * the server doesn't cheat. A subclass will thus have to add it's own methods
 * to provide the protocol-specific data to it's Token counterparts.
 * </p><p>
 * There is no need to store cryptographic keys in this class for transport
 * security as subclasses can assume that all traffic between client and server
 * will be encrypted by the application. This class does however handle the
 * signing of the public data.
 * </p><p>
 * In the remainder of this file, two groups of programmers will be used for
 * specific notes and instuctions: users and developers. Users are programmers
 * who develop applications that use these classes. Developers are programmers
 * who extend these classes to add a new blinding protocol.
 * </p><p>
 * <h3>State diagram</h3>
 * </p><p>
 * The state diagram below details in what order methods can be called.
 * After constructing the object, it is in the 'EMPTY' state.
 * </p>
 * <pre>Legend: X = method call allowed in this state
 *              - = method call causes transition to this state (if no minus is
 *                  present for a certain method than no transition will occur)
 *
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 * generate                 X      -
 * decode            (1)    X                     -
 * decodePrivateImpl (1)                          X       -
 * decodePublicImpl  (1)                                  X      -
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 * getDenominations                X      X                      X
 * getSeries                       X      X                      X
 * getExpiryDate                   X      X                      X
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 * sign                            X      -
 * verify                                 X       X       X      X
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 * encodePublicDataImpl            X         
 * encodePublicData                       X
 * encodePrivateDataImpl           X
 * encodePrivateData                      X
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 * Other methods     (2)                                         X
 *                        EMPTY  NOSIG  SIGNED  DECOD1  DECOD2  READ
 *
 * </pre>
 * <p>
 * Notes:<br>
 * (1): decode calls decodePrivateImpl and decodePublicImpl (in that order), so
 *      in fact three state transitions will occure on one call to decode
 * (2): other methods are subclass specific methods that provide protocol 
 *      specific data. <br>
 * </p>
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public abstract class AbstractPrivateTokenData {

// Constants
//.............................................................................

    /* package */ static final int MAJOR_VERSION = 1;
    /* package */ static final int MINOR_VERSION = 0;


// Instance variables
//.............................................................................

    /** Contains the binary signature data */
    private byte[] sigdata = null;
    /** Contains the binary private data */
    private byte[] privdata = null;
    /** Contains the binary public data */
    private byte[] pubdata = null;


// Abstract init methods
//.............................................................................

    public abstract void generate(SecureRandom sr, long[] denominations,
                                  long series, Date expiry);

    protected abstract void decodePrivateImpl(byte[] data, int start, int len);
    protected abstract void decodePublicImpl(byte[] data, int start, int len);
    

// Abstract information retrieval methods
//.............................................................................

    public abstract long[] getDenominations();
    
    public abstract long getSeries();

    public abstract Date getExpiryDate();


// Abstract output methods
//.............................................................................

    protected abstract byte[] encodePublicDataImpl();
    
    protected abstract byte[] encodePrivateDataImpl();


// Signature methods
//.............................................................................

    public final void sign(PrivateKey pk, String alg, String provider,
                           SecureRandom sr) 
    throws NoSuchAlgorithmException, NoSuchProviderException,
           InvalidKeyException 
    {

        // @@@ ASSERT
        if (pk == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (alg == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sr == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sigdata != null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata != null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (privdata != null) 
            throw new InternalError("Assertion failed");


        Signature sig;
        if (provider == null) {
            sig = Signature.getInstance(alg);
        } else {
            sig = Signature.getInstance(alg, provider);
        }
        
        // ### Note: the first line is needed for compilation on JDK 1.1.
        // ### Preferably it should be changed to the second line when JDK 1.2 
        // ### can be expected.
        sig.initSign(pk);           // JDK 1.1+
        //sig.initSign(pk,sr);      // JDK 1.2+
        
        
        // Fetch the public data for signing
        pubdata = encodePublicDataImpl();

        // Fetching the private here does not make much sense at first sight
        // because we don't need it for signing. However, this method results
        // in a state transition to the SIGNED state and in that state it is
        // not correct anymore to call encodePrivateDataImpl() as is defined
        // at the top of this file.
        // The reasoning behind this is that maybe someday it does make sense
        // to sign the private data as well.
        privdata = encodePrivateDataImpl();
        
        try {

            sig.update(pubdata);
            sigdata = sig.sign();

        } catch (SignatureException se) {

            // According to the SUN documentation, this exception will only be
            // thrown "if this signature object is not initialized properly."
            // This is impossible, because we've called sig.initSign above.
            throw new InternalError("SignatureException caught: should not "+
                                    "happen. "+se);
        }


        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (privdata == null) 
            throw new InternalError("Assertion failed");

    }
    
    public final boolean verify(PublicKey pk, String alg, String provider)
    throws NoSuchAlgorithmException, NoSuchProviderException,
           InvalidKeyException, SignatureException
    {

        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (privdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pk == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (alg == null) 
            throw new InternalError("Assertion failed");


        Signature sig;
        if (provider == null) {
            sig = Signature.getInstance(alg);
        } else {
            sig = Signature.getInstance(alg, provider);
        }
        
        sig.initVerify(pk);
        sig.update(pubdata);
        return sig.verify(sigdata);
        
    }


// Public non-abstract encode/decode methods
//.............................................................................

    public final void decode(byte[] data, int start, int len) 
    throws DataFormatException, UnsupportedVersionException
    {

        // @@@ ASSERT
        if (sigdata != null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata != null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (privdata != null) 
            throw new InternalError("Assertion failed");
        
        
        // read and check identifier and version
        
        if (len < 8) throw new DataFormatException("Blob too small");
        
        int pos = start;
        
        if ((data[pos++] != 84) &&    // 'T'
            (data[pos++] != 75) &&    // 'K'
            (data[pos++] != 83) &&    // 'S'
            (data[pos++] != 68))      // 'D'
        {
            throw new DataFormatException("Wrong identifier string");
        }
        
        int majorVersion = (((int)(data[pos++])) << 8) + ((int)(data[pos++]));
        int minorVersion = (((int)(data[pos++])) << 8) + ((int)(data[pos++]));
        
        if (majorVersion > MAJOR_VERSION) {
            throw new UnsupportedVersionException("Unsupported version");
        }
        

        // read private data
        
        if (pos+4 > start+len) 
            throw new DataFormatException("Blob too small");
        
        int lenpriv = (((int)(data[pos++])) << 24) +
                      (((int)(data[pos++])) << 16) +
                      (((int)(data[pos++])) <<  8) +
                      (((int)(data[pos++])) <<  0);
        
        if (pos+lenpriv > start+len)
            throw new DataFormatException("Blob too small");
        
        privdata = new byte[lenpriv];
        System.arraycopy(data, pos, privdata, 0, lenpriv);
        pos += lenpriv;
        

        // read public data
        
        if (pos+4 > start+len) 
            throw new DataFormatException("Blob too small");
        
        int lenpub = (((int)(data[pos++])) << 24) +
                     (((int)(data[pos++])) << 16) +
                     (((int)(data[pos++])) <<  8) +
                     (((int)(data[pos++])) <<  0);
        
        if (pos+lenpub > start+len)
            throw new DataFormatException("Blob too small");
        
        pubdata = new byte[lenpub];
        System.arraycopy(data, pos, pubdata, 0, lenpub);
        pos += lenpub;
        

        // read signature data
        
        if (pos+4 > start+len) 
            throw new DataFormatException("Blob too small");
        
        int lensig = (((int)(data[pos++])) << 24) +
                     (((int)(data[pos++])) << 16) +
                     (((int)(data[pos++])) <<  8) +
                     (((int)(data[pos++])) <<  0);
        
        if (pos+lensig > start+len)
            throw new DataFormatException("Blob too small");
        
        sigdata = new byte[lensig];
        System.arraycopy(data, pos, sigdata, 0, lensig);
        pos += lensig;
        
        
        // If this is a future version, more data could follow.
        // However, if we know the version, then check if we've reached the end.
        if ((minorVersion <= MINOR_VERSION) || (majorVersion < MAJOR_VERSION)) {
            if (pos != start+len) {
                throw new DataFormatException("Blob too large");
            }
        }
        
        
        // Call the decode methods of the subclass
        decodePrivateImpl(privdata, 0, privdata.length);
        decodePublicImpl(pubdata, 0, privdata.length);
        

        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (privdata == null) 
            throw new InternalError("Assertion failed");

    }

    public final byte[] encodePublicData() {
        
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata.length <= 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sigdata.length <= 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (MAJOR_VERSION < 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (MINOR_VERSION < 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT   ### FIXME: support versions > 255
        if (MAJOR_VERSION > 255) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT   ### FIXME: support versions > 255
        if (MINOR_VERSION > 255) 
            throw new InternalError("Assertion failed");


        byte[] id      = {84, 75, 80, 68};     // 'TKPD' = ToKen Public Data
        // ### FIXME: support versions > 255
        byte[] version = { 0, MAJOR_VERSION, 0, MINOR_VERSION}; 

        byte[] lenpub = new byte[4];
        lenpub[0] = (byte)((pubdata.length >> 24) & 0xFF);
        lenpub[1] = (byte)((pubdata.length >> 16) & 0xFF);
        lenpub[2] = (byte)((pubdata.length >>  8) & 0xFF);
        lenpub[3] = (byte)((pubdata.length >>  0) & 0xFF);

        byte[] lensig = new byte[4];
        lensig[0] = (byte)((sigdata.length >> 24) & 0xFF);
        lensig[1] = (byte)((sigdata.length >> 16) & 0xFF);
        lensig[2] = (byte)((sigdata.length >>  8) & 0xFF);
        lensig[3] = (byte)((sigdata.length >>  0) & 0xFF);

        byte[] result = new byte[id.length     + version.length 
                               + lenpub.length + pubdata.length 
                               + lensig.length + sigdata.length];

        int pos = 0;

        System.arraycopy(id, 0, result, pos, id.length);
        pos += id.length;
        System.arraycopy(id, 0, result, pos, version.length);
        pos += version.length;

        System.arraycopy(id, 0, result, pos, lenpub.length);
        pos += lenpub.length;
        System.arraycopy(id, 0, result, pos, pubdata.length);
        pos += pubdata.length;

        System.arraycopy(id, 0, result, pos, lensig.length);
        pos += lensig.length;
        System.arraycopy(id, 0, result, pos, sigdata.length);
        pos += sigdata.length;
        
        // @@@ ASSERT
        if (pos != result.length) throw new 
            InternalError("Assertion failed");

        return result;
        
    }
    
    public final byte[] encodePrivateData() {
        
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata.length <= 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (sigdata.length <= 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (MAJOR_VERSION < 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (MINOR_VERSION < 0) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT   ### FIXME: support versions > 255
        if (MAJOR_VERSION > 255) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT   ### FIXME: support versions > 255
        if (MINOR_VERSION > 255) 
            throw new InternalError("Assertion failed");


        byte[] id      = {84, 75, 83, 68};     // 'TKSD' = ToKen Secret Data
        // ### FIXME: support versions > 255
        byte[] version = { 0, MAJOR_VERSION, 0, MINOR_VERSION}; 

        byte[] lenpriv = new byte[4];
        lenpriv[0] = (byte)((pubdata.length >> 24) & 0xFF);
        lenpriv[1] = (byte)((pubdata.length >> 16) & 0xFF);
        lenpriv[2] = (byte)((pubdata.length >>  8) & 0xFF);
        lenpriv[3] = (byte)((pubdata.length >>  0) & 0xFF);

        byte[] lenpub = new byte[4];
        lenpub[0] = (byte)((pubdata.length >> 24) & 0xFF);
        lenpub[1] = (byte)((pubdata.length >> 16) & 0xFF);
        lenpub[2] = (byte)((pubdata.length >>  8) & 0xFF);
        lenpub[3] = (byte)((pubdata.length >>  0) & 0xFF);

        byte[] lensig = new byte[4];
        lensig[0] = (byte)((sigdata.length >> 24) & 0xFF);
        lensig[1] = (byte)((sigdata.length >> 16) & 0xFF);
        lensig[2] = (byte)((sigdata.length >>  8) & 0xFF);
        lensig[3] = (byte)((sigdata.length >>  0) & 0xFF);

        byte[] result = new byte[id.length      + version.length + 
                               + lenpriv.length + privdata.length 
                               + lenpub.length  + pubdata.length 
                               + lensig.length  + sigdata.length];

        int pos = 0;

        System.arraycopy(id, 0, result, pos, id.length);
        pos += id.length;
        System.arraycopy(id, 0, result, pos, version.length);
        pos += version.length;

        System.arraycopy(id, 0, result, pos, lenpriv.length);
        pos += lenpriv.length;
        System.arraycopy(id, 0, result, pos, privdata.length);
        pos += privdata.length;

        System.arraycopy(id, 0, result, pos, lenpub.length);
        pos += lenpub.length;
        System.arraycopy(id, 0, result, pos, pubdata.length);
        pos += pubdata.length;

        System.arraycopy(id, 0, result, pos, lensig.length);
        pos += lensig.length;
        System.arraycopy(id, 0, result, pos, sigdata.length);
        pos += sigdata.length;
        
        // @@@ ASSERT
        if (pos != result.length) throw new 
            InternalError("Assertion failed");

        return result;

    }


}



1.1                  java/webfunds/token/algorithm/AbstractProtoToken.java

Index: AbstractProtoToken.java
===================================================================
/* $Id: AbstractProtoToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public abstract class AbstractProtoToken {


// Init methods
//.............................................................................

    public abstract void generate(SecureRandom sr, long value, 
                                  AbstractPublicTokenData pubdata);


// Output methods
//.............................................................................

    public abstract byte[] encodeProtocoin();
    
    public abstract byte[] encodeBlindingFactor();


// Challenge/response methods
//.............................................................................
    
    public byte[] getClientResponse(byte[] challenge, SecureRandom sr,
                                    AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "getServerResponse method, while "+
                                   "needsClientChallenge returns true.");
    }


}



1.1                  java/webfunds/token/algorithm/AbstractPublicTokenData.java

Index: AbstractPublicTokenData.java
===================================================================
/* $Id: AbstractPublicTokenData.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;

import java.util.Date;

import webfunds.token.DataFormatException;
import webfunds.token.UnsupportedVersionException;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public abstract class AbstractPublicTokenData {
    
// Instance variables
//.............................................................................

    /** Contains the binary signature data */
    private byte[] sigdata = null;
    /** Contains the binary public data */
    private byte[] pubdata = null;


// Init methods
//.............................................................................

    protected abstract void decodeImpl(byte[] data, int start, int len);
    

// Information retrieve methods
//.............................................................................

    public abstract long[] getDenominations();
    
    public abstract long getSeries();
    
    public abstract Date getExpiryDate();


// Signature methods
//.............................................................................

    public final boolean verify(PublicKey pk, String alg, String provider)
    throws NoSuchAlgorithmException, NoSuchProviderException,
           InvalidKeyException, SignatureException
    {

        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pk == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (alg == null) 
            throw new InternalError("Assertion failed");


        Signature sig;
        if (provider == null) {
            sig = Signature.getInstance(alg);
        } else {
            sig = Signature.getInstance(alg, provider);
        }
        
        sig.initVerify(pk);
        sig.update(pubdata);
        return sig.verify(sigdata);
        
    }


// Public non-abstract encode/decode methods
//.............................................................................

    public final void decode(byte[] data, int start, int len) 
    throws DataFormatException, UnsupportedVersionException
    {

        // @@@ ASSERT
        if (sigdata != null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata != null) 
            throw new InternalError("Assertion failed");
        
        
        // read and check identifier and version
        
        if (len < 8) throw new DataFormatException("Blob too small");
        
        int pos = start;
        
        if ((data[pos++] != 84) &&    // 'T'
            (data[pos++] != 75) &&    // 'K'
            (data[pos++] != 83) &&    // 'S'
            (data[pos++] != 68))      // 'D'
        {
            throw new DataFormatException("Wrong identifier string");
        }
        
        int majorVersion = (((int)(data[pos++])) << 8) + ((int)(data[pos++]));
        int minorVersion = (((int)(data[pos++])) << 8) + ((int)(data[pos++]));
        
        if (majorVersion > MAJOR_VERSION) {
            throw new UnsupportedVersionException("Unsupported version");
        }
        

        // read public data
        
        if (pos+4 > start+len) 
            throw new DataFormatException("Blob too small");
        
        int lenpub = (((int)(data[pos++])) << 24) +
                     (((int)(data[pos++])) << 16) +
                     (((int)(data[pos++])) <<  8) +
                     (((int)(data[pos++])) <<  0);
        
        if (pos+lenpub > start+len)
            throw new DataFormatException("Blob too small");
        
        pubdata = new byte[lenpub];
        System.arraycopy(data, pos, pubdata, 0, lenpub);
        pos += lenpub;
        

        // read signature data
        
        if (pos+4 > start+len) 
            throw new DataFormatException("Blob too small");
        
        int lensig = (((int)(data[pos++])) << 24) +
                     (((int)(data[pos++])) << 16) +
                     (((int)(data[pos++])) <<  8) +
                     (((int)(data[pos++])) <<  0);
        
        if (pos+lensig > start+len)
            throw new DataFormatException("Blob too small");
        
        sigdata = new byte[lensig];
        System.arraycopy(data, pos, sigdata, 0, lensig);
        pos += lensig;
        
        
        // If this is a future version, more data could follow.
        // However, if we know the version, then check if we've reached the end.
        if ((minorVersion <= MINOR_VERSION) || (majorVersion < MAJOR_VERSION)) {
            if (pos != start+len) {
                throw new DataFormatException("Blob too large");
            }
        }
        
        
        decodeImpl(pubdata, 0, pubdata.length);
        

        // @@@ ASSERT
        if (sigdata == null) 
            throw new InternalError("Assertion failed");
        // @@@ ASSERT
        if (pubdata == null) 
            throw new InternalError("Assertion failed");

    }


}



1.1                  java/webfunds/token/algorithm/AbstractToken.java

Index: AbstractToken.java
===================================================================
/* $Id: AbstractToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public abstract class AbstractToken {


// Init methods
//.............................................................................

    public abstract void unblind(byte[] blindedcoin, byte[] blindingfactor, 
                                 SecureRandom sr, 
                                 AbstractPublicTokenData pubdata);
                                 
    public abstract void decode(byte[] data, int start, int len);
    
    
// Information retrieval methods
//.............................................................................

    public abstract long getSeries();

    public abstract long getValue(AbstractPublicTokenData pubdata);


// Processing methods
//.............................................................................

    public abstract boolean verifyPublic(AbstractPublicTokenData pubdata);
    
    public abstract boolean verifyPrivate(AbstractPrivateTokenData privdata);
    

// Output methods
//.............................................................................

    public abstract byte[] encode();


// Challenge/response methods
//.............................................................................
    
    public byte[] getServerChallenge(SecureRandom sr, 
                                     AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "getClientChallenge method, while "+
                                   "needsServerChallenge returns true.");
    }

    public boolean verifyServerResponse(byte[] response, SecureRandom sr,
                                        AbstractPrivateTokenData privdata) {
        throw new RuntimeException("Subclass did not implement "+
                                   "verifyClientResponse method, while "+
                                   "needsServerChallenge returns true.");
    }
    

}



1.1                  java/webfunds/token/algorithm/ChaumBlindedToken.java

Index: ChaumBlindedToken.java
===================================================================
/* $Id: ChaumBlindedToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class ChaumBlindedToken extends AbstractBlindedToken {


// Init methods
//.............................................................................

    public void decode(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }


// Information retrieval methods
//.............................................................................

    public long getSeries() {
        throw new RuntimeException("NYI");
    }
    
    public long getValue(AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }
    

// Processing methods
//.............................................................................

    public void sign(SecureRandom sr, AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }


// Output methods
//.............................................................................

    public byte[] encode() {
        throw new RuntimeException("NYI");
    }
    

}



1.1                  java/webfunds/token/algorithm/ChaumPrivateTokenData.java

Index: ChaumPrivateTokenData.java
===================================================================
/* $Id: ChaumPrivateTokenData.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

import java.util.Date;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class ChaumPrivateTokenData extends AbstractPrivateTokenData {


// Abstract init methods
//.............................................................................

    public void generate(SecureRandom sr, long[] denominations,
                                  long series, Date expiry) {
        throw new RuntimeException("NYI");
    }

    protected void decodeImpl(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    

// Abstract information retrieval methods
//.............................................................................

    public long[] getDenominations() {
        throw new RuntimeException("NYI");
    }
    
    public long getSeries() {
        throw new RuntimeException("NYI");
    }

    public Date getExpiryDate() {
        throw new RuntimeException("NYI");
    }


// Abstract output methods
//.............................................................................

    protected byte[] encodePublicDataImpl() {
        throw new RuntimeException("NYI");
    }
    
    protected byte[] encodePrivateDataImpl() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/ChaumProtoToken.java

Index: ChaumProtoToken.java
===================================================================
/* $Id: ChaumProtoToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class ChaumProtoToken extends AbstractProtoToken {


// Init methods
//.............................................................................

    public void generate(SecureRandom sr, long value, 
                         AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }


// Output methods
//.............................................................................

    public byte[] encodeProtocoin() {
        throw new RuntimeException("NYI");
    }
    
    public byte[] encodeBlindingFactor() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/ChaumPublicTokenData.java

Index: ChaumPublicTokenData.java
===================================================================
/* $Id: ChaumPublicTokenData.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

import java.util.Date;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class ChaumPublicTokenData extends AbstractPublicTokenData {
    

// Init methods
//.............................................................................

    protected void decodeImpl(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    

// Information retrieve methods
//.............................................................................

    public long[] getDenominations() {
        throw new RuntimeException("NYI");
    }
    
    public long getSeries() {
        throw new RuntimeException("NYI");
    }
    
    public Date getExpiryDate() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/ChaumToken.java

Index: ChaumToken.java
===================================================================
/* $Id: ChaumToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class ChaumToken extends AbstractToken {


// Init methods
//.............................................................................

    public void unblind(byte[] blindedcoin, byte[] blindingfactor, 
                        SecureRandom sr, AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }
                        
                                 
    public void decode(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    
    
// Information retrieval methods
//.............................................................................

    public long getSeries() {
        throw new RuntimeException("NYI");
    }

    public long getValue(AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }


// Processing methods
//.............................................................................

    public boolean verifyPublic(AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }
    
    public boolean verifyPrivate(AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }
    

// Output methods
//.............................................................................

    public byte[] encode() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/RandomBlindedToken.java

Index: RandomBlindedToken.java
===================================================================
/* $Id: RandomBlindedToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class RandomBlindedToken extends AbstractBlindedToken {


// Init methods
//.............................................................................

    public void decode(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }


// Information retrieval methods
//.............................................................................

    public long getSeries() {
        throw new RuntimeException("NYI");
    }
    
    public long getValue(AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }
    

// Processing methods
//.............................................................................

    public void sign(SecureRandom sr, AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }


// Output methods
//.............................................................................

    public byte[] encode() {
        throw new RuntimeException("NYI");
    }
    

}



1.1                  java/webfunds/token/algorithm/RandomPrivateTokenData.java

Index: RandomPrivateTokenData.java
===================================================================
/* $Id: RandomPrivateTokenData.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

import java.util.Date;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class RandomPrivateTokenData extends AbstractPrivateTokenData {


// Abstract init methods
//.............................................................................

    public void generate(SecureRandom sr, long[] denominations,
                                  long series, Date expiry) {
        throw new RuntimeException("NYI");
    }

    protected void decodeImpl(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    

// Abstract information retrieval methods
//.............................................................................

    public long[] getDenominations() {
        throw new RuntimeException("NYI");
    }
    
    public long getSeries() {
        throw new RuntimeException("NYI");
    }

    public Date getExpiryDate() {
        throw new RuntimeException("NYI");
    }


// Abstract output methods
//.............................................................................

    protected byte[] encodePublicDataImpl() {
        throw new RuntimeException("NYI");
    }
    
    protected byte[] encodePrivateDataImpl() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/RandomProtoToken.java

Index: RandomProtoToken.java
===================================================================
/* $Id: RandomProtoToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class RandomProtoToken extends AbstractProtoToken {


// Init methods
//.............................................................................

    public void generate(SecureRandom sr, long value, 
                         AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }


// Output methods
//.............................................................................

    public byte[] encodeProtocoin() {
        throw new RuntimeException("NYI");
    }
    
    public byte[] encodeBlindingFactor() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/RandomPublicTokenData.java

Index: RandomPublicTokenData.java
===================================================================
/* $Id: RandomPublicTokenData.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

import java.util.Date;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class RandomPublicTokenData extends AbstractPublicTokenData {
    

// Init methods
//.............................................................................

    protected void decodeImpl(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    

// Information retrieve methods
//.............................................................................

    public long[] getDenominations() {
        throw new RuntimeException("NYI");
    }
    
    public long getSeries() {
        throw new RuntimeException("NYI");
    }
    
    public Date getExpiryDate() {
        throw new RuntimeException("NYI");
    }


}



1.1                  java/webfunds/token/algorithm/RandomToken.java

Index: RandomToken.java
===================================================================
/* $Id: RandomToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
 *
 * Copyright (c) Systemics Ltd 2000 on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.token.algorithm;

import java.security.SecureRandom;

/**
 * Class description
 *
 * @version $Revision: 1.1 $
 * @author Edwin Woudt <edwin@webfunds.org>
 */
public final class RandomToken extends AbstractToken {


// Init methods
//.............................................................................

    public void unblind(byte[] blindedcoin, byte[] blindingfactor, 
                        SecureRandom sr, AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }
                        
                                 
    public void decode(byte[] data, int start, int len) {
        throw new RuntimeException("NYI");
    }
    
    
// Information retrieval methods
//.............................................................................

    public long getSeries() {
        throw new RuntimeException("NYI");
    }

    public long getValue(AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }


// Processing methods
//.............................................................................

    public boolean verifyPublic(AbstractPublicTokenData pubdata) {
        throw new RuntimeException("NYI");
    }
    
    public boolean verifyPrivate(AbstractPrivateTokenData privdata) {
        throw new RuntimeException("NYI");
    }
    

// Output methods
//.............................................................................

    public byte[] encode() {
        throw new RuntimeException("NYI");
    }


}