bool OTToken::ReassignOwnership(const OTPseudonym & oldOwner, const OTPseudonym & newOwner) { bool bSuccess = 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 theString; // Decrypt the Envelope into strContents if (!theEnvelope.Open(oldOwner, theString)) bSuccess = false; else { bSuccess = true; } if (bSuccess) { OTEnvelope theNewEnvelope; bSuccess = theNewEnvelope.Seal(newOwner, theString); if (bSuccess) bSuccess = theNewEnvelope.GetAsciiArmoredData(m_ascSpendable); } return bSuccess; }
// Use a local variable for theToken, do NOT allocate it on the heap // unless you are going to delete it yourself. // Repeat: OTPurse is NOT responsible to delete it. We create our OWN internal // variable here, new that, and add it to the stack. We do not add the one passed in. bool OTPurse::Push(const OTPseudonym & theOwner, const OTToken & theToken) { if (theToken.GetAssetID() == m_AssetID) { OTString strToken(theToken); // OTLog::vError("$$$$$$$$$$$$$$$ PUSHING token to Purse:\n---------->%s<-------------\n", strToken.Get()); OTEnvelope theEnvelope; theEnvelope.Seal(theOwner, strToken); OTASCIIArmor * pArmor = new OTASCIIArmor(theEnvelope); // OTLog::vError("$$$$$$$$$$$$$$$ PUSHING token to Purse in armored form:\n---------->%s<-------------\n", // pArmor->Get()); m_dequeTokens.push_front(pArmor); // We keep track of the purse's total value. m_lTotalValue += theToken.GetDenomination(); return true; } else { OTString strPurseAssetType(m_AssetID), strTokenAssetType(theToken.GetAssetID()); OTLog::vError("ERROR: Tried to push token with wrong asset type in OTPurse::Push\nPurse Asset Type:\n%s\n" "Token Asset Type:\n%s\n", strPurseAssetType.Get(), strTokenAssetType.Get()); return false; } }
// This function, you pass in a message and it returns true or false to let // you know whether the message was successfully sealed into theEnvelope. // (Based on the public key into cached in the OTClientConnection...) // This is for XmlRpc / HTTP mode. bool OTClientConnection::SealMessageForRecipient(OTMessage & theMsg, OTEnvelope & theEnvelope) { if (m_PublicKey.GetKey()) { // Save the ready-to-go message into a string. OTString strEnvelopeContents(theMsg); // Seal the string up into an encrypted Envelope if (strEnvelopeContents.Exists()) return theEnvelope.Seal(m_PublicKey, strEnvelopeContents); } return false; }
// This function, you pass in a message and it returns true or false to let // you know whether the message was successfully sealed into theEnvelope. // (Based on the public key into cached in the OTClientConnection...) // This is for XmlRpc / HTTP mode. bool OTClientConnection::SealMessageForRecipient(OTMessage & theMsg, OTEnvelope & theEnvelope) { if (m_PublicKey.GetKey()) { // Save the ready-to-go message into a string. OTString strEnvelopeContents(theMsg); // Seal the string up into an encrypted Envelope if (strEnvelopeContents.Exists()) return theEnvelope.Seal(m_PublicKey, strEnvelopeContents); } else OTLog::Error("OTClientConnection::SealMessageForRecipient: Unable to seal message, since this->m_PublicKey isn't set. \n"); return false; }
// This function, you pass in a message and it returns true or false to let // you know whether the message was successfully sealed into theEnvelope. // (Based on the public key into cached in the OTClientConnection...) // This is for XmlRpc / HTTP mode. // bool OTClientConnection::SealMessageForRecipient(OTMessage & theMsg, OTEnvelope & theEnvelope) { OT_ASSERT(NULL != m_pPublicKey); if (!(m_pPublicKey->IsEmpty()) && m_pPublicKey->IsPublic()) { // Save the ready-to-go message into a string. OTString strEnvelopeContents(theMsg); // Seal the string up into an encrypted Envelope. if (strEnvelopeContents.Exists()) return theEnvelope.Seal(*m_pPublicKey, strEnvelopeContents); } else OTLog::Error("OTClientConnection::SealMessageForRecipient: " "Unable to seal message, possibly a missing public key. \n"); return false; }
// Envelope retrieved from payload. bool OTPayload::GetEnvelope(OTEnvelope & theEnvelope) const { // validate checksum uint32_t lSize = GetSize(); uint32_t lIndex = lSize-2; // the index to where the NULL terminator SHOULD be if they // sent us a base64-encoded string, containing an encrypted message. (which we expect...) // (lSize-1 would be the location of the checksum at the end.) if (0 == lSize) return false; if (IsChecksumValid((OT_BYTE*)GetPointer(), (uint32_t)lSize)) { // We add the null-terminator ourselves at this point, for security reasons, // since we will process the data, soon after this function, as a string. ((OT_BYTE *)GetPointer())[lIndex] = 0; theEnvelope.m_dataContents.Release(); OTASCIIArmor theArmor; // Why is this safe, where I cast the Payload data pointer as // a char * and tell the data object to set itself from that? // Because (1) I just validated the checksum, and // (2) There place where the NULL should be, I set to 0, by hand, // just above 2 lines. So when this set operation occurs, the // farthest it will go is to that 0. theArmor.Set((const char *)GetPointer()); // Todo NOTE: If I ever want to process bookends here instead of assuming they aren't there, // IT'S VERY EASY!! All I have to do is call theArmor.LoadFromString instead of theArmor.Set. // Now the ascii-armored string that was sent across is decoded back to binary into the // Envelope object. theEnvelope.SetAsciiArmoredData(theArmor); return true; } else { OTLog::Error("Invalid Checksum in OTPayload::GetEnvelope\n"); return false; } }
// Envelope copied into payload to prepare for sending. bool OTPayload::SetEnvelope(const OTEnvelope & theEnvelope) { OTASCIIArmor theArmor; if (theEnvelope.GetAsciiArmoredData(theArmor)) { uint32_t lSize = theArmor.GetLength()+1; //+1 for the null terminater if (theArmor.GetLength()) { SetPayloadSize(lSize + 1); // +1 for the checksum byte. // Copy it in. memcpy((void *)GetPointer(), theArmor.Get(), lSize); // Add the checksum, success. AppendChecksum( (OT_BYTE*)GetPointer(), lSize ); return true; } } return false; }
// The mint has a different key pair for each denomination. // Pass the actual denomination such as 5, 10, 20, 50, 100... bool OTMint_Lucre::AddDenomination(OTPseudonym & theNotary, int64_t lDenomination, int32_t nPrimeLength/*=1024*/) { OT_ASSERT(NULL != m_pKeyPublic); bool bReturnValue = false; // Let's make sure it doesn't already exist OTASCIIArmor theArmor; if (GetPublic(theArmor, lDenomination)) { // it already exists. OTLog::Error("Error: Denomination public already exists in OTMint::AddDenomination\n"); return false; } if (GetPrivate(theArmor, lDenomination)) { // it already exists. OTLog::Error("Error: Denomination private already exists in OTMint::AddDenomination\n"); return false; } // OTLog::Error("%s <size of bank prime in bits> <bank data file> <bank public data file>\n", if ((nPrimeLength/8) < (MIN_COIN_LENGTH+DIGEST_LENGTH)) { OTLog::vError("Prime must be at least %d bits\n", (MIN_COIN_LENGTH+DIGEST_LENGTH)*8); return false; } if (nPrimeLength%8) { OTLog::Error("Prime length must be a multiple of 8\n"); return false; } #ifdef _WIN32 SetMonitor("openssl.dump"); #else SetMonitor(stderr); #endif OpenSSL_BIO bio = BIO_new(BIO_s_mem()); OpenSSL_BIO bioPublic = BIO_new(BIO_s_mem()); // Generate the mint private key information Bank bank(nPrimeLength/8); bank.WriteBIO(bio); // Generate the mint public key information PublicBank pbank(bank); pbank.WriteBIO(bioPublic); // Copy from BIO back to a normal OTString or Ascii-Armor char privateBankBuffer[4096], publicBankBuffer[4096]; // todo stop hardcoding these string lengths int32_t privatebankLen = BIO_read(bio, privateBankBuffer, 4000); // cutting it a little short on purpose, with the buffer. int32_t publicbankLen = BIO_read(bioPublic, publicBankBuffer, 4000); // Just makes me feel more comfortable for some reason. if (privatebankLen && publicbankLen) { // With this, we have the Lucre public and private bank info converted to OTStrings OTString strPublicBank; strPublicBank.Set(publicBankBuffer, publicbankLen); OTString strPrivateBank; strPrivateBank.Set(privateBankBuffer, privatebankLen); OTASCIIArmor * pPublic = new OTASCIIArmor(); OTASCIIArmor * pPrivate = new OTASCIIArmor(); OT_ASSERT(NULL != pPublic); OT_ASSERT(NULL != pPrivate); // Set the public bank info onto pPublic pPublic->SetString(strPublicBank, true); // linebreaks = true // Seal the private bank info up into an encrypted Envelope // and set it onto pPrivate OTEnvelope theEnvelope; theEnvelope.Seal(theNotary, strPrivateBank); // Todo check the return values on these two functions theEnvelope.GetAsciiArmoredData(*pPrivate); // Add the new key pair to the maps, using denomination as the key m_mapPublic[lDenomination] = pPublic; m_mapPrivate[lDenomination] = pPrivate; // Grab the Server Nym ID and save it with this Mint theNotary.GetIdentifier(m_ServerNymID); // --------------------------- // Grab the Server's public key and save it with this Mint // const OTAsymmetricKey & theNotaryPubKey = theNotary.GetPublicSignKey(); delete m_pKeyPublic; m_pKeyPublic = theNotaryPubKey.ClonePubKey(); // --------------------------- m_nDenominationCount++; // --------------------------- // Success! bReturnValue = true; OTLog::vOutput(1, "Successfully added denomination: %lld\n", lDenomination); } return bReturnValue; }
// Process my reply back out to the client. @something. // For TCP / SSL mode. void OTClientConnection::ProcessReply(OTMessage &theReply) { OT_ASSERT(NULL != m_pPublicKey); int err = 0; uint32_t nwritten = 0; bool bSendCommand = false; bool bSendPayload = false; u_header theCMD; OTPayload thePayload; memset((void *)theCMD.buf, 0, OT_CMD_HEADER_SIZE); // todo cast // For now let's send ALL replies in Envelopes (encrypted to public key of client) // IF we have a public key, that is. Otherwise we send as a normal message. // // All messages already require either a public key, or a nymID used to look up a // public key. So given that I have that information when I reply, I might as well // ENCRYPT my reply to that same public key. More secure that way. // // The wallet (and server) are both ready to open and process these encrypted envelopes. // If GetKey() returns something, that means the key was set in there, it's // not just a null pointer. This means we can use it! So let's encrypt to it. if (m_pPublicKey->IsPublic()) { OTString strEnvelopeContents(theReply); // Save the ready-to-go message into a string. OTEnvelope theEnvelope; // Seal the string up into an encrypted Envelope theEnvelope.Seal(*m_pPublicKey, strEnvelopeContents); // From here on out, theMessage is disposable. OTPayload takes over. // OTMessage doesn't care about checksums and headers. thePayload.SetEnvelope(theEnvelope); // Now that the payload is ready, we'll set up the header. SetupHeader(&theCMD, CMD_TYPE_1, TYPE_1_CMD_2, thePayload); } else { thePayload.SetMessage(theReply); // Now that the payload is ready, we'll set up the header. SetupHeader(&theCMD, CMD_TYPE_1, TYPE_1_CMD_1, thePayload); } bSendCommand = true; bSendPayload = true; OTLog::vOutput(2, "\n****************************************************************\n" "===> Finished setting up header for response.\nFirst 9 bytes are: %d %d %d %d %d %d %d %d %d...\n", theCMD.buf[0], theCMD.buf[1], theCMD.buf[2], theCMD.buf[3], theCMD.buf[4], theCMD.buf[5], theCMD.buf[6], theCMD.buf[7], theCMD.buf[8]); // ------------------------------------------------------------------------------ /* // Write to Client strcpy(buffer, "Hello Client!"); SFSocketWrite(clientSocket, buffer, strlen(buffer)); */ if (bSendCommand) { const unsigned int nHeaderSize = OT_CMD_HEADER_SIZE; for (nwritten = 0; nwritten < nHeaderSize; nwritten += err) { // err = SFSocketWrite(m_pSocket, theCMD.buf + nwritten, nHeaderSize - nwritten); #ifdef _WIN32 if (0 == err || SOCKET_ERROR == err) // 0 means disconnect. error means error. >0 means bytes read. #else if (err <= 0) #endif break; } } // At this point, we have sent the header across the pipe. if (bSendPayload) { uint32_t nPayloadSize = thePayload.GetSize(); for (nwritten = 0; nwritten < nPayloadSize; nwritten += err) { // err = SFSocketWrite(m_pSocket, (unsigned char *)thePayload.GetPayloadPointer() + nwritten, nPayloadSize - nwritten); #ifdef _WIN32 if (0 == err || SOCKET_ERROR == err) // 0 means disconnect. error means error. >0 means bytes read. #else if (err <= 0) #endif break; } } // At this point, we have sent the payload across the pipe. OTLog::Output(2, "...Done.\n"); }
// A certain number of bytes are expected in the payload, according to the header. // This function tries to read that many bytes, and inserts them into an OTPayload object. // From there, a simple method call extracts the message, we return true, and the message // gets added to our internal list for processing. bool OTClientConnection::ProcessType1Cmd(u_header & theCMD, OTMessage & theMessage) { // At this point, the checksum has already validated. // Might as well get the PAYLOAD next. // int err; uint32_t nread, lSize = theCMD.fields.size; // Make sure our byte-order is correct here. // theCMD.fields.size = ntohl(theCMD.fields.size); // I was doing this twice!! This is already done when the header is first read. // setup the buffer we are reading into OTPayload thePayload; nread = thePayload.ReadBytesFrom(m_Buffer, lSize); /* // actually read the payload from the socket into the buffer. for (nread = 0; nread < theCMD.fields.size; nread += err) { err = SFSocketRead(m_pSocket, (unsigned char *)thePayload.GetPayloadPointer() + nread, theCMD.fields.size - nread); // if we don't read anything more, stop reading and move on if (err <= 0) break; } */ // TODO fix the buffering so that if a complete command has not yet been received, it saves the other // bytes instead of discarding them. For now I'll just sleep for a second to make sure the entire command // was received. // sleep(1); // ------------------------------------------------------------ // Try to interpret the command number. // Right now we support signed messages and encrypted envelopes containing // signed messages. switch (theCMD.fields.command_id) { case TYPE_1_CMD_1: OTLog::Output(2, "Received Type 1 CMD 1:\nThere is a signed OTMessage in the payload.\n"); break; case TYPE_1_CMD_2: OTLog::Output(2, "Received Type 1 CMD 2:\n" "There is an encrypted OTEnvelope (containing signed OTMessage) in the payload.\n"); break; default: OTLog::vError("Received unexpected command number %d in OTClientConnection::ProcessType1Cmd\n", theCMD.fields.command_id); break; } // ------------------------------------------------------------ // Hm, that's weird. It was a 0 size payload message. DoS? if (theCMD.fields.size == 0) { OTLog::Output(2, "(The payload was a 0 size.)\n"); return true; } // Uh-oh, somehow the number of bytes read was less than what we expected... else if (nread < theCMD.fields.size) { // TODO: Verify that the amount read matched the amount expected // if not, we have a problem that needs to be handled. // Long term solution is to buffer the data as a comes in and just // add it to the buffer. // Then if we don't have the complete message yet, we just come around next // time some data is read, and we add that to the buffer, THEN we check to see // if there are enough bytes yet read to match the amount expected according to // the header. // // Until I can do that, I'm not yet TRULY asynchronous. TODO: lookup a good buffer class. OTLog::Error("Number of bytes read did NOT match size in header.\n"); return false; } else OTLog::vOutput(2, "Loaded a payload, size: %d\n", theCMD.fields.size); // ------------------------------------------------------------ // Okay so now we've received the expected size from the socket. Let's transfer it // into an object type that we can manipulate here in code. (Message or Envelope.) // a signed OTMessage if (TYPE_1_CMD_1 == theCMD.fields.command_id) { #ifdef _WIN32 if (OTPAYLOAD_GetMessage(thePayload, theMessage)) #else if (thePayload.GetMessage(theMessage)) #endif { OTLog::Output(2, "Successfully retrieved payload message...\n"); if (theMessage.ParseRawFile()) { OTLog::Output(2, "Successfully parsed payload message.\n"); return true; } else { OTLog::Error("Error parsing message.\n"); return false; } } else { OTLog::Error("Error retrieving message from payload.\n"); return false; } } // A base64-encoded envelope, encrypted, and containing a signed message. else if (TYPE_1_CMD_2 == theCMD.fields.command_id) { OTEnvelope theEnvelope; if (thePayload.GetEnvelope(theEnvelope)) { OTLog::Output(2, "Successfully retrieved envelope from payload...\n"); OTString strEnvelopeContents; // Decrypt the Envelope. if (m_pServer && theEnvelope.Open(m_pServer->GetServerNym(), strEnvelopeContents)) { // All decrypted, now let's load the results into an OTMessage. // No need to call theMessage.ParseRawFile() after, since // LoadContractFromString handles it. // if (strEnvelopeContents.Exists() && theMessage.LoadContractFromString(strEnvelopeContents)) { OTLog::Output(2, "Success loading message out of the envelope contents and parsing it.\n"); return true; } else { OTLog::Error("Error loading message from envelope contents.\n"); return false; } } else { OTLog::Error("Unable to open envelope.\n"); return false; } } else { OTLog::Error("Error retrieving message from payload.\n"); return false; } } return true; }
bool OTNym_or_SymmetricKey::Seal_or_Encrypt( OTEnvelope & outputEnvelope, const OTString strInput, const OTString * pstrDisplay/*=NULL*/) { const char * szFunc = "OTNym_or_SymmetricKey::Seal_or_Encrypt"; // -------------------------- bool bSuccess = false; bool bHadToInstantiatePassword = false; // --------------- // Encrypt/Seal strInput into outputEnvelope // if (this->IsNym()) { bSuccess = outputEnvelope.Seal(*(this->GetNym()), strInput); } // ------------------------------------------- else if (this->IsKey()) { OTPassword * pPassword = NULL; if (this->HasPassword()) // Password is already available. Let's use it. pPassword = this->GetPassword(); else // no password? let's collect it from the user... { const OTString strDisplay((NULL == pstrDisplay) ? szFunc : pstrDisplay->Get()); // NOTE: m_pstrDisplay overrides this below. // ------------------------------------------- // returns a text OTPassword, or NULL. // pPassword = OTSymmetricKey::GetPassphraseFromUser((NULL == m_pstrDisplay) ? &strDisplay : m_pstrDisplay);//bool bAskTwice=false if (NULL == pPassword) // Unable to retrieve passphrase from user. { OTLog::vOutput(0, "%s: Failed trying to retrieve passphrase for key. " "Returning false.\n", szFunc); return false; } else // OTNym_or_SymmetricKey stores this, if it creates it. // (And cleans it up on destruction, IF it created it.) // bHadToInstantiatePassword = true; } // ------------------------------------------- // bSuccess = outputEnvelope.Encrypt(strInput, *(this->GetKey()), *pPassword); // We only set this, presuming we have to at all, if it was a success. if (bHadToInstantiatePassword) { if (bSuccess) { m_bCleanupPassword = true; m_pPassword = pPassword; // Not bothering to cleanup whatever was here before, since we only end up here if m_pPassword was set to NULL (according to above logic...) } else // We instantiated the password, but the encrypt failed. (Need to cleanup the password then.) { delete pPassword; pPassword = NULL; } } } // else ? should never happen. // ----------------------------------- return bSuccess; }
// Lucre step 4: client unblinds token -- now it's ready for use. bool OTToken::ProcessToken(const OTPseudonym & theNym, OTMint & theMint, OTToken & theRequest) { // OTLog::vError("%s <bank public info> <private coin request> <signed coin request> <coin>\n", bool bReturnValue = false; // When the Mint has signed a token and sent it back to the client, // the client must unblind the token and set it as spendable. Thus, // this function is only performed on tokens in the signedToken state. if (OTToken::signedToken != m_State) { OTLog::Error("Signed token expected in OTToken::ProcessToken\n"); return false; } // Lucre SetDumper(stderr); BIO *bioBank = BIO_new(BIO_s_mem()); // input BIO *bioSignature = BIO_new(BIO_s_mem()); // input BIO *bioPrivateRequest = BIO_new(BIO_s_mem()); // input BIO *bioCoin = BIO_new(BIO_s_mem()); // output // Get the bank's public key (decoded into strPublicMint) // and put it into bioBank so we can use it with Lucre. OTASCIIArmor ascPublicMint; theMint.GetPublic(ascPublicMint, GetDenomination()); OTString strPublicMint(ascPublicMint); BIO_puts(bioBank, strPublicMint.Get()); // Get the existing signature into a bio. // OTLog::vError("DEBUGGING, m_Signature: -------------%s--------------\n", m_Signature.Get()); OTString strSignature(m_Signature); BIO_puts(bioSignature, strSignature.Get()); // I need the Private coin request also. (Only the client has this private coin request data.) OTASCIIArmor thePrototoken; // The server sets m_nChosenIndex when it signs the token. bool bFoundToken = theRequest.GetPrivatePrototoken(thePrototoken, m_nChosenIndex); if (bFoundToken) { // OTLog::vError("THE PRIVATE REQUEST ARMORED CONTENTS:\n------------------>%s<-----------------------\n", // thePrototoken.Get()); // Decrypt the prototoken OTString strPrototoken; OTEnvelope theEnvelope(thePrototoken); theEnvelope.Open(theNym, strPrototoken); // todo check return value. // OTLog::vError("THE PRIVATE REQUEST CONTENTS:\n------------------>%s<-----------------------\n", // strPrototoken.Get()); // copy strPrototoken to a BIO BIO_puts(bioPrivateRequest, strPrototoken.Get()); // ------- Okay, the BIOs are all loaded.... let's process... PublicBank bank(bioBank); CoinRequest req(bioPrivateRequest); // TODO make sure I'm not leaking memory with these ReadNumbers // Probably need to be calling some free function for each one. // Apparently reading the request id here and then just discarding it... ReadNumber(bioSignature,"request="); // Versus the signature data, which is read into bnSignature apparently. BIGNUM * bnSignature = ReadNumber(bioSignature,"signature="); DumpNumber("signature=", bnSignature); // Produce the final unblinded token in Coin coin, and write it to bioCoin... Coin coin; // Coin Request, processes into Coin, with Bank and Signature passed in. req.ProcessResponse(&coin, bank, bnSignature); // Notice still apparently "request" info is discarded. coin.WriteBIO(bioCoin); // convert bioCoin to a C-style string... char CoinBuffer[1024]; // todo stop hardcoding these string lengths int coinLen = BIO_read(bioCoin, CoinBuffer, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason. if (coinLen) { // ...to OTString... OTString strCoin; strCoin.Set(CoinBuffer, coinLen); // OTLog::vError("Processing token...\n%s\n", strCoin.Get()); // ...to Envelope stored in m_ascSpendable (encrypted and base64-encoded) OTEnvelope theEnvelope; theEnvelope.Seal(theNym, strCoin); // Todo check the return values on these two functions theEnvelope.GetAsciiArmoredData(m_ascSpendable); // Here's the final product. // OTLog::vError("NEW SPENDABLE token...\n--------->%s<----------------\n", m_ascSpendable.Get()); // Now the coin is encrypted from here on out, and otherwise ready-to-spend. m_State = OTToken::spendableToken; bReturnValue = true; // Lastly, we free the signature data, which is no longer needed, and which could be // otherwise used to trace the token. (Which we don't want.) m_Signature.Release(); } } // Todo log error here if the private prototoken is not found. (Very strange if so!!) // else {} // Cleanup openssl resources. BIO_free_all(bioBank); BIO_free_all(bioSignature); BIO_free_all(bioPrivateRequest); BIO_free_all(bioCoin); return bReturnValue; }
void ProcessMessage_ZMQ(const std::string & str_Message, std::string & str_Reply) { OT_ASSERT(NULL != g_pServer); if (str_Message.size() < 1) return; // -------------------- // return value. std::string resultString = ""; // Whatever we put in this string is what will get returned. // First we grab the client's message OTASCIIArmor ascMessage; ascMessage.MemSet(str_Message.data(), str_Message.size()); // ------------------ // // OTPayload thePayload; // thePayload.SetPayloadSize(str_Message.size()); // memcpy((void*)thePayload.GetPayloadPointer(), str_Message.data(), str_Message.size()); // ---------------------------------------------------------------------- // OTLog::vError("Envelope: \n%s\n Size: %ld\n", ascMessage.Get(), ascMessage.GetLength()); OTMessage theMsg, theReply; // we'll need these in a sec... // OTEnvelope theEnvelope(ascMessage); // Now the base64 is decoded and unpacked, and the envelope is in binary form again. OTEnvelope theEnvelope; // Now the base64 is decoded and the envelope is in binary form again. if (theEnvelope.SetAsciiArmoredData(ascMessage)) { OTLog::Output(2, "Successfully retrieved envelope from ZMQ message...\n"); OTString strEnvelopeContents; // OTString strPubkeyPath("TESTPUBKEY.txt"); // g_pServer->GetServerNym().SavePublicKey(strPubkeyPath); // Decrypt the Envelope. if (theEnvelope.Open(g_pServer->GetServerNym(), strEnvelopeContents)) // now strEnvelopeContents contains the decoded message. { // All decrypted--now let's load the results into an OTMessage. // No need to call theMsg.ParseRawFile() after, since // LoadContractFromString handles it. // if (strEnvelopeContents.Exists() && theMsg.LoadContractFromString(strEnvelopeContents)) { // In case you want to see all the incoming messages... // OTLog::vOutput(0, "%s\n\n", strEnvelopeContents.Get()); // By constructing this without a socket, I put it in XmlRpc/http mode, instead of tcp/ssl. OTClientConnection theClient(*g_pServer); // By optionally passing in &theClient, the client Nym's public key will be // set on it whenever verification is complete. (So for the reply, I'll // have the key and thus I'll be able to encrypt reply to the recipient.) if (g_pServer->ProcessUserCommand(theMsg, theReply, &theClient)) { // At this point the reply is ready to go, and theClient has the public key of the recipient... OTLog::vOutput(1, "Successfully processed user command: %s.\n", theMsg.m_strCommand.Get()); // The transaction is now processed, and the server's reply message is in theReply. // Let's seal it up to the recipient's nym (in an envelope) and send back to the user... OTEnvelope theRecipientEnvelope; bool bSealed = theClient.SealMessageForRecipient(theReply, theRecipientEnvelope); if (bSealed) { // OTPayload theReplyPayload; // theReplyPayload.SetEnvelope(theRecipientEnvelope); // // resultString = ascReply.Get(); // resultString.assign(theReplyPayload.GetPayloadPointer(), theReplyPayload.GetPayloadSize()); OTASCIIArmor ascReply; if (theRecipientEnvelope.GetAsciiArmoredData(ascReply)); resultString.assign(ascReply.Get(), ascReply.GetLength()); } else OTLog::Output(0, "Unable to seal envelope in ProcessMessage_ZMQ.\n"); } else OTLog::Output(0, "Unable to process user command in ProcessMessage_ZMQ.\n"); } else OTLog::Error("Error loading message from envelope contents. ProcessMessage_ZMQ.\n"); } else OTLog::Error("Unable to open envelope. ProcessMessage_ZMQ.\n"); } else OTLog::Error("Error retrieving envelope from ProcessMessage_ZMQ.\n"); // ---------------------------------------------------------------------- str_Reply = resultString; }
// static bool LegacySymmetric::Encrypt( const LegacySymmetric& theKey, const String& strPlaintext, String& strOutput, const String& pstrDisplay, bool bBookends, const OTPassword* pAlreadyHavePW) { if (!theKey.IsGenerated()) { LogDetail(OT_METHOD)(__FUNCTION__)( ": Failure: theKey.IsGenerated() was false. (The calling " "code probably should have checked that key already...).") .Flush(); return false; } if (!strPlaintext.Exists()) { LogDetail(OT_METHOD)(__FUNCTION__)( ": Plaintext is empty. Please supply. (Failure).") .Flush(); return false; } // By this point, we know we have a plaintext and a symmetric Key. // std::unique_ptr<OTPassword> pPassUserInput; if (nullptr == pAlreadyHavePW) { const char* szDisplay = "Password-protecting a plaintext."; const auto strDisplay = String::Factory( (!pstrDisplay.Exists()) ? szDisplay : pstrDisplay.Get()); pPassUserInput.reset( GetPassphraseFromUser(strDisplay)); // bAskTwice=false // by default. } else pPassUserInput.reset(new OTPassword(*pAlreadyHavePW)); auto ascOutput = Armored::Factory(); bool bSuccess = false; if (nullptr != pPassUserInput) // Success retrieving the passphrase from // the user. (Now let's encrypt...) { OTEnvelope theEnvelope; if (theEnvelope.Encrypt( strPlaintext, const_cast<LegacySymmetric&>(theKey), *pPassUserInput) && theEnvelope.GetCiphertext(ascOutput)) { bSuccess = true; if (bBookends) { return ascOutput->WriteArmoredString( strOutput, "SYMMETRIC MSG", // todo hardcoding. false); // bEscaped=false } else { strOutput.Set(ascOutput->Get()); } } else { LogDetail(OT_METHOD)(__FUNCTION__)( ": Failed trying to encrypt. (Sorry).") .Flush(); } } else LogDetail(OT_METHOD)(__FUNCTION__)( ": Sorry, unable to retrieve passphrase from user. (Failure).") .Flush(); return bSuccess; }
// assumes envelope contains encrypted data; // grabs that data in base64-form onto *this. OTASCIIArmor::OTASCIIArmor(const OTEnvelope & theEnvelope) : OTString() { theEnvelope.GetAsciiArmoredData(*this); }
// 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; }
// true == YES, DISCONNECT m_pSocket, something must have gone wrong. // false == NO, do NOT disconnect m_pSocket, everything went wonderfully! // bool ProcessMessage_ZMQ(OTServer & theServer, const std::string & str_Message, std::string & str_Reply) { if (str_Message.size() < 1) return false; const char * szFunc = "ProcessMessage_ZMQ"; // -------------------- // return value. std::string resultString = ""; // Whatever we put in this string is what will get returned. // First we grab the client's message OTASCIIArmor ascMessage; ascMessage.MemSet(str_Message.data(), str_Message.size()); // ------------------ // // OTPayload thePayload; // thePayload.SetPayloadSize(str_Message.size()); // memcpy((void*)thePayload.GetPayloadPointer(), str_Message.data(), str_Message.size()); // ---------------------------------------------------------------------- // OTLog::vError("Envelope: \n%s\n Size: %ld\n", ascMessage.Get(), ascMessage.GetLength()); bool bReturnVal = false; // "false" == no, do NOT disconnect. No errors. ("True" means YES, DISCONNECT!) OTMessage theMsg, theReply; // we'll need these in a sec... // OTEnvelope theEnvelope(ascMessage); OTEnvelope theEnvelope; if (false == theEnvelope.SetAsciiArmoredData(ascMessage)) { OTLog::vError("%s: Error retrieving envelope.\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // Now the base64 is decoded and the envelope is in binary form again. OTLog::vOutput(2, "%s: Successfully retrieved envelope from ZMQ message...\n", szFunc); OTString strEnvelopeContents; // OTString strPubkeyPath("TESTPUBKEY.txt"); // theServer.GetServerNym().SavePublicKey(strPubkeyPath); // Decrypt the Envelope. if (false == theEnvelope.Open(theServer.GetServerNym(), strEnvelopeContents)) // now strEnvelopeContents contains the decoded message. { OTLog::vError("%s: Unable to open envelope.\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // All decrypted--now let's load the results into an OTMessage. // No need to call theMsg.ParseRawFile() after, since // LoadContractFromString handles it. // if (strEnvelopeContents.Exists() && theMsg.LoadContractFromString(strEnvelopeContents)) { theReply.m_strCommand.Format("@%s", theMsg.m_strCommand.Get()); theReply.m_strNymID = theMsg.m_strNymID; // UserID theReply.m_strServerID = theMsg.m_strServerID; // ServerID, a hash of the server contract. theReply.m_bSuccess = false; // The default reply. In fact this is probably superfluous. // In case you want to see all the incoming messages... // OTLog::vOutput(0, "%s\n\n", strEnvelopeContents.Get()); // By constructing this without a socket, I put it in ZMQ mode, instead of tcp/ssl. OTClientConnection theClient(theServer); // By optionally passing in &theClient, the client Nym's public key will be // set on it whenever verification is complete. (So for the reply, I'll // have the key and thus I'll be able to encrypt reply to the recipient.) if (false == theServer.ProcessUserCommand(theMsg, theReply, &theClient)) { const OTString s1(theMsg), s2(theReply); OTLog::vOutput(0, "%s: Unable to process user command.\n\n ********** " "REQUEST:\n\n%s\n\n ********** RESPONSE:\n\n%s\n\n", szFunc, s1.Get(), s2.Get()); // NOTE: normally you would even HAVE a true or false if we're in this block. ProcessUserCommand() // is what tries to process a command and then sets false if/when it fails. Until that point, you // wouldn't get any server reply. I'm now changing this slightly, so you still get a reply (defaulted // to success==false.) That way if a client needs to re-sync his request number, he will get the false // and therefore know to resync the # as his next move, vs being stuck with no server reply (and thus // stuck with a bad socket.) // We sign the reply here, but not in the else block, since it's already signed in cases where // ProcessUserCommand() is a success, by the time that call returns. theReply.m_bSuccess = false; // Since the process call definitely failed, I'm making sure this here is definitely set to false (even though it probably was already.) theReply.SignContract(theServer.GetServerNym()); theReply.SaveContract(); } else // At this point the reply is ready to go, and theClient has the public key of the recipient... OTLog::vOutput(1, "%s: Successfully processed user command: %s.\n", szFunc, theMsg.m_strCommand.Get()); // ------------------------------------------------- // The transaction is now processed (or not), and the server's reply message is in theReply. // Let's seal it up to the recipient's nym (in an envelope) and send back to the user... // OTEnvelope theRecipientEnvelope; bool bSealed = theClient.SealMessageForRecipient(theReply, theRecipientEnvelope); if (false == bSealed) { OTLog::vOutput(0, "%s: Unable to seal envelope. (No reply will be sent.)\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // OTPayload theReplyPayload; // theReplyPayload.SetEnvelope(theRecipientEnvelope); // resultString = ascReply.Get(); // resultString.assign(theReplyPayload.GetPayloadPointer(), theReplyPayload.GetPayloadSize()); OTASCIIArmor ascReply; if (theRecipientEnvelope.GetAsciiArmoredData(ascReply)) resultString.assign(ascReply.Get(), ascReply.GetLength()); } } else { OTLog::vError("%s: Error loading message from envelope contents:\n\n%s\n\n", szFunc, strEnvelopeContents.Get()); bReturnVal = true; // disconnect the socket! } } } // ---------------------------------------------------------------------- str_Reply = resultString; return bReturnVal; } // ProcessMessage_ZMQ