[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");
}
}