Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bank.h
Go to the documentation of this file.
1 //-*-C++-*-
2 
3 #include <openssl/bio.h>
4 #include <openssl/dh.h>
5 #include <openssl/sha.h>
6 #include <memory.h>
7 #include <assert.h>
8 
9 #ifdef _WIN32
10 #include <malloc.h>
11 #endif
12 
13 #define MIN_COIN_LENGTH 16
14 #define BLINDING_LENGTH 8
15 #define DIGEST_LENGTH SHA_DIGEST_LENGTH
16 
17 typedef int boolean;
18 
19 class Bank;
20 class PublicCoinRequest;
21 class CoinRequest;
22 class Coin;
23 
24 extern const char _NL[];
25 void SetDumper(BIO *out);
26 void SetDumper(FILE *f);
27 void SetMonitor(BIO *out);
28 void SetMonitor(FILE *f);
29 void DumpNumber(BIO *out,const char *szTitle,const BIGNUM *bn,
30  const char *szTrailer=_NL);
31 void DumpNumber(const char *szTitle,const BIGNUM *bn,
32  const char *szTrailer=_NL);
33 void HexDump(BIO *out,const char *szTitle,const unsigned char *acBuf,
34  int nLength);
35 void HexDump(const char *szTitle,const unsigned char *acBuf,int nLength);
36 BIGNUM *ReadNumber(BIO *in,const char *szTitle);
37 
39  {
40 protected:
41  DH *m_pDH;
42 public:
43  PublicBank(Bank &bank);
44  PublicBank(BIO *bio)
45  {
46  m_pDH=NULL;
47  ReadBIO(bio);
48  }
50  { m_pDH=NULL; }
52  { DH_free(m_pDH); }
53  const BIGNUM *p() const
54  { return m_pDH->p; }
55  /*const*/ BIGNUM *g() // regrettably not const, coz C doesn't support mutable
56  { return m_pDH->g; }
57  /*const*/ BIGNUM *pub_key() // see above
58  { return m_pDH->pub_key; }
59  void WriteBIO(BIO *bio);
60  void ReadBIO(BIO *bio);
61  void Dump()
62  {
63  DumpNumber("p= ",m_pDH->p);
64  DumpNumber("g= ",m_pDH->g);
65  DumpNumber("g^k= ",m_pDH->pub_key);
66  }
67  int CoinLength() const
68  {
70  }
71  int PrimeLength() const
72  { return BN_num_bytes(p()); }
73  };
74 
75 class Bank : public PublicBank
76  {
77  BN_CTX *m_ctx;
78 
79  static void cb(int p, int, void *arg);
80 public:
81  Bank(int nPrimeLength)
82  {
83  assert(nPrimeLength >= MIN_COIN_LENGTH+DIGEST_LENGTH);
84  m_pDH=DH_generate_parameters(nPrimeLength*8,DH_GENERATOR_5,cb,NULL);
85  assert(m_pDH);
86  assert(BN_num_bytes(m_pDH->p) == nPrimeLength); // can this fail? i.e. does OpenSSL check for length when generating?
87  int nRet=DH_generate_key(m_pDH);
88  assert(nRet);
89  m_ctx=NULL;
90  }
91  Bank(BIO *bio)
92  {
93  m_ctx=NULL;
94  ReadBIO(bio);
95  }
97  { BN_CTX_free(m_ctx); }
98  void InitCTX()
99  {
100  if(!m_ctx)
101  m_ctx=BN_CTX_new();
102  }
103  void Dump()
104  {
106  DumpNumber("k= ",m_pDH->priv_key);
107  }
108  const BIGNUM *priv_key()
109  { return m_pDH->priv_key; }
110  /*const*/ BIGNUM *SignRequest(PublicCoinRequest &req);
111  boolean Verify(Coin &coin);
112  void WriteBIO(BIO *bio);
113  void ReadBIO(BIO *bio);
114  };
115 
117  {
118 protected:
119  BIGNUM *m_bnCoinID;
120 public:
122  { m_bnCoinID=NULL; }
123  UnsignedCoin(BIGNUM *bnCoinID)
124  { m_bnCoinID=BN_dup(bnCoinID); }
126  { BN_free(m_bnCoinID); }
127  void Clear()
128  {
129  BN_free(m_bnCoinID);
130  m_bnCoinID=NULL;
131  }
132  void Set(const BIGNUM *bnCoinID)
133  {
134  Clear();
135  m_bnCoinID=BN_dup(bnCoinID);
136  }
137  void Random(int nCoinLength)
138  {
139  if(!m_bnCoinID)
140  m_bnCoinID=BN_new();
141  // choose x
142  BN_rand(m_bnCoinID,nCoinLength*8,0,1);
143  DumpNumber("x= ",m_bnCoinID);
144 
145  assert(BN_num_bytes(m_bnCoinID) == nCoinLength);
146  }
147 
148  BIGNUM *ID()
149  { return m_bnCoinID; }
150  boolean GenerateCoinNumber(BIGNUM *bnNumber,const PublicBank &bank)
151  {
152  int nCoinLength=BN_num_bytes(m_bnCoinID);
153  int nDigestIterations=(bank.PrimeLength()-nCoinLength)/DIGEST_LENGTH;
154 
155  if(nCoinLength != bank.CoinLength())
156  return false;
157 
158  unsigned char *xplusd=
159  static_cast<unsigned char *>(alloca(bank.PrimeLength()));
160 
161  // generate y=x|hash(x)
162  memset(xplusd,'\0',nCoinLength);
163  BN_bn2bin(m_bnCoinID,xplusd);
164 
165  for(int n=0 ; n < nDigestIterations ; ++n)
166  SHA1(xplusd,nCoinLength+DIGEST_LENGTH*n,
167  &xplusd[nCoinLength+DIGEST_LENGTH*n]);
168 
169  HexDump("x|hash(x)=",xplusd,
170  nCoinLength+nDigestIterations*DIGEST_LENGTH);
171 
172  BN_bin2bn(xplusd,nCoinLength+nDigestIterations*DIGEST_LENGTH,bnNumber);
173  DumpNumber("y= ",bnNumber);
174 
175  return true;
176  }
177  void Dump()
178  {
179  DumpNumber("coin= ",m_bnCoinID);
180  }
181  void WriteBIO(BIO *bio);
182  void ReadBIO(BIO *bio);
183  };
184 
185 class Coin : public UnsignedCoin
186  {
187  BIGNUM *m_bnCoinSignature;
188 public:
190  { m_bnCoinSignature=NULL; }
191  Coin(BIO *bio)
192  {
193  m_bnCoinSignature=NULL;
194  ReadBIO(bio);
195  }
196  Coin(BIGNUM *bnCoinID,BIGNUM *bnCoinSignature)
197  : UnsignedCoin(bnCoinID)
198  { m_bnCoinSignature=BN_dup(bnCoinSignature); }
200  { BN_free(m_bnCoinSignature); }
201  void Clear()
202  {
203  BN_free(m_bnCoinSignature);
204  m_bnCoinSignature=NULL;
206  }
207  void Set(BIGNUM *bnCoinID,BIGNUM *bnCoinSignature)
208  {
209  Clear();
210  m_bnCoinSignature=BN_dup(bnCoinSignature);
211  UnsignedCoin::Set(bnCoinID);
212  }
213  void Set(UnsignedCoin &ucoin,BIGNUM *bnCoinSignature)
214  { Set(ucoin.ID(),bnCoinSignature); }
215  void Dump()
216  {
217  DumpNumber("coin= (",m_bnCoinID,"");
218  DumpNumber(",",m_bnCoinSignature,")\n");
219  }
220  BIGNUM *Signature()
221  { return m_bnCoinSignature; }
222  void WriteBIO(BIO *bio);
223  void ReadBIO(BIO *bio);
224  };
225 
227  {
228 protected:
230 public:
232  { m_bnCoinRequest=NULL; }
234  {
235  m_bnCoinRequest=NULL;
236  ReadBIO(bio);
237  }
239  { BN_free(m_bnCoinRequest); }
240  /*const*/ BIGNUM *Request()
241  { return m_bnCoinRequest; }
242  void WriteBIO(BIO *bio);
243  void ReadBIO(BIO *bio);
244 
245  void Dump()
246  { DumpNumber("request= ",m_bnCoinRequest); }
247  };
248 
250  {
251  BIGNUM *m_bnBlindingFactor;
252  UnsignedCoin m_coin;
253  BN_CTX *m_ctx;
254 
255  void CheckCTX()
256  {
257  if(m_ctx)
258  return;
259  m_ctx=BN_CTX_new();
260  }
261 public:
262  CoinRequest(BIO *bio)
263  {
264  m_ctx=NULL;
265  ReadBIO(bio);
266  }
268  {
269  m_ctx=NULL;
270 
271  BIGNUM *y=BN_new();
272  for( ; ; )
273  {
274  m_coin.Random(bank.CoinLength());
275 
276  m_coin.GenerateCoinNumber(y,bank);
277 
278  if(BN_cmp(y,bank.p()) < 0)
279  break;
280  }
281 
282  // choose b
283  m_bnBlindingFactor=BN_new();
284  BN_rand(m_bnBlindingFactor,BLINDING_LENGTH*8,0,0);
285  DumpNumber("b= ",m_bnBlindingFactor);
286 
287  // calculate A->B: y g^b
288  m_bnCoinRequest=BN_new();
289  CheckCTX();
290 
291  BN_mod_exp(m_bnCoinRequest,bank.g(),m_bnBlindingFactor,bank.p(),m_ctx);
292  BN_mod_mul(m_bnCoinRequest,m_bnCoinRequest,y,bank.p(),m_ctx);
293  DumpNumber("A->B= ",m_bnCoinRequest);
294 
295  BN_free(y);
296  }
298  {
299  BN_free(m_bnBlindingFactor);
300  BN_CTX_free(m_ctx);
301  }
302  BIGNUM *Unblind(BIGNUM *bnSignedCoin,PublicBank &bank)
303  {
304  CheckCTX();
305  BIGNUM *z=BN_new();
306  BN_mod_exp(z,bank.pub_key(),m_bnBlindingFactor,bank.p(),m_ctx);
307  BN_mod_inverse(z,z,bank.p(),m_ctx);
308  BN_mod_mul(z,bnSignedCoin,z,bank.p(),m_ctx);
309  return z;
310  }
311  void ProcessResponse(Coin *pCoin,PublicBank &bank,
312  BIGNUM *bnSignedCoinRequest)
313  {
314  BIGNUM *bnCoinSignature=Unblind(bnSignedCoinRequest,bank);
315  DumpNumber("z= ",bnCoinSignature);
316  pCoin->Set(m_coin,bnCoinSignature);
317  }
318  void WriteBIO(BIO *bio);
319  void ReadBIO(BIO *bio);
320 
321  void Dump()
322  {
324  m_coin.Dump();
325  DumpNumber("blinding= ",m_bnBlindingFactor);
326  }
327  };
void ReadBIO(BIO *bio)
PublicCoinRequest(BIO *bio)
Definition: bank.h:233
void Dump()
Definition: bank.h:61
int boolean
Definition: bank.h:17
CoinRequest(PublicBank &bank)
Definition: bank.h:267
void WriteBIO(BIO *bio)
void WriteBIO(BIO *bio)
Definition: bank.h:185
BIGNUM * ID()
Definition: bank.h:148
void DumpNumber(BIO *out, const char *szTitle, const BIGNUM *bn, const char *szTrailer=_NL)
BIGNUM * m_bnCoinID
Definition: bank.h:119
PublicBank()
Definition: bank.h:49
BIGNUM * pub_key()
Definition: bank.h:57
void Set(BIGNUM *bnCoinID, BIGNUM *bnCoinSignature)
Definition: bank.h:207
void WriteBIO(BIO *bio)
~Coin()
Definition: bank.h:199
BIGNUM * ReadNumber(BIO *in, const char *szTitle)
void WriteBIO(BIO *bio)
void Dump()
Definition: bank.h:215
boolean GenerateCoinNumber(BIGNUM *bnNumber, const PublicBank &bank)
Definition: bank.h:150
~Bank()
Definition: bank.h:96
void Dump()
Definition: bank.h:103
const BIGNUM * priv_key()
Definition: bank.h:108
void Dump()
Definition: bank.h:321
BIGNUM * Request()
Definition: bank.h:240
~CoinRequest()
Definition: bank.h:297
void Random(int nCoinLength)
Definition: bank.h:137
int CoinLength() const
Definition: bank.h:67
void HexDump(BIO *out, const char *szTitle, const unsigned char *acBuf, int nLength)
DH * m_pDH
Definition: bank.h:41
~PublicBank()
Definition: bank.h:51
const char _NL[]
UnsignedCoin()
Definition: bank.h:121
void ReadBIO(BIO *bio)
~UnsignedCoin()
Definition: bank.h:125
void WriteBIO(BIO *bio)
CoinRequest(BIO *bio)
Definition: bank.h:262
Definition: bank.h:75
void ReadBIO(BIO *bio)
void ReadBIO(BIO *bio)
Bank(int nPrimeLength)
Definition: bank.h:81
BIGNUM * m_bnCoinRequest
Definition: bank.h:229
BIGNUM * Signature()
Definition: bank.h:220
void ReadBIO(BIO *bio)
BIGNUM * g()
Definition: bank.h:55
Coin()
Definition: bank.h:189
Coin(BIGNUM *bnCoinID, BIGNUM *bnCoinSignature)
Definition: bank.h:196
void SetMonitor(BIO *out)
void ProcessResponse(Coin *pCoin, PublicBank &bank, BIGNUM *bnSignedCoinRequest)
Definition: bank.h:311
void ReadBIO(BIO *bio)
#define BLINDING_LENGTH
Definition: bank.h:14
PublicBank(BIO *bio)
Definition: bank.h:44
void Set(UnsignedCoin &ucoin, BIGNUM *bnCoinSignature)
Definition: bank.h:213
#define DIGEST_LENGTH
Definition: bank.h:15
void Dump()
Definition: bank.h:177
void SetDumper(BIO *out)
PublicCoinRequest()
Definition: bank.h:231
const BIGNUM * p() const
Definition: bank.h:53
Coin(BIO *bio)
Definition: bank.h:191
void Clear()
Definition: bank.h:201
BIGNUM * Unblind(BIGNUM *bnSignedCoin, PublicBank &bank)
Definition: bank.h:302
~PublicCoinRequest()
Definition: bank.h:238
BIGNUM * SignRequest(PublicCoinRequest &req)
void Set(const BIGNUM *bnCoinID)
Definition: bank.h:132
#define MIN_COIN_LENGTH
Definition: bank.h:13
void InitCTX()
Definition: bank.h:98
void Clear()
Definition: bank.h:127
boolean Verify(Coin &coin)
void WriteBIO(BIO *bio)
void Dump()
Definition: bank.h:245
UnsignedCoin(BIGNUM *bnCoinID)
Definition: bank.h:123
int PrimeLength() const
Definition: bank.h:71
Bank(BIO *bio)
Definition: bank.h:91