bool OTEnvelope::Seal(const OTPseudonym & theRecipient, const OTString & theInput) { OTString strNymID; mapOfAsymmetricKeys theKeys; theRecipient.GetIdentifier(strNymID); theKeys.insert(std::pair<std::string, OTAsymmetricKey *> (strNymID.Get(), const_cast<OTAsymmetricKey *>(&(theRecipient.GetPublicEncrKey())))); // ----------------------------- return this->Seal(theKeys, theInput); }
// Verify Contract ID first, THEN Verify Owner. // Because we use the ID in this function, so make sure that it is verified before calling this. bool OTAccount::VerifyOwner(OTPseudonym & theCandidate) { OTIdentifier ID_CANDIDATE; theCandidate.GetIdentifier(ID_CANDIDATE); // ID_CANDIDATE now contains the ID of the Nym we're testing. if (m_AcctUserID == ID_CANDIDATE) // There's an op== function, but no != ... So I used == since it exists. { return true; } return false; }
// Verify Contract ID first, THEN Verify Owner. // Because we use the ID in this function, so make sure that it is verified before calling this. // bool OTAccount::VerifyOwner(const OTPseudonym & theCandidate) const { OTIdentifier ID_CANDIDATE; theCandidate.GetIdentifier(ID_CANDIDATE); // ID_CANDIDATE now contains the ID of the Nym we're testing. if (m_AcctUserID == ID_CANDIDATE) { return true; } return false; }
FOR_EACH(mapOfNyms, m_mapNyms) { OTPseudonym * pNym = (*it).second; OT_ASSERT_MSG((NULL != pNym), "NULL pseudonym pointer in OTWallet::GetNymByID."); OTIdentifier id_CurrentNym; pNym->GetIdentifier(id_CurrentNym); if (id_CurrentNym == NYM_ID) return pNym; }
bool OTEnvelope::Seal(setOfNyms & theRecipients, const OTString & theInput) { mapOfAsymmetricKeys RecipPubKeys; // Loop through theRecipients, and add the public key of each one to a set of keys. // FOR_EACH(setOfNyms, theRecipients) { OTPseudonym * pNym = *it; OT_ASSERT_MSG(NULL != pNym, "OTEnvelope::Seal: Assert: NULL pseudonym pointer."); // ------------------------------ OTString strNymID; pNym->GetIdentifier(strNymID); RecipPubKeys.insert(std::pair<std::string, OTAsymmetricKey *> (strNymID.Get(), const_cast<OTAsymmetricKey *>(&(pNym->GetPublicEncrKey())))); }
// The above method uses this one internally... bool OTAccount::GenerateNewAccount(const OTPseudonym & theServer, const OTMessage & theMessage, const OTAccount::AccountType eAcctType/*=OTAccount::simple*/) { // First we generate a secure random number into a binary object. OTPayload thePayload; thePayload.SetPayloadSize(100); if (!RAND_bytes((unsigned char*)thePayload.GetPayloadPointer(), 100)) { OTLog::Error("The PRNG is not seeded!\n"); // abort( ); return false; } // Next we calculate that binary object into a message digest (an OTIdentifier). OTIdentifier newID; if (!newID.CalculateDigest(thePayload)) { OTLog::Error("Error generating new account ID.\n"); return false; } // Next we get that digest (which is a binary hash number) // and extract a human-readable standard string format of that hash, // into an OTString. OTString strID(newID); SetRealAccountID(newID); // Set the account number based on what we just generated. SetPurportedAccountID(newID); // Might as well set them both. (Safe here to do so, for once.) m_strName.Set(strID); // So it's not blank. The user can always change it. // Next we create the full path filename for the account using the ID. m_strFilename.Format("%s%s%s%s%s", OTLog::Path(), OTLog::PathSeparator(), OTLog::AccountFolder(), OTLog::PathSeparator(), strID.Get()); // Then we try to load it, in order to make sure that it doesn't already exist. if (LoadContractRawFile()) { OTLog::Error("Error generating new account ID, account already exists.\n"); return false; } // Set up the various important starting values of the account. m_AcctType = eAcctType; // account type defaults to OTAccount::simple. But there are also issuer accts... // for basket accounts, the server is the user. if (OTAccount::basket == eAcctType) { theServer.GetIdentifier(m_AcctUserID); } else { m_AcctUserID.SetString(theMessage.m_strNymID); } m_AcctAssetTypeID.SetString(theMessage.m_strAssetID); OTString TEMPstr(m_AcctAssetTypeID); OTLog::vOutput(3, "Creating new account, type:\n%s\nChanged to ID then back to string:\n%s\n", theMessage.m_strAssetID.Get(), TEMPstr.Get()); OTIdentifier SERVER_ID(theMessage.m_strServerID); SetRealServerID(SERVER_ID); // todo this assumes the serverID on the message is correct. It's vetted, but still... SetPurportedServerID(SERVER_ID); const time_t tDate = time(NULL); // Today, now. m_BalanceDate.Format("%d", tDate); m_BalanceAmount.Set("0"); // Sign the Account (so we know that we did)... Otherwise someone could put a fake // account file on the server if the code wasn't designed to verify the signature on the // account. SignContract(theServer); SaveContract(); // Save the Account to storage (based on its ID.) SaveAccount(); // Don't know why I had this here. Putting SaveAccount() instead. // OTString strFilename(m_strFilename); // SaveContract(strFilename.Get()); // Saves the account to a specific filename // No need to create the inbox and outbox ledgers...they will be created automatically // if they do not exist when they are needed. return true; }
// 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; }
// The above method uses this one internally... bool OTAccount::GenerateNewAccount(const OTPseudonym & theServer, const OTMessage & theMessage, const OTAccount::AccountType eAcctType/*=OTAccount::simple*/, int64_t lStashTransNum/*=0*/) { const char *szFunc = "OTAccount::GenerateNewAccount"; // ----------------------------------------------- // First we generate a secure random number into a binary object... // OTPayload thePayload; if (false == thePayload.Randomize(100)) // todo hardcoding. Plus: is 100 bytes of random a little much here? { OTLog::vError("%s: Failed trying to acquire random numbers.\n", szFunc); return false; } // -------------------------------------------------- // // Next we calculate that binary object into a message digest (an OTIdentifier). // OTIdentifier newID; if (!newID.CalculateDigest(thePayload)) { OTLog::vError("%s: Error generating new account ID.\n", szFunc); return false; } // -------------------------------------------------- // // Next we get that digest (which is a binary hash number) // and extract a human-readable standard string format of that hash, // into an OTString. // OTString strID(newID); SetRealAccountID(newID); // Set the account number based on what we just generated. SetPurportedAccountID(newID); // Might as well set them both. (Safe here to do so, for once.) m_strName.Set(strID); // So it's not blank. The user can always change it. // Next we create the full path filename for the account using the ID. // m_strFoldername = OTFolders::Account().Get(); m_strFilename = strID.Get(); // Then we try to load it, in order to make sure that it doesn't already exist. // -------------------------------------------------------------------- if (OTDB::Exists(m_strFoldername.Get(), m_strFilename.Get())) { OTLog::vError("%s: Account already exists: %s\n", szFunc, m_strFilename.Get()); return false; } // -------------------------------------------------------------------- // Set up the various important starting values of the account. m_AcctType = eAcctType; // account type defaults to OTAccount::simple. But there are also issuer accts... // -------------------------------------------------------------------- if (IsInternalServerAcct()) // basket, basketsub, mint, voucher, and stash accounts are all "owned" by the server. { theServer.GetIdentifier(m_AcctUserID); } else { m_AcctUserID.SetString(theMessage.m_strNymID); } // -------------------------------------------------------------------- m_AcctAssetTypeID.SetString(theMessage.m_strAssetID); OTLog::vOutput(3, "%s: Creating new account, type:\n%s\n", szFunc, theMessage.m_strAssetID.Get()); OTIdentifier SERVER_ID(theMessage.m_strServerID); SetRealServerID(SERVER_ID); // todo this assumes the serverID on the message is correct. It's vetted, but still... SetPurportedServerID(SERVER_ID); const time64_t tDate = OTTimeGetCurrentTime(); // Today, now. m_BalanceDate.Format("%d", tDate); m_BalanceAmount.Set("0"); // -------------------------------------------------------------------- if (IsStashAcct()) { OT_ASSERT_MSG(lStashTransNum > 0, "You created a stash account, but with a zero-or-negative transaction number for its cron item."); m_lStashTransNum = lStashTransNum; } // -------------------------------------------------------------------- // Sign the Account (so we know that we did)... Otherwise someone could put a fake // account file on the server if the code wasn't designed to verify the signature on the // account. SignContract(theServer); SaveContract(); // Save the Account to storage (based on its ID.) SaveAccount(); // Don't know why I had this here. Putting SaveAccount() instead. // OTString strFilename(m_strFilename); // SaveContract(strFilename.Get()); // Saves the account to a specific filename // No need to create the inbox and outbox ledgers...they will be created automatically // if they do not exist when they are needed. return true; }
// ---------------------------------------------------- // INTERNAL NYM: For adding a PASSPHRASE to a PURSE. // // What if you DON'T want to encrypt the purse to your Nym?? // What if you just want to use a passphrase instead? // That's what these functions are for. OT just generates // a dummy Nym and stores it INSIDE THE PURSE. You set the // passphrase for the dummy nym, and thereafter your // experience is one of a password-protected purse. (But // in reality, there is a dummy nym inside that purse.) // bool OTPurse::GenerateInternalNym(int nBits/*=1024*/) { // ------------------------------------------- if (this->IsUsingATempNym() || (NULL != this->GetInternalNym())) { OTLog::Output(0, "OTPurse::GenerateInternalNym: Failed: internal Nym already exists.\n"); return false; } // ------------------------------------------- if (!this->IsEmpty()) { OTLog::Output(0, "OTPurse::GenerateInternalNym: Failed: The purse must be EMPTY before you create a new dummy Nym, internal to that purse. (For the purposes of adding a passphrase to the purse, normally.)\n"); return false; } // ------------------------------------------- switch (nBits) { case 1024: // todo hardcoding. case 2048: case 4096: case 8192: break; default: OTLog::vError("OTPurse::GenerateInternalNym: Failure: nBits must be one of: " "1024, 2048, 4096, 8192. (%d was passed...)\n", nBits); return false; } // ------------------------------------------- OTPseudonym * pNym = new OTPseudonym; OT_ASSERT_MSG(NULL != pNym, "OTPurse::GenerateInternalNym: Assert: NULL != new OTPseudonym \n"); // BELOW THIS point, pNym must either be deleted, or saved. (Or it will leak.) // -------------------------------------------- if (false == pNym->GenerateNym(nBits, false)) // bCreateFile=true by default, but it's FALSE here. { OTLog::vOutput(0, "OTPurse::GenerateInternalNym: Failed while calling pNym->GenerateNym(%d, false).\n", nBits); delete pNym; pNym = NULL; return false; } // --------------------------------------------------- const bool bSetIdentifier = pNym->SetIdentifierByPubkey(); OT_ASSERT_MSG(bSetIdentifier, "OTPurse::GenerateInternalNym: Assert: pNym->SetIdentifierByPubkey() \n"); // By this point, the Nym has been successfully generated, and he even has an ID! // Let's attach him to the purse so we don't have to keep worrying about a leak. // m_pTempNym = pNym; // ---------------------------- // Let's make sure the new Nym's ID is also this purse's UserID... // pNym->GetIdentifier(m_UserID); m_bUsingTempNym = true; m_bIsNymIDIncluded = true; return true; }
// THIS FUNCTION IS CALLED BY THE CUSTOMER // // (Transaction number and closing number are retrieved from Nym at this time.) bool OTAgreement::Confirm(OTPseudonym & MERCHANT_NYM, OTPseudonym & PAYER_NYM) { // ---------------------------------------------------------------------------- OTIdentifier id_MERCHANT_NYM, id_PAYER_NYM; MERCHANT_NYM.GetIdentifier(id_MERCHANT_NYM); PAYER_NYM.GetIdentifier(id_PAYER_NYM); if (GetRecipientUserID() == GetSenderUserID()) { OTLog::Output(0, "OTAgreement::Confirm: Error: Sender and recipient have the same Nym ID (not allowed.)\n"); return false; } else if (GetRecipientUserID() != id_MERCHANT_NYM) { OTLog::Output(0, "OTAgreement::Confirm: Merchant has wrong NymID (should be same as RecipientUserID.)\n"); return false; } else if (GetSenderUserID() != id_PAYER_NYM) { OTLog::Output(0, "OTAgreement::Confirm: Payer has wrong NymID (should be same as SenderUserID.)\n"); return false; } else if (PAYER_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::Confirm: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } else if (GetRecipientCountClosingNumbers() < 2) { OTLog::Output(0, "OTAgreement::Confirm: Failure. (The merchant was supposed to attach 2 transaction numbers.)\n"); return false; } // ---------------------------------------------------------------------------- // This is the single reason why MERCHANT_NYM was even passed in here! // Supposedly merchant has already signed. Let's verify this!! // if (false == this->VerifySignature(MERCHANT_NYM)) { OTLog::Output(0, "OTAgreement::Confirm: Merchant's signature failed to verify.\n"); return false; } // ---------------------------------------------------------------------------- // Now that we KNOW the merchant signed it... SAVE MERCHANT's COPY. // Let's save a copy of the one the merchant signed, before changing it and re-signing it, // (to add my own transaction numbers...) // OTString strTemp; this->SaveContractRaw(strTemp); this->SetMerchantSignedCopy(strTemp); // ******************************************************************* // The payer has to submit TWO transaction numbers in order to activate this agreement... // OTString strServerID(GetServerID()); long lTransactionNumber=0, lClosingTransactionNo=0; if (false == PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID, lTransactionNumber)) { OTLog::Error("OTAgreement::Confirm: Error: Strangely unable to get a transaction number.\n"); return false; } else if (false == PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID, lClosingTransactionNo)) { OTLog::Error("OTAgreement::Confirm: Error: Strangely unable to get a closing transaction number.\n"); PAYER_NYM.AddTransactionNum(PAYER_NYM, strServerID, lTransactionNumber, true); // bSave=true // (Since the first one was successful, we just put it back before returning.) return false; } // At this point we now HAVE 2 transaction numbers (for payer / sender)... // We can't return without USING THEM or PUTTING THEM BACK. // // --------------------------------------------------------- this->SetTransactionNum(lTransactionNumber); // Set the Transaction Number this->AddClosingTransactionNo(lClosingTransactionNo); // and the Closing Number (both for sender)... // ------------------------------------------- // CREATION DATE was set in the Merchant's proposal, and it's RESET here in the Confirm. // This way, (since we still have the original proposal) we can see BOTH times. // time_t CURRENT_TIME = time(NULL); // Set the Creation Date. SetCreationDate(CURRENT_TIME); // ------------------------------------------- OTLog::Output(4, "OTAgreement::Confirm(): Success!\n"); return true; }
// THIS FUNCTION IS CALLED BY THE MERCHANT // // (lMerchantTransactionNumber, lMerchantClosingNumber are set internally in this call, from MERCHANT_NYM.) bool OTAgreement::SetProposal(OTPseudonym & MERCHANT_NYM, const OTString & strConsideration, const time_t VALID_FROM/*=0*/, const time_t VALID_TO/*=0*/) { // ---------------------------------------------------------------------------- OTIdentifier id_MERCHANT_NYM; MERCHANT_NYM.GetIdentifier(id_MERCHANT_NYM); if (GetRecipientUserID() != id_MERCHANT_NYM) { OTLog::Output(0, "OTAgreement::SetProposal: Merchant has wrong NymID (should be same as RecipientUserID.)\n"); return false; } else if (GetRecipientUserID() == GetSenderUserID()) { OTLog::Output(0, "OTAgreement::SetProposal: Error: Sender and recipient have the same Nym ID (not allowed.)\n"); return false; } else if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::SetProposal: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } // ------------------------------------------- // Set the CREATION DATE // const time_t CURRENT_TIME = time(NULL); // Set the Creation Date. SetCreationDate(CURRENT_TIME); // ----------------------------------------- // Putting this above here so I don't have to put the transaction numbers back if this fails: // ------------------------------------------- // VALID_FROM // // The default "valid from" time is NOW. if (0 >= VALID_FROM) // if it's 0 or less, set to current time. SetValidFrom(CURRENT_TIME); else // Otherwise use whatever was passed in. SetValidFrom(VALID_FROM); // ------------------------------------------- // VALID_TO // // The default "valid to" time is 0 (which means no expiration date / cancel anytime.) if (0 == VALID_TO) // VALID_TO is 0 { SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire. } else if (0 < VALID_TO) // VALID_TO is ABOVE zero... { if (VALID_TO < VALID_FROM) // If Valid-To date is EARLIER than Valid-From date... { long lValidTo = VALID_TO, lValidFrom = VALID_FROM; OTLog::vError("OTAgreement::SetProposal: VALID_TO (%ld) is earlier than VALID_FROM (%ld)\n", lValidTo, lValidFrom); return false; } SetValidTo(VALID_TO); // Set it to whatever it is, since it is now validated as higher than Valid-From. } else // VALID_TO is a NEGATIVE number... Error. { long lValidTo = VALID_TO; OTLog::vError("Negative value for valid_to in SetAgreement: %ld\n", lValidTo); return false; } // ---------------------------------------------------------------------------- // Since we'll be needing 2 transaction numbers to do this, let's grab 'em... // OTString strServerID(GetServerID()); long lTransactionNumber=0, lClosingTransactionNo=0; if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) < 2) // Need opening and closing numbers (that's 2)... { OTLog::Output(0, "OTAgreement::SetProposal: Failure. You need at least 2 transaction numbers available to do this.\n"); return false; } else if (false == MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID, lTransactionNumber)) { OTLog::Error("OTAgreement::SetProposal: Error: Strangely unable to get a transaction number.\n"); return false; } else if (false == MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID, lClosingTransactionNo)) { OTLog::Error("OTAgreement::SetProposal: Error: Strangely unable to get a closing transaction number.\n"); MERCHANT_NYM.AddTransactionNum(MERCHANT_NYM, strServerID, lTransactionNumber, true); // bSave=true // (Since the first one was successful, we just put it back before returning.) return false; } // At this point we now have 2 transaction numbers... // We can't return without either USING THEM, or PUTTING THEM BACK. // // --------------------------------------------------------- // Set the Transaction Number and the Closing transaction number... (for merchant / recipient.) // this->AddRecipientClosingTransactionNo(lTransactionNumber); this->AddRecipientClosingTransactionNo(lClosingTransactionNo); // (They just both go onto this same list.) // ------------------------------------------- // Set the Consideration memo... m_strConsideration.Set(strConsideration); // ------------------------------------------- OTLog::Output(4, "Successfully performed OTPaymentPlan::SetProposal()\n"); return true; }