[Webfunds-commits] java/webfunds/token/algorithm AbstractPrivateTokenParameters.java AbstractPublicTokenParameters.java ChaumConstants.java ChaumPrivateTokenParameters.java ChaumPublicTokenParameters.java EncodeDecodeUtil.java RandomPrivateTokenParameters.java RandomPublicTokenParameters.java AbstractBlindedToken.java AbstractProtoToken.java AbstractToken.java ChaumBlindedToken.java ChaumProtoToken.java ChaumToken.java RandomBlindedToken.java RandomProtoToken.java RandomToken.java AbstractPrivateTokenData.java AbstractPublicTokenData.java ChaumPrivateTokenData.java ChaumPublicTokenData.java RandomPrivateTokenData.java RandomPublicTokenData.java
Edwin Woudt
edwin@cypherpunks.ai
Sat, 30 Dec 2000 23:54:24 -0400 (AST)
edwin 00/12/30 23:54:24
Modified: webfunds/token/algorithm AbstractBlindedToken.java
AbstractProtoToken.java AbstractToken.java
ChaumBlindedToken.java ChaumProtoToken.java
ChaumToken.java RandomBlindedToken.java
RandomProtoToken.java RandomToken.java
Added: webfunds/token/algorithm AbstractPrivateTokenParameters.java
AbstractPublicTokenParameters.java
ChaumConstants.java
ChaumPrivateTokenParameters.java
ChaumPublicTokenParameters.java
EncodeDecodeUtil.java
RandomPrivateTokenParameters.java
RandomPublicTokenParameters.java
Removed: webfunds/token/algorithm AbstractPrivateTokenData.java
AbstractPublicTokenData.java
ChaumPrivateTokenData.java
ChaumPublicTokenData.java
RandomPrivateTokenData.java
RandomPublicTokenData.java
Log:
- Barebones chaum implementation (keygen still missing)
- Rename *TokenData -> *TokenParameters
- Add encode/decode utility methods
- Much more small things
This still is Work In Progress. More commits next year.
Revision Changes Path
1.2 +12 -9 java/webfunds/token/algorithm/AbstractBlindedToken.java
Index: AbstractBlindedToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/AbstractBlindedToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractBlindedToken.java 2000/12/28 22:12:57 1.1
+++ AbstractBlindedToken.java 2000/12/31 03:54:19 1.2
@@ -1,4 +1,4 @@
-/* $Id: AbstractBlindedToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
+/* $Id: AbstractBlindedToken.java,v 1.2 2000/12/31 03:54:19 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -7,10 +7,13 @@
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public abstract class AbstractBlindedToken {
@@ -19,7 +22,8 @@
// Init methods
//.............................................................................
- public abstract void decode(byte[] data, int start, int len);
+ public abstract void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException;
// Information retrieval methods
@@ -27,14 +31,14 @@
public abstract long getSeries();
- public abstract long getValue(AbstractPrivateTokenData privdata);
+ public abstract long getValue(AbstractPrivateTokenParameters privparams);
// Processing methods
//.............................................................................
public abstract void sign(SecureRandom sr,
- AbstractPrivateTokenData privdata);
+ AbstractPrivateTokenParameters privparams);
// Output methods
@@ -47,24 +51,23 @@
//.............................................................................
public boolean needsClientChallenge() { return false; }
- public boolean needsServerChallenge() { return false; }
public byte[] getClientChallenge(SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"getClientChallenge method, while "+
"needsClientChallenge returns true.");
}
public boolean verifyClientResponse(byte[] response, SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"verifyClientResponse method, while "+
"needsClientChallenge returns true.");
}
public byte[] getServerResponse(byte[] challenge, SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"getServerResponse method, while "+
"needsServerChallenge returns true.");
1.2 +6 -6 java/webfunds/token/algorithm/AbstractProtoToken.java
Index: AbstractProtoToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/AbstractProtoToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractProtoToken.java 2000/12/28 22:12:57 1.1
+++ AbstractProtoToken.java 2000/12/31 03:54:19 1.2
@@ -1,4 +1,4 @@
-/* $Id: AbstractProtoToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
+/* $Id: AbstractProtoToken.java,v 1.2 2000/12/31 03:54:19 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -10,7 +10,7 @@
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public abstract class AbstractProtoToken {
@@ -20,22 +20,22 @@
//.............................................................................
public abstract void generate(SecureRandom sr, long value,
- AbstractPublicTokenData pubdata);
+ AbstractPublicTokenParameters pubparams);
// Output methods
//.............................................................................
- public abstract byte[] encodeProtocoin();
+ public abstract byte[] encodeBlindedProtoToken();
- public abstract byte[] encodeBlindingFactor();
+ public abstract byte[] encodeLocallySavedData();
// Challenge/response methods
//.............................................................................
public byte[] getClientResponse(byte[] challenge, SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"getServerResponse method, while "+
"needsClientChallenge returns true.");
1.2 +21 -11 java/webfunds/token/algorithm/AbstractToken.java
Index: AbstractToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/AbstractToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractToken.java 2000/12/28 22:12:57 1.1
+++ AbstractToken.java 2000/12/31 03:54:20 1.2
@@ -1,4 +1,4 @@
-/* $Id: AbstractToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
+/* $Id: AbstractToken.java,v 1.2 2000/12/31 03:54:20 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -7,10 +7,13 @@
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public abstract class AbstractToken {
@@ -18,12 +21,15 @@
// Init methods
//.............................................................................
+
+ public abstract void unblind(byte[] blindedcoin, int start, int len,
+ byte[] locallysaveddata, SecureRandom sr,
+ AbstractPublicTokenParameters pubparams)
+ throws DataFormatException;
- public abstract void unblind(byte[] blindedcoin, byte[] blindingfactor,
- SecureRandom sr,
- AbstractPublicTokenData pubdata);
- public abstract void decode(byte[] data, int start, int len);
+ public abstract void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException;
// Information retrieval methods
@@ -31,15 +37,17 @@
public abstract long getSeries();
- public abstract long getValue(AbstractPublicTokenData pubdata);
+ public abstract long getValue();
// Processing methods
//.............................................................................
- public abstract boolean verifyPublic(AbstractPublicTokenData pubdata);
+ public abstract boolean verifyPublic(
+ AbstractPublicTokenParameters pubparams);
- public abstract boolean verifyPrivate(AbstractPrivateTokenData privdata);
+ public abstract boolean verifyPrivate(
+ AbstractPrivateTokenParameters privparams);
// Output methods
@@ -51,15 +59,17 @@
// Challenge/response methods
//.............................................................................
+ public boolean needsServerChallenge() { return false; }
+
public byte[] getServerChallenge(SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"getClientChallenge method, while "+
"needsServerChallenge returns true.");
}
public boolean verifyServerResponse(byte[] response, SecureRandom sr,
- AbstractPrivateTokenData privdata) {
+ AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("Subclass did not implement "+
"verifyClientResponse method, while "+
"needsServerChallenge returns true.");
1.2 +36 -8 java/webfunds/token/algorithm/ChaumBlindedToken.java
Index: ChaumBlindedToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/ChaumBlindedToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ChaumBlindedToken.java 2000/12/28 22:12:57 1.1
+++ ChaumBlindedToken.java 2000/12/31 03:54:20 1.2
@@ -1,26 +1,39 @@
-/* $Id: ChaumBlindedToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
+/* $Id: ChaumBlindedToken.java,v 1.2 2000/12/31 03:54:20 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
+import java.math.BigInteger;
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class ChaumBlindedToken extends AbstractBlindedToken {
+// Instance variables
+//.............................................................................
+
+private BigInteger blindedProtoToken;
+private BigInteger blindedSignedToken;
+
+
// Init methods
//.............................................................................
- public void decode(byte[] data, int start, int len) {
- throw new RuntimeException("NYI");
+ public void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException
+ {
+ blindedProtoToken = EncodeDecodeUtil.decodeMPI(data, start, len);
}
@@ -31,7 +44,7 @@
throw new RuntimeException("NYI");
}
- public long getValue(AbstractPrivateTokenData privdata) {
+ public long getValue(AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("NYI");
}
@@ -39,8 +52,16 @@
// Processing methods
//.............................................................................
- public void sign(SecureRandom sr, AbstractPrivateTokenData privdata) {
- throw new RuntimeException("NYI");
+ public void sign(SecureRandom sr,
+ AbstractPrivateTokenParameters privparams)
+ {
+
+ BigInteger n = ((ChaumPrivateTokenParameters)privparams).getN();
+ BigInteger d = ((ChaumPrivateTokenParameters)privparams).getD(
+ getValue(privparams));
+
+ blindedSignedToken = blindedProtoToken.modPow(d, n);
+
}
@@ -48,7 +69,14 @@
//.............................................................................
public byte[] encode() {
- throw new RuntimeException("NYI");
+
+ byte[] bb = new byte[EncodeDecodeUtil.getMPILength(blindedSignedToken)];
+
+ int pos=0;
+ pos += EncodeDecodeUtil.encodeMPI(blindedSignedToken, bb, pos);
+
+ return bb;
+
}
1.2 +80 -8 java/webfunds/token/algorithm/ChaumProtoToken.java
Index: ChaumProtoToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/ChaumProtoToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ChaumProtoToken.java 2000/12/28 22:12:57 1.1
+++ ChaumProtoToken.java 2000/12/31 03:54:20 1.2
@@ -1,39 +1,111 @@
-/* $Id: ChaumProtoToken.java,v 1.1 2000/12/28 22:12:57 edwin Exp $
+/* $Id: ChaumProtoToken.java,v 1.2 2000/12/31 03:54:20 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
+import java.math.BigInteger;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class ChaumProtoToken extends AbstractProtoToken {
+// Instance variables
+//.............................................................................
+
+private BigInteger protoToken;
+private BigInteger blindingFactor;
+private BigInteger blindedProtoToken;
+
// Init methods
//.............................................................................
+ public byte[] hashAndExtend(byte[] id) {
+
+ byte[] proto = new byte[ChaumConstants.KEY_SIZE];
+ proto[0] = 0; // first byte always zero to avoid overflow errors
+
+ System.arraycopy(id, 0, proto, 1, id.length);
+ int pos = id.length+1;
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance(ChaumConstants.HASH_ALG);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new RuntimeException("Hash algorithm not found. Probably a "+
+ "provider problem.");
+ }
+
+ while (pos < proto.length - ChaumConstants.HASH_SIZE) {
+ md.reset();
+ id = md.digest(id);
+ System.arraycopy(id, 0, proto, pos, id.length);
+ pos += id.length;
+ }
+
+ md.reset();
+ id = md.digest(id);
+ System.arraycopy(id, 0, proto, pos, proto.length - pos);
+
+ return proto;
+
+ }
+
public void generate(SecureRandom sr, long value,
- AbstractPublicTokenData pubdata) {
- throw new RuntimeException("NYI");
+ AbstractPublicTokenParameters pubparams) {
+
+ byte[] id = new byte[ChaumConstants.RANDOM_SIZE];
+ sr.nextBytes(id);
+
+ byte[] proto = hashAndExtend(id);
+ protoToken = new BigInteger(1, proto);
+
+ byte[] blind = new byte[ChaumConstants.KEY_SIZE];
+ blind[0] &= 0x7f; // zero first bit to make it smaller than N
+ blindingFactor = new BigInteger(1, blind);
+
+ BigInteger n = ((ChaumPublicTokenParameters)pubparams).getN();
+ BigInteger e = ((ChaumPublicTokenParameters)pubparams).getE(value);
+
+ blindedProtoToken =
+ protoToken.multiply(blindingFactor.modPow(e, n)).mod(n);
}
// Output methods
//.............................................................................
- public byte[] encodeProtocoin() {
- throw new RuntimeException("NYI");
+ public byte[] encodeBlindedProtoToken() {
+
+ byte[] bpt = new byte[EncodeDecodeUtil.getMPILength(blindedProtoToken)];
+
+ int pos=0;
+ pos += EncodeDecodeUtil.encodeMPI(blindedProtoToken, bpt, pos);
+
+ return bpt;
+
}
- public byte[] encodeBlindingFactor() {
- throw new RuntimeException("NYI");
+ public byte[] encodeLocallySavedData() {
+
+ byte[] lsd = new byte[EncodeDecodeUtil.getMPILength(protoToken) +
+ EncodeDecodeUtil.getMPILength(blindingFactor)];
+
+ int pos=0;
+ pos += EncodeDecodeUtil.encodeMPI(protoToken, lsd, pos);
+ pos += EncodeDecodeUtil.encodeMPI(blindingFactor, lsd, pos);
+
+ return lsd;
}
1.2 +85 -13 java/webfunds/token/algorithm/ChaumToken.java
Index: ChaumToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/ChaumToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ChaumToken.java 2000/12/28 22:12:58 1.1
+++ ChaumToken.java 2000/12/31 03:54:21 1.2
@@ -1,32 +1,79 @@
-/* $Id: ChaumToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
+/* $Id: ChaumToken.java,v 1.2 2000/12/31 03:54:21 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
+import java.math.BigInteger;
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class ChaumToken extends AbstractToken {
+// Instance variables
+//.............................................................................
+
+private BigInteger token;
+private BigInteger sig;
+
// Init methods
//.............................................................................
- public void unblind(byte[] blindedcoin, byte[] blindingfactor,
- SecureRandom sr, AbstractPublicTokenData pubdata) {
- throw new RuntimeException("NYI");
+ public void unblind(byte[] blindedcoin, int start, int len,
+ byte[] locallysaveddata, SecureRandom sr,
+ AbstractPublicTokenParameters pubparams)
+ throws DataFormatException
+ {
+ int delta;
+ BigInteger blindedSignedCoin, blindingFactor;
+
+ blindedSignedCoin = EncodeDecodeUtil.decodeMPI(blindedcoin, start, len);
+ delta = EncodeDecodeUtil.getMPILength(blindedcoin, start, len);
+ start += delta; len -= delta;
+
+
+ start = 0; len = locallysaveddata.length;
+
+ blindingFactor = EncodeDecodeUtil.decodeMPI(locallysaveddata, start, len);
+ delta = EncodeDecodeUtil.getMPILength(locallysaveddata, start, len);
+ start += delta; len -= delta;
+
+ token = EncodeDecodeUtil.decodeMPI(locallysaveddata, start, len);
+ delta = EncodeDecodeUtil.getMPILength(locallysaveddata, start, len);
+ start += delta; len -= delta;
+
+
+ BigInteger n = ((ChaumPublicTokenParameters)pubparams).getN();
+
+ sig = blindedSignedCoin.multiply(blindingFactor.modInverse(n)).mod(n);
+
}
- public void decode(byte[] data, int start, int len) {
- throw new RuntimeException("NYI");
+ public void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException
+ {
+
+ int delta;
+
+ token = EncodeDecodeUtil.decodeMPI(data, start, len);
+ delta = EncodeDecodeUtil.getMPILength(data, start, len);
+ start += delta; len -= delta;
+
+ sig = EncodeDecodeUtil.decodeMPI(data, start, len);
+ delta = EncodeDecodeUtil.getMPILength(data, start, len);
+ start += delta; len -= delta;
+
}
@@ -37,7 +84,7 @@
throw new RuntimeException("NYI");
}
- public long getValue(AbstractPublicTokenData pubdata) {
+ public long getValue() {
throw new RuntimeException("NYI");
}
@@ -45,12 +92,28 @@
// Processing methods
//.............................................................................
- public boolean verifyPublic(AbstractPublicTokenData pubdata) {
- throw new RuntimeException("NYI");
+ public boolean verify(BigInteger e, BigInteger n) {
+
+ return token.equals(sig.modPow(e,n));
+
}
+
+ public boolean verifyPublic(AbstractPublicTokenParameters pubparams) {
+
+ BigInteger n = ((ChaumPublicTokenParameters)pubparams).getN();
+ BigInteger e = ((ChaumPublicTokenParameters)pubparams).getE(getValue());
+
+ return verify(e,n);
+
+ }
- public boolean verifyPrivate(AbstractPrivateTokenData privdata) {
- throw new RuntimeException("NYI");
+ public boolean verifyPrivate(AbstractPrivateTokenParameters privparams) {
+
+ BigInteger n = ((ChaumPrivateTokenParameters)privparams).getN();
+ BigInteger e = ((ChaumPrivateTokenParameters)privparams).getE(getValue());
+
+ return verify(e,n);
+
}
@@ -58,7 +121,16 @@
//.............................................................................
public byte[] encode() {
- throw new RuntimeException("NYI");
+
+ byte[] bb = new byte[EncodeDecodeUtil.getMPILength(token) +
+ EncodeDecodeUtil.getMPILength(sig)];
+
+ int pos=0;
+ pos += EncodeDecodeUtil.encodeMPI(token, bb, pos);
+ pos += EncodeDecodeUtil.encodeMPI(sig, bb, pos);
+
+ return bb;
+
}
1.2 +12 -5 java/webfunds/token/algorithm/RandomBlindedToken.java
Index: RandomBlindedToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/RandomBlindedToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RandomBlindedToken.java 2000/12/28 22:12:58 1.1
+++ RandomBlindedToken.java 2000/12/31 03:54:21 1.2
@@ -1,4 +1,4 @@
-/* $Id: RandomBlindedToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
+/* $Id: RandomBlindedToken.java,v 1.2 2000/12/31 03:54:21 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -7,10 +7,13 @@
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class RandomBlindedToken extends AbstractBlindedToken {
@@ -19,7 +22,9 @@
// Init methods
//.............................................................................
- public void decode(byte[] data, int start, int len) {
+ public void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException
+ {
throw new RuntimeException("NYI");
}
@@ -31,7 +36,7 @@
throw new RuntimeException("NYI");
}
- public long getValue(AbstractPrivateTokenData privdata) {
+ public long getValue(AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("NYI");
}
@@ -39,7 +44,9 @@
// Processing methods
//.............................................................................
- public void sign(SecureRandom sr, AbstractPrivateTokenData privdata) {
+ public void sign(SecureRandom sr,
+ AbstractPrivateTokenParameters privparams)
+ {
throw new RuntimeException("NYI");
}
1.2 +5 -5 java/webfunds/token/algorithm/RandomProtoToken.java
Index: RandomProtoToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/RandomProtoToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RandomProtoToken.java 2000/12/28 22:12:58 1.1
+++ RandomProtoToken.java 2000/12/31 03:54:21 1.2
@@ -1,4 +1,4 @@
-/* $Id: RandomProtoToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
+/* $Id: RandomProtoToken.java,v 1.2 2000/12/31 03:54:21 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -10,7 +10,7 @@
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class RandomProtoToken extends AbstractProtoToken {
@@ -20,7 +20,7 @@
//.............................................................................
public void generate(SecureRandom sr, long value,
- AbstractPublicTokenData pubdata) {
+ AbstractPublicTokenParameters pubparams) {
throw new RuntimeException("NYI");
}
@@ -28,11 +28,11 @@
// Output methods
//.............................................................................
- public byte[] encodeProtocoin() {
+ public byte[] encodeBlindedProtoToken() {
throw new RuntimeException("NYI");
}
- public byte[] encodeBlindingFactor() {
+ public byte[] encodeLocallySavedData() {
throw new RuntimeException("NYI");
}
1.2 +16 -8 java/webfunds/token/algorithm/RandomToken.java
Index: RandomToken.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/token/algorithm/RandomToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RandomToken.java 2000/12/28 22:12:58 1.1
+++ RandomToken.java 2000/12/31 03:54:22 1.2
@@ -1,4 +1,4 @@
-/* $Id: RandomToken.java,v 1.1 2000/12/28 22:12:58 edwin Exp $
+/* $Id: RandomToken.java,v 1.2 2000/12/31 03:54:22 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
@@ -7,10 +7,13 @@
import java.security.SecureRandom;
+import webfunds.token.DataFormatException;
+import webfunds.token.UnsupportedVersionException;
+
/**
* Class description
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class RandomToken extends AbstractToken {
@@ -19,13 +22,18 @@
// Init methods
//.............................................................................
- public void unblind(byte[] blindedcoin, byte[] blindingfactor,
- SecureRandom sr, AbstractPublicTokenData pubdata) {
+ public void unblind(byte[] blindedcoin, int start, int len,
+ byte[] locallysaveddata, SecureRandom sr,
+ AbstractPublicTokenParameters pubparams)
+ throws DataFormatException
+ {
throw new RuntimeException("NYI");
}
- public void decode(byte[] data, int start, int len) {
+ public void decode(byte[] data, int start, int len)
+ throws DataFormatException, UnsupportedVersionException
+ {
throw new RuntimeException("NYI");
}
@@ -37,7 +45,7 @@
throw new RuntimeException("NYI");
}
- public long getValue(AbstractPublicTokenData pubdata) {
+ public long getValue() {
throw new RuntimeException("NYI");
}
@@ -45,11 +53,11 @@
// Processing methods
//.............................................................................
- public boolean verifyPublic(AbstractPublicTokenData pubdata) {
+ public boolean verifyPublic(AbstractPublicTokenParameters pubparams) {
throw new RuntimeException("NYI");
}
- public boolean verifyPrivate(AbstractPrivateTokenData privdata) {
+ public boolean verifyPrivate(AbstractPrivateTokenParameters privparams) {
throw new RuntimeException("NYI");
}
1.1 java/webfunds/token/algorithm/AbstractPrivateTokenParameters.java
Index: AbstractPrivateTokenParameters.java
===================================================================
/* $Id: AbstractPrivateTokenParameters.java,v 1.1 2000/12/31 03:54:19 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 AbstractPublicTokenParameters) 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 AbstractPrivateTokenParameters and
* AbstractPublicTokenParameters 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 AbstractPrivateTokenParameters {
// Constants
//.............................................................................
/**
* Major version number. Upping this number will cause older clients to
* reject a particular set of data.
*
* Note that this version number is only used between
* AbstractPrivateTokenParameters and AbstractPublicTokenParameters.
* Subclasses should implement their own versioning scheme.
*/
/* package */ static final int MAJOR_VERSION = 1;
/**
* Minor version number. Upping this number will NOT cause older clients to
* reject a particular set of data.
*
* Note that this version number is only used between
* AbstractPrivateTokenParameters and AbstractPublicTokenParameters.
* Subclasses should implement their own versioning scheme.
*/
/* 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
//.............................................................................
/**
* Generate a new set of data.
*
* @param sr A source of randomness
* @param denominations A list of denominations for which parameters have
* to be generated.
* @param series An identifier that uniquely identifies this series.
* @param expiry The date on which this series will expire. If it
* will not expire or if expiration is not determined
* in advance, a null value should be given for this
* parameter.
*/
public abstract void generate(SecureRandom sr, long[] denominations,
long series, Date expiry);
/**
* Decode the private data.
*
* <p>This method will be given the result of an earlier encodePrivateImpl
* call.</p>
*
* @param data The array that contains the data.
* @param start The position in the array where the data starts.
* @param len The length of the data. If the implementation wants to read
* more data than available, it should throw a
* DataFormatException. If there is some extra data at the end
* it is left up to the implementation to decide if the extra
* data is ignored or a DataFormatException is thrown.
*
* @throws DataFormatException If the data is incorrectly formatted.
* @throws UnsupportedVersionException If the data contains an unsupported
* version. This assumes that the implementation does have some sort
* of versioning system.
*/
protected abstract void decodePrivateImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException;
/**
* Decode the public data.
*
* <p>This method will be given the result of an earlier encodePublicImpl
* call.</p>
*
* @param data The array that contains the data.
* @param start The position in the array where the data starts.
* @param len The length of the data. If the implementation wants to read
* more data than available, it should throw a
* DataFormatException. If there is some extra data at the end
* it is left up to the implementation to decide if the extra
* data is ignored or a DataFormatException is thrown.
*
* @throws DataFormatException If the data is incorrectly formatted.
* @throws UnsupportedVersionException If the data contains an unsupported
* version. This assumes that the implementation does have some sort
* of versioning system.
*/
protected abstract void decodePublicImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException;
// Abstract output methods
//.............................................................................
protected abstract byte[] encodePublicDataImpl();
protected abstract byte[] encodePrivateDataImpl();
// Information retrieval methods
//.............................................................................
public final byte[] getCurrencyID() {
throw new RuntimeException("NYI");
}
public final long getSeries() {
throw new RuntimeException("NYI");
}
public final Date getExpiryDate() {
throw new RuntimeException("NYI");
}
public final long[] getDenominations() {
throw new RuntimeException("NYI");
}
// 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/AbstractPublicTokenParameters.java
Index: AbstractPublicTokenParameters.java
===================================================================
/* $Id: AbstractPublicTokenParameters.java,v 1.1 2000/12/31 03:54:20 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.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;
/**
* Class description
*
* @version $Revision: 1.1 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public abstract class AbstractPublicTokenParameters {
// 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)
throws DataFormatException, UnsupportedVersionException;
// Information retrieval methods
//.............................................................................
public final byte[] getCurrencyID() {
throw new RuntimeException("NYI");
}
public final long getSeries() {
throw new RuntimeException("NYI");
}
public final Date getExpiryDate() {
throw new RuntimeException("NYI");
}
public final long[] getDenominations() {
throw new RuntimeException("NYI");
}
// 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 > AbstractPrivateTokenParameters.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 <= AbstractPrivateTokenParameters.MINOR_VERSION) ||
(majorVersion < AbstractPrivateTokenParameters.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/ChaumConstants.java
Index: ChaumConstants.java
===================================================================
/* $Id: ChaumConstants.java,v 1.1 2000/12/31 03:54:20 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
/**
* Constants for the Chaum blinding algorithm
*
* @version $Revision: 1.1 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class ChaumConstants {
private ChaumConstants() {} // static constants only
public static final int KEY_SIZE = 1024/8;
public static final int RANDOM_SIZE = 160/8;
public static final int HASH_SIZE = 160/8;
public static final String HASH_ALG = "SHA-1";
}
1.1 java/webfunds/token/algorithm/ChaumPrivateTokenParameters.java
Index: ChaumPrivateTokenParameters.java
===================================================================
/* $Id: ChaumPrivateTokenParameters.java,v 1.1 2000/12/31 03:54:20 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
import java.math.BigInteger;
import java.security.SecureRandom;
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 final class ChaumPrivateTokenParameters
extends AbstractPrivateTokenParameters {
// Abstract init methods
//.............................................................................
public void generate(SecureRandom sr, long[] denominations,
long series, Date expiry) {
throw new RuntimeException("NYI");
}
protected void decodePrivateImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
throw new RuntimeException("NYI");
}
protected void decodePublicImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
throw new RuntimeException("NYI");
}
// Abstract output methods
//.............................................................................
protected byte[] encodePublicDataImpl() {
throw new RuntimeException("NYI");
}
protected byte[] encodePrivateDataImpl() {
throw new RuntimeException("NYI");
}
// Parameters
//.............................................................................
public BigInteger getN() {
throw new RuntimeException("NYI");
}
public BigInteger getE(long value) {
throw new RuntimeException("NYI");
}
public BigInteger getD(long value) {
throw new RuntimeException("NYI");
}
}
1.1 java/webfunds/token/algorithm/ChaumPublicTokenParameters.java
Index: ChaumPublicTokenParameters.java
===================================================================
/* $Id: ChaumPublicTokenParameters.java,v 1.1 2000/12/31 03:54:21 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
import java.math.BigInteger;
import java.security.SecureRandom;
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 final class ChaumPublicTokenParameters
extends AbstractPublicTokenParameters {
// Init methods
//.............................................................................
protected void decodeImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
throw new RuntimeException("NYI");
}
// Parameters
//.............................................................................
public BigInteger getN() {
throw new RuntimeException("NYI");
}
public BigInteger getE(long value) {
throw new RuntimeException("NYI");
}
}
1.1 java/webfunds/token/algorithm/EncodeDecodeUtil.java
Index: EncodeDecodeUtil.java
===================================================================
/* $Id: EncodeDecodeUtil.java,v 1.1 2000/12/31 03:54:21 edwin Exp $
*
* Copyright (c) Systemics Ltd 2000 on behalf of
* the WebFunds Development Team. All Rights Reserved.
*/
package webfunds.token.algorithm;
import java.math.BigInteger;
import java.util.Date;
import webfunds.token.DataFormatException;
/**
* Encode and decode utility methods.
*
* <p>This class provides a number of static methods to encode and decode
* various types and objects. For all of the methods, little-endian encoding
* will be used.</p>
*
* @version $Revision: 1.1 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class EncodeDecodeUtil {
// Constructor
//.............................................................................
/**
* This constructor is private, which makes sure no instance of this class
* can be created. All methods in this class are declared static, so no
* instance is necessairy.
*/
private EncodeDecodeUtil() {} // static methods only
// BigInteger's / MPI's
//.............................................................................
/**
* Return the number of bytes the encoded MPI occupies.
*
* <p>
* This is a helper method for decodeMPI(...): it should be called with the
* same parameters. See decodeMPI for more information on how to use this
* method.
* </p>
*/
public static int getMPILength(byte[] data, int start, int len)
throws DataFormatException {
int bits = decodeUnsignedShort(data, start, len);
return ((bits + 7) / 8) + 2;
}
/**
* Decode an MPI (Multi Precision Integer, or BigInteger in Java).
*
* <p>Example usage:<br>
* <pre>
* BigInteger x = decodeMPI(data, start, len);
* int delta = getMPILength(data, start, len);
* start += delta; len -= delta;
* </pre></p><p>
* If you use this method as outlined above, you don't have to any bounds
* checking yourself. As soon as something goes wrong, this method will
* throw a DataFormatException.
* </p>
*
* @param data Byte array which contains the MPI to decode
* @param start Starting position of the MPI to decode
* @param len Maximum number of bytes this method is allowed to read. If
* this method wants more bytes, a DataFormatException will be
* thrown.
*
* @throws DataFormatException If an improperly formatted MPI is encountered
* or if not enough bytes are available.
*/
public static BigInteger decodeMPI(byte[] data, int start, int len)
throws DataFormatException {
int mpilen = (decodeShort(data, start, len) + 7) / 8;
if (mpilen + 2 > len) {
throw new DataFormatException("Not enough room to decode an MPI");
}
byte[] mpi = new byte[mpilen];
System.arraycopy(data, start+2, mpi, 0, mpilen);
return new BigInteger (1, mpi);
}
/**
* Return the number of bytes the encoded MPI will occupy.
*
* <p>
* This is a helper method for encodeMPI(...): it should be called with the
* same parameters to determine how many bytes to reserve. See encodeMPI for
* an example on how to use this method.
* </p>
*/
public static int getMPILength(BigInteger x) {
int bitlen = x.bitLength();
return ((bitlen + 7) / 8) + 2;
}
/**
* Encode an MPI (Multi Precision Integer, or BigInteger in Java).
*
* <p>
* The MPI will be encoded in PGP compatible format. First two bytes that
* encode the number of bits (not the number of bytes), followed by the
* binary representation of the MPI.
* </p><p>
* Note: only positive MPI's are supported. No sign information will be
* stored. The maximum size of the MPI is 65535 bits.
* </p><p>
* Example: encoding two MPI's: bigA and bigB:<br>
* <pre>
* int len = getMPILength(bigA) + getMPILength(bigB);
* byte[] data = new byte[len];
* int start = 0;
* start += encodeMPI(bigA, data, start);
* start += encodeMPI(bigB, data, start);
* </pre></p>
*
* @param x The MPI to be encoded
* @param data Byte array into which the MPI has to be encoded
* @param start Starting position in data where to start encoding
*/
public static int encodeMPI(BigInteger x, byte[] data, int start) {
byte[] bytes = x.toByteArray();
if (bytes[0] == 0) {
encodeShort((short)(bytes.length - 1), data, start);
System.arraycopy(bytes, 1, data, start+2, bytes.length - 1);
return bytes.length - 1;
} else {
encodeShort((short)bytes.length, data, start);
System.arraycopy(bytes, 0, data, start+2, bytes.length);
return bytes.length;
}
}
// Date and Time
//.............................................................................
/**
* Decode a date/time
*
* <p>
* This method always decodes 4 bytes.
* </p>
*
* @param data The byte array which contains the date to decode
* @param start The position of the date
* @param len The maximum length this date is allowed to occupy
*
* @throws DataFormatException If len < 4.
*/
public static Date decodeDateTime(byte[] data, int start, int len)
throws DataFormatException {
return new Date(decodeUnsignedInt(data, start, len));
}
/**
* Encode a date/time value
*
* <p>
* The date/time value will be encoded as an unsigned int, containing the
* number of seconds since January 1, 1970, 00:00:00 GMT. Because it is
* unsigned, this should be sufficient to encode dates until the year 2106.
* </p><p>
* The caller should make sure that from the starting position start at
* least four bytes are available in the byte array data.
* </p>
*
* @param x The date to encode
* @param data The byte array into where the date should be encoded
* @param start The starting position inside data where the encoding should
* start.
*/
public static void encodeDateTime(Date x, byte[] data, int start) {
int time = (int)(x.getTime() / 1000);
encodeInt(time, data, start);
}
// Byte array's
//.............................................................................
/**
* Return the number of bytes the encoded byte array occupies.
*
* <p>
* This is a helper method for decodeByteArray(...): it should be called
* with the same parameters. See decodeByteArray for more information on how
* to use this method.
* </p>
*/
public static int getByteArrayLength(byte[] data, int start, int len)
throws DataFormatException {
return decodeInt(data, start, len) + 4;
}
/**
* Decode a Byte Array
*
* <p>Example usage:<br>
* <pre>
* byte[] x = decodeByteArray(data, start, len);
* int delta = getByteArrayLength(data, start, len);
* start += delta; len -= delta;
* </pre></p><p>
* If you use this method as outlined above, you don't have to any bounds
* checking yourself. As soon as something goes wrong, this method will
* throw a DataFormatException.
* </p>
*
* @param data Byte array which contains the byte array to decode
* @param start Starting position of the byte array to decode
* @param len Maximum number of bytes this method is allowed to read. If
* this method wants more bytes, a DataFormatException will be
* thrown.
*
* @throws DataFormatException If an improperly formatted MPI is encountered
* or if not enough bytes are available.
*/
public static byte[] decodeByteArray(byte[] data, int start, int len)
throws DataFormatException {
int blen = decodeInt(data, start, len);
if (blen + 4 > len) {
throw new DataFormatException("Not enough room to decode byte array");
}
byte[] bytes = new byte[blen];
System.arraycopy(data, start+4, bytes, 0, blen);
return bytes;
}
/**
* Return the number of bytes the encoded byte array will occupy.
*
* <p>
* This is a helper method for encodeByteArray(...): it should be called
* with the same parameters to determine how many bytes to reserve.
* See encodeByteArray for an example on how to use this method.
* </p>
*/
public static int getByteArrayLength(byte[] x) {
return x.length + 4;
}
/**
* Encode a byte array
*
* <p>
* The encoding is pretty simple: the byte array is prefixed with a 4 byte
* little endian length.
* </p><p>
* Example: encoding two byte array's: arrA and arrB:<br>
* <pre>
* int len = getByteArrayLength(arrA) + getByteArrayLength(arrB);
* byte[] data = new byte[len];
* int start = 0;
* start += encodeByteArray(arrA, data, start);
* start += encodeByteArray(arrB, data, start);
* </pre></p>
*
* @param x The MPI to be encoded
* @param data Byte array into which the MPI has to be encoded
* @param start Starting position in data where to start encoding
*/
public static int encodeByteArray(byte[] bytes, byte[] data, int start) {
encodeInt(bytes.length, data, start);
System.arraycopy(bytes, 0, data, start+2, bytes.length);
return bytes.length + 2;
}
// Decode elementary types
//.............................................................................
/**
* Decode a signed byte.
*
* @param data The byte array which contains the byte to decode
* @param start The position of the byte
* @param len The maximum length this byte is allowed to occupy
*
* @throws DataFormatException If len < 1.
*/
public static byte decodeByte(byte[] data, int start, int len)
throws DataFormatException {
if (len < 1) {
throw new DataFormatException("Not enough room to decode a byte");
}
return data[start];
}
/**
* Decode an unsigned byte.
*
* @param data The byte array which contains the byte to decode
* @param start The position of the byte
* @param len The maximum length this byte is allowed to occupy
*
* @throws DataFormatException If len < 1.
*/
public static short decodeUnsignedByte(byte[] data, int start, int len)
throws DataFormatException {
if (len < 1) {
throw new DataFormatException("Not enough room to decode a byte");
}
return (short)(data[start] & 0xff);
}
/**
* Decode a signed short.
*
* <p>This method will read 2 bytes.</p>
*
* @param data The byte array which contains the short to decode
* @param start The starting position of the short
* @param len The maximum length this short is allowed to occupy
*
* @throws DataFormatException If len < 2.
*/
public static short decodeShort(byte[] data, int start, int len)
throws DataFormatException {
if (len < 2) {
throw new DataFormatException("Not enough room to decode a short");
}
return (short)((data[start+0] << 8) +
(data[start+1] << 0));
}
/**
* Decode an unsigned short.
*
* <p>This method will read 2 bytes.</p>
*
* @param data The byte array which contains the short to decode
* @param start The starting position of the short
* @param len The maximum length this short is allowed to occupy
*
* @throws DataFormatException If len < 2.
*/
public static int decodeUnsignedShort(byte[] data, int start, int len)
throws DataFormatException {
if (len < 2) {
throw new DataFormatException("Not enough room to decode a short");
}
return (((int)(data[start+0] << 8)) +
((int)(data[start+1] << 0))) & 0xffff;
}
/**
* Decode a signed int.
*
* <p>This method will read 4 bytes.</p>
*
* @param data The byte array which contains the int to decode
* @param start The starting position of the int
* @param len The maximum length this int is allowed to occupy
*
* @throws DataFormatException If len < 4.
*/
public static int decodeInt(byte[] data, int start, int len)
throws DataFormatException {
if (len < 4) {
throw new DataFormatException("Not enough room to decode an int");
}
return ((int)(data[start+0] << 24)) +
((int)(data[start+1] << 16)) +
((int)(data[start+2] << 8)) +
((int)(data[start+3] << 0));
}
/**
* Decode an unsigned int.
*
* <p>This method will read 4 bytes.</p>
*
* @param data The byte array which contains the int to decode
* @param start The starting position of the int
* @param len The maximum length this int is allowed to occupy
*
* @throws DataFormatException If len < 4.
*/
public static long decodeUnsignedInt(byte[] data, int start, int len)
throws DataFormatException {
if (len < 4) {
throw new DataFormatException("Not enough room to decode an int");
}
return (((long)(data[start+0] << 24)) +
((long)(data[start+1] << 16)) +
((long)(data[start+2] << 8)) +
((long)(data[start+3] << 0))) & 0xffffffffL;
}
/**
* Decode a signed long.
*
* <p>This method will read 8 bytes.</p>
*
* @param data The byte array which contains the long to decode
* @param start The starting position of the long
* @param len The maximum length this long is allowed to occupy
*
* @throws DataFormatException If len < 8.
*/
public static long decodeLong(byte[] data, int start, int len)
throws DataFormatException {
if (len < 8) {
throw new DataFormatException("Not enough room to decode a long");
}
return ((long)(data[start+0] << 56)) +
((long)(data[start+1] << 48)) +
((long)(data[start+2] << 40)) +
((long)(data[start+3] << 32)) +
((long)(data[start+4] << 24)) +
((long)(data[start+5] << 16)) +
((long)(data[start+6] << 8)) +
((long)(data[start+7] << 0));
}
// Encode elementary types
//.............................................................................
/**
* Encode a byte
*
* <p>The caller should make sure that from the starting position start at
* least one byte is available in the byte array data.</p>
*
* @param x The byte to encode
* @param data The byte array into where the byte should be encoded
* @param start The starting position inside data where the encoding should
* start.
*/
public static void encodeByte(byte x, byte[] data, int start) {
data[start] = x;
}
/**
* Encode a short
*
* <p>The caller should make sure that from the starting position start at
* least two bytes are available in the byte array data.</p>
*
* @param x The short to encode
* @param data The byte array into where the short should be encoded
* @param start The starting position inside data where the encoding should
* start.
*/
public static void encodeShort(short x, byte[] data, int start) {
data[start+0] = (byte)((x >> 8) & 0xff);
data[start+1] = (byte)((x >> 0) & 0xff);
}
/**
* Encode an int
*
* <p>The caller should make sure that from the starting position start at
* least four bytes are available in the byte array data.</p>
*
* @param x The int to encode
* @param data The byte array into where the int should be encoded
* @param start The starting position inside data where the encoding should
* start.
*/
public static void encodeInt(int x, byte[] data, int start) {
data[start+0] = (byte)((x >> 24) & 0xff);
data[start+1] = (byte)((x >> 16) & 0xff);
data[start+2] = (byte)((x >> 8) & 0xff);
data[start+3] = (byte)((x >> 0) & 0xff);
}
/**
* Encode a long
*
* <p>The caller should make sure that from the starting position start at
* least eight bytes are available in the byte array data.</p>
*
* @param x The long to encode
* @param data The byte array into where the long should be encoded
* @param start The starting position inside data where the encoding should
* start.
*/
public static void encodeLong(long x, byte[] data, int start) {
data[start+0] = (byte)((x >> 56) & 0xff);
data[start+1] = (byte)((x >> 48) & 0xff);
data[start+2] = (byte)((x >> 40) & 0xff);
data[start+3] = (byte)((x >> 32) & 0xff);
data[start+4] = (byte)((x >> 24) & 0xff);
data[start+5] = (byte)((x >> 16) & 0xff);
data[start+6] = (byte)((x >> 8) & 0xff);
data[start+7] = (byte)((x >> 0) & 0xff);
}
}
1.1 java/webfunds/token/algorithm/RandomPrivateTokenParameters.java
Index: RandomPrivateTokenParameters.java
===================================================================
/* $Id: RandomPrivateTokenParameters.java,v 1.1 2000/12/31 03:54:21 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;
import webfunds.token.DataFormatException;
import webfunds.token.UnsupportedVersionException;
/**
* Class description
*
* @version $Revision: 1.1 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class RandomPrivateTokenParameters
extends AbstractPrivateTokenParameters {
// Abstract init methods
//.............................................................................
public void generate(SecureRandom sr, long[] denominations,
long series, Date expiry) {
throw new RuntimeException("NYI");
}
protected void decodePrivateImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
throw new RuntimeException("NYI");
}
protected void decodePublicImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
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/RandomPublicTokenParameters.java
Index: RandomPublicTokenParameters.java
===================================================================
/* $Id: RandomPublicTokenParameters.java,v 1.1 2000/12/31 03:54:22 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;
import webfunds.token.DataFormatException;
import webfunds.token.UnsupportedVersionException;
/**
* Class description
*
* @version $Revision: 1.1 $
* @author Edwin Woudt <edwin@webfunds.org>
*/
public final class RandomPublicTokenParameters
extends AbstractPublicTokenParameters {
// Init methods
//.............................................................................
protected void decodeImpl(byte[] data, int start, int len)
throws DataFormatException, UnsupportedVersionException
{
throw new RuntimeException("NYI");
}
}