示例#1
0
// Lucre step 2 (client generates coin request)
// nDenomination must be one of the denominations supported by the mint.
// sets m_nTokenCount and populates the maps with prototokens (in ASCII-armored format.)
bool OTToken::GenerateTokenRequest(const OTPseudonym & theNym, OTMint & theMint, 
								   long lDenomination, int nTokenCount/*=OTToken::nMinimumPrototokenCount*/)
{		
	//	OTLog::vError("%s <bank public info> <coin request private output file> <coin request public output file>\n", argv[0]);

	if (OTToken::blankToken != m_State)
	{
		OTLog::Error("Blank token expected in OTToken::GenerateTokenRequest\n");
		return false;
	}
	
	// We are supposed to set these values here.
	// The server actually sets them again, for security reasons.
	// But we should still set them since server may choose to reject the request.
	SetSeriesAndExpiration(theMint.GetSeries(), theMint.GetValidFrom(), theMint.GetValidTo());
	
    SetDumper(stderr);
	
    BIO *bioBank		=	BIO_new(BIO_s_mem()); // Input. We must supply the bank's public lucre info
    BIO *bioCoin		=	BIO_new(BIO_s_mem()); // These two are output. We must write these bios, after
    BIO *bioPublicCoin	=	BIO_new(BIO_s_mem()); // the operation, back into some form we can use
	
	// This version base64-DECODES the ascii-armored string passed in,
	// and then sets the decoded plaintext string onto the string.
	//OTString::OTString(const OTASCIIArmor & strValue)
	OTASCIIArmor ascPublicMint;
	
	theMint.GetPublic(ascPublicMint, lDenomination);
	
//	OTLog::vError("DEBUG: OTToken  public asc: \n%s\n", ascPublicMint.Get());

	
	OTString strPublicMint(ascPublicMint);

//	OTLog::vError("DEBUG: OTToken  public str: \n%s\n", strPublicMint.Get());
	

	// Get the bank's public key (now decoded in strPublicMint)
	// and put it into bioBank so we can use it with Lucre.
	BIO_puts(bioBank, strPublicMint.Get());
	
	// Instantiate a PublicBank (Lucre) object.
	// We will use it to generate all the prototokens in the loop below.
    PublicBank bank;
    bank.ReadBIO(bioBank);
	
	Release();

	const int nFinalTokenCount = (nTokenCount < OTToken::nMinimumPrototokenCount) ? 
					OTToken::nMinimumPrototokenCount : nTokenCount; 
	
	// Token count is actually 1 (always) with Lucre, although this lib has potential to work with 
	// multiple proto-tokens, you can see this loop as though it always executes just once.
	for (int i = 0; i < nFinalTokenCount; i++)
	{
		CoinRequest req(bank);

		// write the private coin request to BIO
		req.WriteBIO(bioCoin);
		
		// write the public coin request to BIO
		((PublicCoinRequest *)&req)->WriteBIO(bioPublicCoin);
		
		// Convert the two bios to our format
		char privateCoinBuffer[4096], publicCoinBuffer[4096];   // todo stop hardcoding these string lengths
		int privatecoinLen	= BIO_read(bioCoin, privateCoinBuffer, 4000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
		int publiccoinLen	= BIO_read(bioPublicCoin, publicCoinBuffer, 4000); 
		
		if (privatecoinLen && publiccoinLen)
		{
			// With this, we have the Lucre public and private bank info converted to OTStrings
			OTString strPublicCoin;		strPublicCoin.Set(publicCoinBuffer, publiccoinLen);
			OTString strPrivateCoin;	strPrivateCoin.Set(privateCoinBuffer, privatecoinLen);
			
			OTASCIIArmor * pArmoredPublic	= new OTASCIIArmor(strPublicCoin);
			OTASCIIArmor * pArmoredPrivate	= new OTASCIIArmor();
			
			OT_ASSERT_MSG(((NULL != pArmoredPublic) && (NULL != pArmoredPrivate)), "ERROR: Unable to allocate memory in OTToken::GenerateTokenRequest\n");
			
			// Change the state. It's no longer a blank token, but a prototoken.
			m_State = OTToken::protoToken;

			// Seal the private coin info up into an encrypted Envelope 
			// and set it onto pArmoredPrivate (which was just added to our internal map, above.)
			OTEnvelope theEnvelope;
			theEnvelope.Seal(theNym, strPrivateCoin);	// Todo check the return values on these two functions
			theEnvelope.GetAsciiArmoredData(*pArmoredPrivate);
			
			m_mapPublic[i]	= pArmoredPublic;
			m_mapPrivate[i]	= pArmoredPrivate;

			m_nTokenCount = nFinalTokenCount;
			SetDenomination(lDenomination);
		}
		else {
			// Error condition
		}

		// Free the Private and Public coins and allocate them fresh, for the next iteration of the loop.
		BIO_free_all(bioCoin);	
		BIO_free_all(bioPublicCoin);

		bioCoin			=	BIO_new(BIO_s_mem());
		bioPublicCoin	=	BIO_new(BIO_s_mem());
	}
	
	
	// Cleanup openssl resources.
	BIO_free_all(bioBank);	
    BIO_free_all(bioCoin);	
    BIO_free_all(bioPublicCoin);
	
	return true;
}
示例#2
0
// **** VERIFY THE TOKEN WHEN REDEEMED AT THE SERVER
// Lucre step 5: token verifies when it is redeemed by merchant.
// IMPORTANT: while stored on the client side, the tokens are
// encrypted to the client side nym. But when he redeems them to
// the server, he re-encrypts them first to the SERVER's public nym.
// So by the time it comes to verify, we are opening this envelope
// with the Server's Nym.
bool OTToken::VerifyToken(OTPseudonym & theNotary, OTMint & theMint)
{
	//OTLog::vError("%s <bank info> <coin>\n",argv[0]);
    SetDumper(stderr);
	
	if (OTToken::spendableToken != m_State)
	{
		OTLog::Error("Expected spendable token in OTToken::VerifyToken\n");
		return false;
	}
	
	// load the bank and coin info into the bios
	// The Mint private info is encrypted in m_ascPrivate. So I need to extract that
	// first before I can use it.
	OTEnvelope theEnvelope(m_ascSpendable);
	
	OTString strContents; // output from opening the envelope.
	// Decrypt the Envelope into strContents    
	if (!theEnvelope.Open(theNotary, strContents))
		return false; // todo log error, etc.
	
	// Verify that the series is correct...
	// (Otherwise, someone passed us the wrong Mint and the
	// thing won't verify anyway, since we'd have the wrong keys.)
	if (m_nSeries		!= theMint.GetSeries() ||
		// Someone might, however, in a clever attack, choose to leave
		// the series intact, but change the expiration dates, so that the
		// mint keys continue to work properly for this token, but then
		// when we check the date, it APPEARS good, when really the dates
		// were altered! To prevent this, we explicitly verify the series
		// information on the token against the same info on the mint,
		// BEFORE checking the date.
		m_VALID_FROM	!= theMint.GetValidFrom() ||
		m_VALID_TO		!= theMint.GetValidTo())
	{
		OTLog::vOutput(0, "Token series information doesn't match Mint series information!\n");
		return false;
	}
	
	// Verify whether token has expired...expiration date is validated here.
	// We know the series is correct or the key wouldn't verify below... and
	// we know that the dates are correct because we compared them against the
	// mint of that series above. So now we just make sure that the CURRENT date
	// and time is within the range described on the token.
	if (!VerifyCurrentDate())
	{
		OTLog::Output(0, "Token is expired!\n");
		return false;
	}
	
	// pass the cleartext Lucre spendable coin data to the Mint to be verified.
    if (theMint.VerifyToken(theNotary, strContents, GetDenomination()))  // Here's the boolean output: coin is verified!
	{
		OTLog::Output(0, "Token verified!\n");
		return true;
	}
	else {
		OTLog::Output(0, "Bad coin!\n");
		return false;
	}
}