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