Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTSubcredential.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTSubcredential.cpp
4  *
5  */
6 
7 // A nym contains a list of credentials
8 //
9 // Each credential contains a "master" subkey, and a list of subkeys
10 // signed by that master.
11 //
12 // The same class (subkey) is used because there are master credentials
13 // and subkey credentials, so we're using a single "subkey" class to
14 // encapsulate each credential, both for the master credential and
15 // for each subkey credential.
16 //
17 // Each subkey has 3 key pairs: encryption, signing, and authentication.
18 //
19 // Each key pair has 2 OTAsymmetricKeys (public and private.)
20 
21 /************************************************************
22  -----BEGIN PGP SIGNED MESSAGE-----
23  Hash: SHA1
24 
25  * OPEN TRANSACTIONS
26  *
27  * Financial Cryptography and Digital Cash
28  * Library, Protocol, API, Server, CLI, GUI
29  *
30  * -- Anonymous Numbered Accounts.
31  * -- Untraceable Digital Cash.
32  * -- Triple-Signed Receipts.
33  * -- Cheques, Vouchers, Transfers, Inboxes.
34  * -- Basket Currencies, Markets, Payment Plans.
35  * -- Signed, XML, Ricardian-style Contracts.
36  * -- Scripted smart contracts.
37  *
38  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
39  *
40  * EMAIL:
42  *
43  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
44  *
45  * KEY FINGERPRINT (PGP Key in license file):
46  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
47  *
48  * OFFICIAL PROJECT WIKI(s):
49  * https://github.com/FellowTraveler/Moneychanger
50  * https://github.com/FellowTraveler/Open-Transactions/wiki
51  *
52  * WEBSITE:
53  * http://www.OpenTransactions.org/
54  *
55  * Components and licensing:
56  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
57  * -- otlib.........A class library.......LICENSE:...LAGPLv3
58  * -- otapi.........A client API..........LICENSE:...LAGPLv3
59  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
60  * -- otserver......Server Application....LICENSE:....AGPLv3
61  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
62  *
63  * All of the above OT components were designed and written by
64  * Fellow Traveler, with the exception of Moneychanger, which
65  * was contracted out to Vicky C ([email protected]).
66  * The open-source community has since actively contributed.
67  *
68  * -----------------------------------------------------
69  *
70  * LICENSE:
71  * This program is free software: you can redistribute it
72  * and/or modify it under the terms of the GNU Affero
73  * General Public License as published by the Free Software
74  * Foundation, either version 3 of the License, or (at your
75  * option) any later version.
76  *
77  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
78  * section 7: (This paragraph applies only to the LAGPLv3
79  * components listed above.) If you modify this Program, or
80  * any covered work, by linking or combining it with other
81  * code, such other code is not for that reason alone subject
82  * to any of the requirements of the GNU Affero GPL version 3.
83  * (==> This means if you are only using the OT API, then you
84  * don't have to open-source your code--only your changes to
85  * Open-Transactions itself must be open source. Similar to
86  * LGPLv3, except it applies to software-as-a-service, not
87  * just to distributing binaries.)
88  *
89  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
90  * used by Open Transactions: This program is released under
91  * the AGPL with the additional exemption that compiling,
92  * linking, and/or using OpenSSL is allowed. The same is true
93  * for any other open source libraries included in this
94  * project: complete waiver from the AGPL is hereby granted to
95  * compile, link, and/or use them with Open-Transactions,
96  * according to their own terms, as long as the rest of the
97  * Open-Transactions terms remain respected, with regard to
98  * the Open-Transactions code itself.
99  *
100  * Lucre License:
101  * This code is also "dual-license", meaning that Ben Lau-
102  * rie's license must also be included and respected, since
103  * the code for Lucre is also included with Open Transactions.
104  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
105  * The Laurie requirements are light, but if there is any
106  * problem with his license, simply remove the Lucre code.
107  * Although there are no other blind token algorithms in Open
108  * Transactions (yet. credlib is coming), the other functions
109  * will continue to operate.
110  * See Lucre on Github: https://github.com/benlaurie/lucre
111  * -----------------------------------------------------
112  * You should have received a copy of the GNU Affero General
113  * Public License along with this program. If not, see:
114  * http://www.gnu.org/licenses/
115  *
116  * If you would like to use this software outside of the free
117  * software license, please contact FellowTraveler.
118  * (Unfortunately many will run anonymously and untraceably,
119  * so who could really stop them?)
120  *
121  * DISCLAIMER:
122  * This program is distributed in the hope that it will be
123  * useful, but WITHOUT ANY WARRANTY; without even the implied
124  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
125  * PURPOSE. See the GNU Affero General Public License for
126  * more details.
127 
128  -----BEGIN PGP SIGNATURE-----
129  Version: GnuPG v1.4.9 (Darwin)
130 
131  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
132  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
133  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
134  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
135  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
136  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
137  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
138  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
139  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
140  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
141  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
142  kamH0Y/n11lCvo1oQxM+
143  =uSzz
144  -----END PGP SIGNATURE-----
145  **************************************************************/
146 
147 #include "stdafx.hpp"
148 
150 
151 #include "crypto/OTASCIIArmor.hpp"
152 #include "crypto/OTCredential.hpp"
153 #include "OTLog.hpp"
154 #include "OTStorage.hpp"
155 
156 #include <irrxml/irrXML.hpp>
157 
158 // Contains 3 key pairs: signing, authentication, and encryption.
159 // This is stored as an OTContract, and it must be signed by the
160 // master key. (which is also an OTSubcredential.)
161 //
162 
163 namespace opentxs
164 {
165 
167 {
168  m_pOwner = &theOwner;
169 }
170 
172  : ot_super()
173  , m_StoreAs(OTSubcredential::credPrivateInfo)
174  , m_pOwner(nullptr)
175 {
176  m_strContractType = "CREDENTIAL";
177 }
178 
180  : ot_super()
181  , m_StoreAs(OTSubcredential::credPrivateInfo)
182  , m_pOwner(&theOwner)
183 {
184  m_strContractType = "CREDENTIAL";
185 }
186 
188 {
190 }
191 
192 // virtual
194 {
195  Release_Subcredential(); // My own cleanup is done here.
196 
197  // Next give the base class a chance to do the same...
198  ot_super::Release(); // since I've overridden the base class, I call it
199  // now...
200 }
201 
203 {
204  // Release any dynamically allocated members here. (Normally.)
205 }
206 
207 // virtual
209 {
210  m_mapPublicInfo = mapPublic;
211  return true;
212 }
213 
214 // virtual
216  const OTPassword*) // if not nullptr,
217  // it means to
218  // use this
219  // password by
220  // default.)
221 {
222  m_mapPrivateInfo = mapPrivate;
223  return true;
224 }
225 
226 void OTSubcredential::SetMasterCredID(const OTString& strMasterCredID)
227 {
228  m_strMasterCredID = strMasterCredID;
229 }
230 
232  const OTString& strSourceForNymID)
233 {
234  m_strNymID = strNymID;
235  m_strSourceForNymID = strSourceForNymID;
236 }
237 
239  OTString& strAppendTo) // Used in UpdateContents.
240 {
241  OT_ASSERT(nullptr != m_pOwner);
242  OTASCIIArmor ascMaster(m_pOwner->GetPubCredential());
243  strAppendTo.Concatenate("<masterPublic>\n%s</masterPublic>\n\n",
244  ascMaster.Get());
245 }
246 
248  OTString& strAppendTo) // Used in UpdateContents.
249 {
250  if (!m_mapPublicInfo.empty()) {
251  strAppendTo.Concatenate("<publicContents count=\"%d\">\n\n",
252  m_mapPublicInfo.size());
253 
254  for (auto& it : m_mapPublicInfo) {
255  OTString strInfo(it.second);
256  OTASCIIArmor ascInfo(strInfo);
257  strAppendTo.Concatenate(
258  "<publicInfo key=\"%s\">\n%s</publicInfo>\n\n",
259  it.first.c_str(), ascInfo.Get());
260  }
261 
262  strAppendTo.Concatenate("</publicContents>\n\n");
263  }
264 }
265 
267  OTString& strAppendTo) // Used in UpdateContents.
268 {
269  if (GetContents().Exists()) {
270  OTASCIIArmor ascContents(GetContents());
271  if (ascContents.Exists())
272  strAppendTo.Concatenate(
273  "<publicCredential>\n%s</publicCredential>\n\n",
274  ascContents.Get());
275  }
276 }
277 
279  OTString& strAppendTo) // Used in UpdateContents.
280 {
281  if (!m_mapPrivateInfo.empty()) {
282  strAppendTo.Concatenate("<privateContents count=\"%d\">\n\n",
283  m_mapPrivateInfo.size());
284 
285  for (auto& it : m_mapPrivateInfo) {
286  OTString strInfo(it.second);
287  OTASCIIArmor ascInfo(strInfo);
288  strAppendTo.Concatenate(
289  "<privateInfo key=\"%s\">\n%s</privateInfo>\n\n",
290  it.first.c_str(), ascInfo.Get());
291  }
292  strAppendTo.Concatenate("</privateContents>\n\n");
293  }
294 }
295 
297 {
299 
301  "<subCredential nymID=\"%s\"\n" // a hash of the nymIDSource
302  " masterCredentialID=\"%s\" >\n\n", // Hash of the master credential
303  // that signed this subcredential.
304  GetNymID().Get(),
305  GetMasterCredID().Get());
306 
307  if (GetNymIDSource().Exists()) {
308  OTASCIIArmor ascSource;
309  ascSource.SetString(GetNymIDSource()); // A nym should always
310  // verify through its own
311  // source. (Whatever that
312  // may be.)
313  m_xmlUnsigned.Concatenate("<nymIDSource>\n%s</nymIDSource>\n\n",
314  ascSource.Get());
315  }
316 
317  // if (OTSubcredential::credPublicInfo == m_StoreAs) // (Always saving
318  // public info.)
319  {
320  // PUBLIC INFO
322 
324  }
325 
326  // If we're saving the private credential info...
327  //
330 
332  }
333  // -------------------------------------------------
334  m_xmlUnsigned.Concatenate("</subCredential>\n");
335 
336  m_StoreAs = OTSubcredential::credPrivateInfo; // <=== SET IT BACK TO DEFAULT
337  // BEHAVIOR. Any other state
338  // processes ONCE, and then
339  // goes back to this again.
340 }
341 
342 // return -1 if error, 0 if nothing, and 1 if the node was processed.
343 //
345 {
346  int32_t nReturnVal = 0;
347 
348  const OTString strNodeName(xml->getNodeName());
349 
350  // Here we call the parent class first.
351  // If the node is found there, or there is some error,
352  // then we just return either way. But if it comes back
353  // as '0', then nothing happened, and we'll continue executing.
354  //
355  // -- Note you can choose not to call the parent if
356  // you don't want to use any of those xml tags.
357  // As I do in the case of OTAccount.
358  //
359  // if (nReturnVal = OTContract::ProcessXMLNode(xml))
360  // return nReturnVal;
361 
362  if (strNodeName.Compare("subCredential")) {
363  m_strNymID = xml->getAttributeValue("nymID");
364  m_strMasterCredID = xml->getAttributeValue("masterCredentialID");
365 
366  otWarn << "Loading subcredential...\n";
367 
368  nReturnVal = 1;
369  }
370  else if (strNodeName.Compare("nymIDSource")) {
371  otWarn << "Loading nymIDSource...\n";
372 
373  OTASCIIArmor ascTemp;
374  if (!OTContract::LoadEncodedTextField(xml, ascTemp)) {
375  otErr << "Error in " << __FILE__ << " line " << __LINE__
376  << ": failed loading expected nymIDSource field.\n";
377  return (-1); // error condition
378  }
379  if (ascTemp.Exists()) ascTemp.GetString(m_strSourceForNymID);
380 
381  nReturnVal = 1;
382  }
383  else if (strNodeName.Compare("masterPublic")) {
384  OTString strMasterPublicCredential;
385 
386  if (false ==
387  OTContract::LoadEncodedTextField(xml, strMasterPublicCredential)) {
388  otErr << "Error in " << __FILE__ << " line " << __LINE__
389  << ": failed loading expected master public credential while "
390  "loading subcredential.\n";
391  return (-1); // error condition
392  }
393  // Verify the master public credential we loaded against the one we
394  // expected to get, according
395  // to the OTCredential that is m_pOwner.
396  //
397  else if ((nullptr != m_pOwner) &&
398  false == (m_pOwner->GetPubCredential().Compare(
399  strMasterPublicCredential))) {
400  otErr << "Failure in " << __FILE__ << " line " << __LINE__
401  << ": while loading subcredential: master public "
402  "credential loaded just now, doesn't match the actual "
403  "master public credential, "
404  "according to the current owner object.\n";
405  return (-1); // error condition
406  }
407 
408  nReturnVal = 1;
409  }
410  else if (strNodeName.Compare("publicContents")) {
411  OTString strCount;
412  strCount = xml->getAttributeValue("count");
413  const int32_t nCount = strCount.Exists() ? atoi(strCount.Get()) : 0;
414  if (nCount > 0) {
415  int32_t nTempCount = nCount;
416  OTString::Map mapPublic;
417 
418  while (nTempCount-- > 0) {
419 
420  const char* pElementExpected = "publicInfo";
421  OTString strPublicInfo;
422 
423  // This map contains values we will also want, when we read the
424  // info...
425  // (The OTContract::LoadEncodedTextField call below will read
426  // all the values
427  // as specified in this map.)
428  //
429  OTString::Map temp_MapAttributes;
430  temp_MapAttributes.insert(std::pair<std::string, std::string>(
431  "key",
432  "")); // Value should be "A" or "E" or "S" after reading.
433 
435  xml, strPublicInfo, pElementExpected,
436  &temp_MapAttributes)) // </publicInfo>
437  {
438  otErr << __FUNCTION__ << ": Error: Expected "
439  << pElementExpected << " element with text field.\n";
440  return (-1); // error condition
441  }
442 
443  auto it = temp_MapAttributes.find("key");
444  if ((it != temp_MapAttributes.end())) // We expected this much.
445  {
446  std::string& str_key = it->second;
447 
448  if (str_key.size() >
449  0) // Success finding key type ('A' 'E' or 'S')
450  {
451 
452  mapPublic.insert(std::pair<std::string, std::string>(
453  str_key, strPublicInfo.Get()));
454 
455  }
456  // else it's empty, which is expected if nothing was there,
457  // since that's the default value
458  // that we set above for "name" in temp_MapAttributes.
459  else {
460  otErr << __FUNCTION__
461  << ": Expected key type of 'A' or 'E' or 'S'.\n";
462  return (-1); // error condition
463  }
464  }
465  else {
466  otErr << __FUNCTION__
467  << ": Strange error: couldn't find key type AT "
468  "ALL.\n"; // should never happen.
469  return (-1); // error condition
470  }
471  } // while
472 
473  if (static_cast<int64_t>(mapPublic.size()) != nCount) {
474  otErr << __FUNCTION__ << ", " << __FILE__ << ", " << __LINE__
475  << ": Subcredential expected to load " << nCount
476  << " publicInfo objects, "
477  "but actually loaded " << mapPublic.size()
478  << ". (Mismatch, failure loading.)\n";
479  return (-1); // error condition
480  }
481 
482  if (false ==
483  SetPublicContents(mapPublic)) // <============== Success.
484  {
485  otErr << __FUNCTION__ << ", " << __FILE__ << ", " << __LINE__
486  << ": Subcredential failed setting public contents while "
487  "loading.\n";
488  return (-1); // error condition
489  }
490 
491  } // if strCount.Exists() && nCount > 0
492 
493  otInfo << "Loaded publicContents for subcredential.\n";
494 
495  nReturnVal = 1;
496  }
497  else if (strNodeName.Compare("publicCredential")) {
499  xml, m_strContents)) // <========= m_strContents.
500  {
501  otErr << "Error in " << __FILE__ << " line " << __LINE__
502  << ": failed loading expected public credential while "
503  "loading private subcredential.\n";
504  return (-1); // error condition
505  }
506 
507  nReturnVal = 1;
508  }
509  else if (strNodeName.Compare("privateContents")) {
510  OTString strCount;
511  strCount = xml->getAttributeValue("count");
512  const int32_t nCount = strCount.Exists() ? atoi(strCount.Get()) : 0;
513  if (nCount > 0) {
514  int32_t nTempCount = nCount;
515  OTString::Map mapPrivate;
516 
517  while (nTempCount-- > 0) {
518 
519  const char* pElementExpected = "privateInfo";
520  OTString strPrivateInfo;
521 
522  // This map contains values we will also want, when we read the
523  // info...
524  // (The OTContract::LoadEncodedTextField call below will read
525  // all the values
526  // as specified in this map.)
527  //
528  OTString::Map temp_MapAttributes;
529  temp_MapAttributes.insert(std::pair<std::string, std::string>(
530  "key",
531  "")); // Value should be "A" or "E" or "S" after reading.
532 
534  xml, strPrivateInfo, pElementExpected,
535  &temp_MapAttributes)) // </privateInfo>
536  {
537  otErr << __FUNCTION__ << ": Error: Expected "
538  << pElementExpected << " element with text field.\n";
539  return (-1); // error condition
540  }
541 
542  auto it = temp_MapAttributes.find("key");
543  if ((it != temp_MapAttributes.end())) // We expected this much.
544  {
545  std::string& str_key = it->second;
546 
547  if (str_key.size() >
548  0) // Success finding key type ('A' 'E' or 'S')
549  {
550 
551  mapPrivate.insert(std::pair<std::string, std::string>(
552  str_key, strPrivateInfo.Get()));
553 
554  }
555  // else it's empty, which is expected if nothing was there,
556  // since that's the default value
557  // that we set above for "name" in temp_MapAttributes.
558  else {
559  otErr << __FUNCTION__
560  << ": Expected key type of 'A' or 'E' or 'S'.\n";
561  return (-1); // error condition
562  }
563  }
564  else {
565  otErr << __FUNCTION__
566  << ": Strange error: couldn't find key type AT "
567  "ALL.\n"; // should never happen.
568  return (-1); // error condition
569  }
570  } // while
571 
572  if (static_cast<int64_t>(mapPrivate.size()) != nCount) {
573  otErr << __FUNCTION__ << ", " << __FILE__ << ", " << __LINE__
574  << ": Subcredential expected to load " << nCount
575  << " privateInfo objects, "
576  "but actually loaded " << mapPrivate.size()
577  << ". (Mismatch, failure loading.)\n";
578  return (-1); // error condition
579  }
580 
581  OT_ASSERT(nullptr != m_pOwner);
582 
583  // Sometimes we are supposed to use a specific, pre-specified
584  // password (versus just
585  // blindly asking the user to type a password when it's not cached
586  // alrady.) For example,
587  // when importing a Nym, the exported version of the Nym is not
588  // encrypted to the cached
589  // wallet key. It's got its own exported passphrase. So it won't be
590  // cached, and we will have
591  // the wallet's cached key disabled while loading it. This means we
592  // have to enter the same
593  // passphrase many times in a row, while OT loads up all the
594  // credentials and keys for that
595  // Nym. Therefore, instead, we ask the user up front to enter the
596  // special passphrase for that
597  // exported Nym. Then we just pass it in to all the functions that
598  // need it, so none of them have
599  // to ask the user to type it.
600  //
601  // That's what brings us here now... when that happens,
602  // m_pOwner->GetImportPassword() will be set
603  // with the appropriate pointer to the passphrase. Otherwise it will
604  // be nullptr. Meanwhile SetPrivateContents
605  // below accepts an import passphrase, which it defaults to nullptr.
606  //
607  // So we just pass it in either way (sometimes it's nullptr and the
608  // wallet cached master key is used, and
609  // sometimes an actual passphrase is passed in, so we use it.)
610 
611  if (false ==
613  otErr << __FUNCTION__ << ", " << __FILE__ << ", " << __LINE__
614  << ": Subcredential failed setting private contents "
615  "while loading.\n";
616  return (-1); // error condition
617  }
618 
619  } // if strCount.Exists() && nCount > 0
620 
621  otInfo << "Loaded privateContents for subcredential.\n";
622 
623  nReturnVal = 1;
624  }
625 
626  return nReturnVal;
627 }
628 
629 bool OTSubcredential::SaveContractWallet(std::ofstream&) const
630 {
631  return false;
632 }
633 
634 // VERIFICATION
635 
636 // Verify that m_strNymID is the same as the hash of m_strSourceForNymID.
637 //
639 {
640 
641  // Verify that m_strNymID is the same as the hash of m_strSourceForNymID.
642  //
643  OTIdentifier theTempID;
644  const bool bCalculate = theTempID.CalculateDigest(m_strSourceForNymID);
645  OT_ASSERT(bCalculate);
646 
647  const OTString strNymID(theTempID);
648  if (!m_strNymID.Compare(strNymID)) {
649  otOut << __FUNCTION__
650  << ": Failure: When the NymID's source is hashed, the result "
651  "doesn't match the expected NymID.\n"
652  "Expected: " << m_strNymID << "\n Found: " << strNymID
653  << "\n Source: " << m_strSourceForNymID << "\n";
654  return false;
655  }
656 
657  return true;
658 }
659 
660 // Call VerifyNymID. Then verify m_strMasterCredID against the hash of
661 // m_pOwner->GetMasterkey().GetPubCredential() (the master credential.) Verify
662 // that
663 // m_pOwner->GetMasterkey() and *this have the same NymID. Then verify the
664 // signature of m_pOwner->GetMasterkey().
665 //
667 {
668  OT_ASSERT(nullptr != m_pOwner);
669 
670  // Verify that m_strNymID is the same as the hash of m_strSourceForNymID.
671  //
672  if (!VerifyNymID()) return false;
673 
674  // Verify that m_pOwner->GetMasterkey() and *this have the same NymID.
675  //
677  otOut << __FUNCTION__
678  << ": Failure: The actual master credential's NymID doesn't "
679  "match the NymID on this subcredential.\n"
680  " This NymID: " << m_strNymID
681  << "\nMaster's NymID: " << m_pOwner->GetMasterkey().GetNymID()
682  << "\n My Master Cred ID: " << m_strMasterCredID << "\n";
683  return false;
684  }
685 
686  // Verify m_strMasterCredID against the hash of
687  // m_pOwner->GetMasterkey().GetPubCredential()
688  // (the master credentialID is a hash of the master credential.)
689  //
690  OTIdentifier theActualMasterID;
691  const bool bCalcMasterCredID =
692  theActualMasterID.CalculateDigest(m_pOwner->GetPubCredential());
693  OT_ASSERT(bCalcMasterCredID);
694  const OTString strActualMasterID(theActualMasterID);
695 
696  if (!m_strMasterCredID.Compare(strActualMasterID)) {
697  otOut << __FUNCTION__
698  << ": Failure: When the actual Master Credential is hashed, the "
699  "result doesn't match the expected Master Credential ID.\n"
700  "Expected: " << m_strMasterCredID
701  << "\n Found: " << strActualMasterID << "\nMaster Cred:\n"
702  << m_pOwner->GetPubCredential() << "\n";
703  return false;
704  }
705 
706  // Then verify the signature of m_pOwner->GetMasterkey()...
707  // Let's get a few things straight:
708  // * OTMasterkey is a key (derived from OTKeyCredential, derived from
709  // OTSubcredential) and it can only sign itself.
710  // * The only further verification a Masterkey can get is if its hash is
711  // posted at the source. Or, if the source
712  // is a public key, then the master key must be signed by the
713  // corresponding private key. (Again: itself.)
714  // * Conversely to a master key which can ONLY sign itself, all subkeys must
715  // ALSO sign themselves.
716  //
717  // * Thus: Any OTKeyCredential (both master and subkeys, but no other
718  // credentials) must ** sign itself.**
719  // * Whereas m_strMasterSigned is only used by OTSubkey, and thus only must
720  // be verified there.
721  // * Any OTSubcredential must also be signed by its master. (Except masters,
722  // which already sign themselves.)
723  // * Any OTMasterkey must (at some point, and/or regularly) verify against
724  // its own source.
725 
726  // * Any OTSubcredential must also be signed by its master. (Except masters,
727  // which already sign themselves.)
728  //
729  if (!VerifySignedByMaster()) {
730  otOut << __FUNCTION__ << ": Failure: This subcredential hasn't been "
731  "signed by its master credential.\n";
732  return false;
733  }
734 
735  return true;
736 }
737 
739 {
740  OT_ASSERT(nullptr != m_pOwner);
742 }
743 
745 {
746  if (!VerifyContractID()) {
747  otWarn << __FUNCTION__ << ": Failed verifying credential ID against "
748  "whatever it was expected to be.\n";
749  return false;
750  }
751 
752  if (!VerifyInternally()) // Logs copiously.
753  return false;
754 
755  return true;
756 }
757 
758 // Overriding from OTContract.
760 {
761  if (!newID.CalculateDigest(GetPubCredential()))
762  otErr << __FUNCTION__ << ": Error calculating credential digest.\n";
763 }
764 
765 // I needed this for exporting a Nym (with credentials) from the wallet.
767 {
768  OT_ASSERT_MSG(!m_mapPrivateInfo.empty(), "ASSERT: GetPriCredential can "
769  "only be called on private "
770  "subcredentials.");
771 
772  return m_strRawFile;
773 }
774 
775 // We don't want to have to figure this out each time we need the public
776 // credential, so we just
777 // call this function wherever we need to get the public credential.
778 //
779 const OTString& OTSubcredential::GetPubCredential() const // More intelligent
780  // version of
781  // GetContents. Higher
782  // level.
783 {
784  // If this is a private (client-side) credential containing private keys,
785  // then the public version is stored in GetContents(), and return that.
786  if ((!m_mapPrivateInfo.empty()) && GetContents().Exists())
787  return GetContents();
788 
789  // Otherwise this is a server-side copy of a Nym's credential, with no
790  // private keys inside it.
791  // In which case public info that would have been in GetContents (making
792  // room so we can have
793  // the private keys in m_strRawFile) is now directly found in m_strRawFile,
794  // since that's all the
795  // server ever loads up. There is only public info and nothing else, so it's
796  // found in the main
797  // normal location, m_strRawFile.
798  //
799  return m_strRawFile;
800 }
801 
802 } // namespace opentxs
std::map< std::string, std::string > Map
Definition: OTString.hpp:162
void UpdatePublicCredentialToString(OTString &strAppendTo)
EXPORT const OTAsymmetricKey & GetPublicKey() const
Definition: OTKeypair.cpp:229
EXPORT bool CalculateDigest(const OTData &dataInput)
const OTString & GetContents() const
void SetOwner(OTCredential &theOwner)
const OTString & GetMasterCredID() const
void SetMasterCredID(const OTString &strMasterCredID)
virtual bool VerifySignedByMaster()
virtual EXPORT bool VerifyContractID() const
Definition: OTContract.cpp:379
OTLOG_IMPORT OTLogStream otOut
void UpdatePublicContentsToString(OTString &strAppendTo)
virtual bool SetPrivateContents(const OTString::Map &mapPrivate, const OTPassword *pImportPassword=nullptr)
void UpdateMasterPublicToString(OTString &strAppendTo)
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
EXPORT bool VerifyWithKey(const OTAsymmetricKey &theKey, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:848
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT bool SetString(const OTString &theData, bool bLineBreaks=true)
const OTString & GetPriCredential() const
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
void SetNymIDandSource(const OTString &strNymID, const OTString &strSourceForNymID)
virtual bool SaveContractWallet(std::ofstream &) const
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTString m_strContractType
Definition: OTContract.hpp:178
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
OTLOG_IMPORT OTLogStream otInfo
EXPORT const OTString & GetPubCredential() const
const OTString & GetNymID() const
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
OTLOG_IMPORT OTLogStream otWarn
const OTString & GetNymIDSource() const
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
void UpdatePrivateContentsToString(OTString &strAppendTo)
EXPORT const OTPassword * GetImportPassword() const
EXPORT const OTMasterkey & GetMasterkey() const
virtual EXPORT void Release()
Definition: OTContract.cpp:277
EXPORT const OTString & GetPubCredential() const
virtual bool SetPublicContents(const OTString::Map &mapPublic)
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
EXPORT bool GetString(OTString &theData, bool bLineBreaks=true) const
virtual EXPORT void Release()
Definition: OTString.cpp:765
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
static bool LoadEncodedTextFieldByName(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput, const char *&szName, OTString::Map *pmapExtraVars=nullptr)