Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTCredential.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTCredential.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 
149 #include "crypto/OTCredential.hpp"
150 #include "util/OTFolders.hpp"
151 #include "OTLog.hpp"
152 #include "crypto/OTPasswordData.hpp"
153 #include "OTStorage.hpp"
154 #include "crypto/OTSubkey.hpp"
155 
156 #include <memory>
157 #include <algorithm>
158 
159 // '0' for cKeyType means, theSignature MUST have metadata in order for ANY keys
160 // to be returned, and it MUST match.
161 // Whereas if you pass 'A', 'E', or 'S' for cKeyType, that means it can ONLY
162 // return authentication, encryption, or signing
163 // keys. It also means that metadata must match IF it's present, but that
164 // otherwise, if theSignature has no metadata at
165 // all, then it will still be a "presumed match" and returned as a possibility.
166 // (With the 'A', 'E', or 'S' enforced.)
167 //
168 
169 namespace opentxs
170 {
171 
173  listOfAsymmetricKeys& listOutput, const OTSignature& theSignature,
174  char cKeyType) const // 'S' (signing key) or 'E' (encryption key)
175  // or 'A' (authentication key)
176 {
177  int32_t nCount = 0;
178  for (const auto& it : m_mapSubcredentials) {
179  const OTSubcredential* pSub = it.second;
180  OT_ASSERT(nullptr != pSub);
181 
182  const OTSubkey* pKey = dynamic_cast<const OTSubkey*>(pSub);
183  if (nullptr == pKey)
184  continue; // Skip all non-key credentials. We're looking for keys.
185 
186  const int32_t nTempCount =
187  pKey->GetPublicKeysBySignature(listOutput, theSignature, cKeyType);
188  nCount += nTempCount;
189  }
190  return nCount;
191 }
192 
194 {
195 
196  OTIdentifier theActualMasterCredID;
197  theActualMasterCredID.CalculateDigest(m_Masterkey.GetPubCredential());
198  const OTString strActualMasterCredID(theActualMasterCredID);
199 
200  if (!m_strNymID.Compare(m_Masterkey.GetNymID())) {
201  otOut << __FUNCTION__
202  << ": NymID did not match its "
203  "counterpart in m_Masterkey (failed to verify): " << GetNymID()
204  << "\n";
205  return false;
206  }
207 
208  if (!m_strMasterCredID.Compare(strActualMasterCredID)) {
209  otOut << __FUNCTION__
210  << ": Master Credential ID did not match its "
211  "counterpart in m_Masterkey:\nExpected Master Credential ID: "
212  << GetMasterCredID()
213  << "\n "
214  "Hash of m_Masterkey contents: " << strActualMasterCredID
215  << "\nContents:\n" << m_Masterkey.GetPubCredential() << "\n";
216  return false;
217  }
218 
219  if (!const_cast<OTMasterkey&>(m_Masterkey).VerifyContract()) {
220  otOut << __FUNCTION__
221  << ": Master Credential failed to verify: " << GetMasterCredID()
222  << "\nNymID: " << GetNymID() << "\n";
223  return false;
224  }
225 
226  for (const auto& it : m_mapSubcredentials) {
227  std::string str_sub_id = it.first;
228  OTSubcredential* pSub = it.second;
229  OT_ASSERT(nullptr != pSub);
230 
231  if (!pSub->VerifyContract()) {
232  otOut << __FUNCTION__
233  << ": Subcredential failed to verify: " << str_sub_id
234  << "\nNymID: " << GetNymID() << "\n";
235  return false;
236  }
237  }
238 
239  return true;
240 }
241 
243 {
244  // * Any OTMasterkey must (at some point, and/or regularly) verify against
245  // its own source.
246  //
247  if (!m_Masterkey.VerifyAgainstSource()) {
248  otWarn
249  << __FUNCTION__
250  << ": Failed verifying master credential against its own source.\n";
251  return false;
252  }
253  // NOTE: This spot will have a significant delay, TODO OPTIMIZE. Performing
254  // a Freenet lookup, or DNS, etc,
255  // will introduce delay inside the call VerifyAgainstSource. Therefore in
256  // the int64_t term, we must have a
257  // separate server process which will verify identities for some specified
258  // period of time (specified in
259  // their credentials I suppose...) That way, when we call
260  // VerifyAgainstSource, we are verifying against
261  // some server-signed authorization, based on a lookup that some separate
262  // process did within the past
263  // X allowed time, such that the lookup is still considered valid (without
264  // having to lookup every single
265  // time, which is untenable.)
266 
267  return true;
268 }
269 
270 // Contains a "master" subkey,
271 // and a list of "sub" subkeys signed by that master.
272 // Each subkey can generate its own "credential" contract,
273 // so OTCredential actually may include many "credentials."
274 // A nym has multiple OTCredentials because there may be
275 // several master keys.
276 //
277 
279 {
280  return m_strNymID;
281 }
282 
284 {
285  return m_strSourceForNymID;
286 }
287 
291 void OTCredential::SetSourceForNymID(const OTString& strSourceForNymID)
292 {
293  m_strSourceForNymID = strSourceForNymID;
294 
295  // Now re-calculate the NymID...
296  //
297  m_strNymID.Release();
298  OTIdentifier theTempID;
299  const bool bCalculate = theTempID.CalculateDigest(m_strSourceForNymID);
300  OT_ASSERT(bCalculate);
301  theTempID.GetString(m_strNymID);
302 
303  m_Masterkey.SetNymIDandSource(
304  m_strNymID, m_strSourceForNymID); // The key in here must somehow verify
305  // against its own source.
306 
307  // Success! By this point, m_strSourceForNymID and m_strNymID
308  // are both set.
309 }
310 
312 {
313  return m_Masterkey.GetPubCredential();
314 }
315 
317 {
318  return m_Masterkey.GetPriCredential();
319 }
320 
321 bool OTCredential::SetPublicContents(const OTString::Map& mapPublic)
322 {
323  return m_Masterkey.SetPublicContents(mapPublic);
324 }
325 
326 bool OTCredential::SetPrivateContents(const OTString::Map& mapPrivate)
327 {
328  return m_Masterkey.SetPrivateContents(mapPrivate);
329 }
330 
331 // private
332 OTCredential::OTCredential()
333  : m_Masterkey(*this)
334  , m_pImportPassword(nullptr)
335 {
336 }
337 
338 void OTCredential::SetMasterCredID(const OTString& strID)
339 {
340  m_strMasterCredID = strID;
341 }
342 
344 {
345  return m_strMasterCredID;
346 }
347 
348 // static (Caller is responsible to delete.)
350  const OTString& strNymID, // Caller is responsible to delete, in both
351  // CreateMaster and LoadMaster.
352  const OTString& strMasterCredID, const OTPasswordData* pPWData)
353 {
354  OTCredential* pCredential = new OTCredential;
355  std::unique_ptr<OTCredential> theCredentialAngel(pCredential);
356  OT_ASSERT(nullptr != pCredential);
357 
358  OTPasswordData thePWData("Loading master credential. (static 1.)");
359  const bool bLoaded = pCredential->Load_Master(
360  strNymID, strMasterCredID, (nullptr == pPWData) ? &thePWData : pPWData);
361  if (!bLoaded) {
362  otErr << __FUNCTION__ << ": Failed trying to load master credential "
363  "from local storage. 1\n";
364  return nullptr;
365  }
366 
367  return theCredentialAngel.release();
368 }
369 
370 // static (Caller is responsible to delete.)
372  const OTString& strInput,
373  const OTString& strNymID, // Caller is responsible to delete, in both
374  // CreateMaster and LoadMaster.
375  const OTString& strMasterCredID, OTPasswordData* pPWData,
376  const OTPassword* pImportPassword)
377 {
378  OTCredential* pCredential = new OTCredential;
379  std::unique_ptr<OTCredential> theCredentialAngel(pCredential);
380  OT_ASSERT(nullptr != pCredential);
381 
382  OTPasswordData thePWData(nullptr == pImportPassword
383  ? "Enter wallet master passphrase."
384  : "Enter passphrase for exported Nym.");
385  const bool bLoaded = pCredential->Load_MasterFromString(
386  strInput, strNymID, strMasterCredID,
387  (nullptr == pPWData) ? &thePWData : pPWData, pImportPassword);
388  if (!bLoaded) {
389  otErr << __FUNCTION__
390  << ": Failed trying to load master credential from string. 2\n";
391  return nullptr;
392  }
393 
394  return theCredentialAngel.release();
395 }
396 
397 // called by OTCredential::CreateMaster
398 bool OTCredential::SignNewMaster(const OTPasswordData* pPWData)
399 {
400  OTPasswordData thePWData(
401  "Signing new master credential... OTCredential::SignNewMaster");
402 
403  m_Masterkey.StoreAsPublic(); // So the version we create here only contains
404  // public keys, not private.
405  const bool bSignedPublic = m_Masterkey.Sign(
406  m_Masterkey, nullptr == pPWData ? &thePWData : pPWData);
407  if (bSignedPublic) {
408  m_Masterkey.SaveContract();
409  // THE OFFICIAL "PUBLIC CREDENTIAL" FOR THE MASTER KEY
410  // (Copied from the raw contents here into a member variable for
411  // safe-keeping.)
412  // Future verifiers can hash it and the output should match the master
413  // credential ID.
414  //
415  OTString strPublicCredential;
416 
417  if (m_Masterkey.SaveContractRaw(strPublicCredential)) {
418  m_Masterkey.SetContents(strPublicCredential); // <=== The "master
419  // public credential"
420  // string.
421  // NEW MASTER CREDENTIAL ID.
422  //
423  // Only now can we calculate the master key's ID, since the ID is a
424  // hash of
425  // the contents.
426  //
427  OTIdentifier theNewID;
428  m_Masterkey.CalculateContractID(theNewID);
429  m_Masterkey.SetIdentifier(theNewID); // Usually this will be set
430  // based on an expected value
431  // from above, then loaded from
432  // storage, and then verified
433  // against what was actually
434  // loaded (by hashing it.)
435 
436  const OTString strMasterCredID(theNewID);
437  SetMasterCredID(
438  strMasterCredID); // <=== Master Credential ID is now set.
439  }
440  else {
441  otErr << "In " << __FILE__ << ", line " << __LINE__
442  << ": Failed calling m_Masterkey.SaveContractRaw 1.\n";
443  return false;
444  }
445  // THE PRIVATE KEYS
446  //
447  // Next, we sign / save it again, this time in its private form, and
448  // also
449  // m_Masterkey.m_strContents and m_strIDsOnly will be contained within
450  // that
451  // private form along with the private keys.
452  //
453  m_Masterkey.ReleaseSignatures(); // This time we'll sign it in private
454  // mode.
455  const bool bSignedPrivate = m_Masterkey.Sign(
456  m_Masterkey, nullptr == pPWData ? &thePWData : pPWData);
457  if (bSignedPrivate) {
458  m_Masterkey.SaveContract();
459 
460  m_Masterkey.SetMetadata();
461  }
462  else {
463  otErr << "In " << __FILE__ << ", line " << __LINE__
464  << ": Failed trying to sign the master private credential.\n";
465  return false;
466  }
467  }
468  else {
469  otErr << "In " << __FILE__ << ", line " << __LINE__
470  << ": Failed trying to sign the master public credential.\n";
471  return false;
472  }
473 
474  return true;
475 }
476 
477 // When exporting a Nym, you don't want his private keys encrypted to the cached
478 // key
479 // for the wallet, so you have to load them up, and then pause OTCachedKey, and
480 // then
481 // save them to string again, re-encrypting them to the export passphrase (and
482 // not to
483 // any "master key" from the wallet.) And you have to release all the signatures
484 // on
485 // the private credentials, since the private info is being re-encrypted, and
486 // re-sign
487 // them all. Joy.
488 //
490  const OTPassword& theExportPassword, bool bImporting)
491 {
492  if (m_Masterkey.GetPrivateMap().size() > 0) {
493  OTPasswordData thePWData(
494  bImporting ? "2 Enter passphrase for the Nym being imported."
495  : "2 Enter new passphrase for exported Nym.");
496 
497  // Re-encrypt the private keys in the masterkey. (THEN sign.)
498  //
499  const bool bReEncryptMaster =
500  m_Masterkey.ReEncryptKeys(theExportPassword, bImporting);
501  bool bSignedMaster = false;
502 
503  if (bReEncryptMaster) {
504  m_Masterkey.ReleaseSignatures(); // This time we'll sign it in
505  // private mode.
506  bSignedMaster = m_Masterkey.Sign(m_Masterkey, &thePWData);
507  }
508  else {
509  otErr << "In " << __FILE__ << ", line " << __LINE__
510  << ": Failed trying to re-encrypt the private masterkey.\n";
511  return false;
512  }
513 
514  if (bSignedMaster) {
515  m_Masterkey.SaveContract();
516  m_Masterkey.SetMetadata(); // todo: can probably remove this, since
517  // it was set based on public info when
518  // the key was first created.
519 
520  for (auto& it : m_mapSubcredentials) {
521  OTSubcredential* pSub = it.second;
522  OT_ASSERT(nullptr != pSub);
523 
524  OTSubkey* pKey = dynamic_cast<OTSubkey*>(pSub);
525  if (nullptr == pKey) continue;
526 
527  const bool bReEncryptSubkey =
528  pKey->ReEncryptKeys(theExportPassword, bImporting);
529  bool bSignedSubkey = false;
530 
531  if (bReEncryptSubkey) {
532  pKey->ReleaseSignatures();
533  bSignedSubkey = pKey->Sign(*pKey, &thePWData);
534  }
535  else {
536  otErr << "In " << __FILE__ << ", line " << __LINE__
537  << ": Failed trying to re-encrypt the private "
538  "subkey.\n";
539  return false;
540  }
541 
542  if (bSignedSubkey) {
543  pKey->SaveContract();
544  pKey->SetMetadata(); // todo: can probably remove this,
545  // since it was set based on public
546  // info when the key was first created.
547  }
548  else {
549  otErr << "In " << __FILE__ << ", line " << __LINE__
550  << ": Failed trying to re-sign the private subkey.\n";
551  return false;
552  }
553  }
554 
555  return true; // <=== Success.
556  }
557  else
558  otErr << "In " << __FILE__ << ", line " << __LINE__
559  << ": Failed trying to re-sign the master private "
560  "credential.\n";
561  }
562  else
563  otErr << "In " << __FILE__ << ", line " << __LINE__
564  << ": Failed: There is no private info on this master "
565  "credential.\n";
566 
567  return false;
568 }
569 
570 bool OTCredential::SignNewSubcredential(OTSubcredential& theSubCred,
571  OTIdentifier& theSubCredID_out,
572  const OTPasswordData* pPWData)
573 {
574  OTPasswordData thePWData(
575  "Signing new subcredential... OTCredential::SignNewSubcredential");
576 
577  // First, we store the subcredential itself with its basic info.
578  // This version is signed with the Masterkey. Then we save a copy of it
579  // in a member variable for safe-keeping, m_strMasterSigned. Next, we
580  // save a "public" version of the subcredential (the official version)
581  // which will include m_strMasterSigned inside it, and be signed by the
582  // subkey. This version may not need to duplicate all that data, especially
583  // if we end up just having to verify it twice as a result. So I might have
584  // the public version be sparse (other than including the master signed
585  // version,
586  // and being signed by the subkey.)
587  // Though with many subcredentials, there will ONLY be the master-signed
588  // version,
589  // and that WILL be the public version. Only with subkeys will that be
590  // different!
591  //
592  OTSubkey* pSubkey = dynamic_cast<OTSubkey*>(&theSubCred);
593  const bool bIsSubkey = (nullptr != pSubkey); // It's not just any
594  // subcredential -- it's a
595  // subkey!
596 
597  // If it's not a subkey, but rather, a normal subcredential with no keys,
598  // then it doesn't need to contain a "master signed" version,
599  // since the entire subcredential will already be master signed, since
600  // there's no subkey to sign in that case.
601  if (!bIsSubkey) theSubCred.SetMasterSigned(OTString(""));
602 
603  // ELSE It's a subkey...
604  else // Subkeys must be self-signed, and must contain a master-signed
605  // version of themselves where the data is actually stored.
606  {
607  pSubkey->StoreAsMasterSigned(); // So the version we create here only
608  // contains public keys, not private.
609  // (And so it won't include
610  // the "master signed" version in what it stores, since that's what
611  // we're creating now.)
612 
613  const bool bMasterSigned = m_Masterkey.Sign(
614  *pSubkey, nullptr == pPWData ? &thePWData : pPWData);
615  if (!bMasterSigned) {
616  otErr << "In " << __FILE__ << ", line " << __LINE__
617  << ": Failed calling m_Masterkey.Sign(*pSubkey) "
618  "after StoreAsMasterSigned.\n";
619  return false;
620  }
621  else {
622  pSubkey->SaveContract();
623 
624  // Make a copy of the "master signed" version of the public
625  // subcredential.
626  //
627  OTString strMasterSigned;
628 
629  if (pSubkey->SaveContractRaw(strMasterSigned)) // <=== The "master
630  // signed" version of
631  // the "public
632  // credential"
633  // string. Captured
634  // here
635  pSubkey->SetMasterSigned(strMasterSigned); // so that the
636  // (subkey-signed)
637  // public version of
638  // the subcredential
639  // will contain it.
640  else {
641  otErr << "In " << __FILE__ << ", line " << __LINE__
642  << ": Failed calling pSubkey->SaveContractRaw 1.\n";
643  return false;
644  }
645  }
646 
647  pSubkey->ReleaseSignatures();
648  }
649  theSubCred.StoreAsPublic(); // So the version we create here only contains
650  // public keys, not private.
651 
652  // Here, dynamic cast theSubCred to a subkey and if successful, use it to
653  // sign itself.
654  // Otherwise, sign it with the master. (If it's a real subkey, then it will
655  // contain the
656  // master-signed version, and it will be signed with itself, its own subkey.
657  // Whereas if
658  // it's a subcredential that is NOT a subkey, such as a Google Authenticator
659  // or some other
660  // 3rd-party authentication, then it will HAVE no key to sign itself with,
661  // since its primary
662  // purpose in that case is to provide some OTHER authentication info INSTEAD
663  // of a key.
664  // So in that case, it must be signed by the master.)
665  //
666  bool bSignedPublic = false;
667 
668  if (bIsSubkey) // If it's a subkey, its keys are already generated by the
669  // time we got here. So use it to sign its own public
670  // version.
671  bSignedPublic = pSubkey->Sign(
672  theSubCred, nullptr == pPWData ? &thePWData : pPWData);
673  else // It's not a subkey, but some other conventional subcredential. So we
674  // sign with master key, since that's all we've got.
675  bSignedPublic = m_Masterkey.Sign(
676  theSubCred, nullptr == pPWData ? &thePWData : pPWData);
677 
678  if (!bSignedPublic) {
679  otErr
680  << "In " << __FILE__ << ", line " << __LINE__
681  << ": Failed trying to sign the public subcredential or subkey.\n";
682  return false;
683  }
684  else {
685  theSubCred.SaveContract();
686  // THE OFFICIAL "PUBLIC CREDENTIAL STRING" FOR THIS NEW SUB-CREDENTIAL
687  // Set it aside for safe-keeping as the official contents, hashable to
688  // form
689  // the ID for this sub-credential.
690  //
691  OTString strPublicCredential;
692  if (theSubCred.SaveContractRaw(strPublicCredential)) {
693  theSubCred.SetContents(strPublicCredential); // <=== The "public
694  // credential" string
695  // aka the contents.
696  // NEW SUB-CREDENTIAL ID.
697  //
698  // Only now that the contents have been set, can we calculate the
699  // ID, which
700  // is a hash of those contents. (Credential ID is a hash of
701  // GetPubCredential instead
702  // of m_strRawXML as most contracts would use, since we only want to
703  // use the PUBLIC
704  // info for calculating the ID, not the private info.)
705  //
706  theSubCred.CalculateContractID(theSubCredID_out);
707  theSubCred.SetIdentifier(theSubCredID_out);
708  }
709  else {
710  otErr << "In " << __FILE__ << ", line " << __LINE__
711  << ": Failed calling theSubCred.SaveContractRaw.\n";
712  return false;
713  }
714  // CREATE THE PRIVATE FORM.
715  //
716  // Next, we sign / save it again, this time in its private form, and
717  // also
718  // theSubCred.m_strContents will be contained within that private form,
719  // along with the private keys.
720  //
721  theSubCred.ReleaseSignatures(); // This time we'll sign it in private
722  // mode.
723  bool bSignedPrivate = false;
724 
725  if (bIsSubkey) // If it's a subkey, its keys are already generated by
726  // the time we got here. So use it to sign its own
727  // private version.
728  bSignedPrivate = pSubkey->Sign(
729  theSubCred, nullptr == pPWData ? &thePWData : pPWData);
730  else // It's not a subkey, but some other conventional subcredential. So
731  // we sign the private info with the master key, since that's all
732  // we've got.
733  bSignedPrivate = m_Masterkey.Sign(
734  theSubCred, nullptr == pPWData ? &thePWData : pPWData);
735 
736  if (bSignedPrivate)
737  theSubCred.SaveContract();
738  else {
739  otErr << "In " << __FILE__ << ", line " << __LINE__
740  << ": Failed trying to sign the private subcredential.\n";
741  return false;
742  }
743  }
744 
745  return true;
746 }
747 
748 bool OTCredential::GenerateMasterkey(int32_t nBits) // CreateMaster is
749  // able to create
750  // keys from
751  // scratch (by
752  // calling this
753  // function.)
754 {
755  return m_Masterkey.GenerateKeys(nBits);
756 }
757 
759  const OTString& strNymID,
760  const OTString& strMasterCredID,
761  const OTPasswordData*,
762  const OTPassword* pImportPassword)
763 {
764  m_strNymID = strNymID;
765  m_strMasterCredID = strMasterCredID;
766 
767  m_Masterkey.SetIdentifier(strMasterCredID);
768 
769  // m_Masterkey and the subkeys all have a pointer to "owner" (who is *this)
770  // and so I can set pImportPassword onto a member variable, perform the
771  // load,
772  // and then set that member nullptr again. During the call to
773  // LoadContractFromString,
774  // m_Masterkey can reference m_pOwner->GetImportPassword() and if it's not
775  // nullptr,
776  // use it instead of using the wallet's cached master key. After all, if
777  // it's not
778  // nullptr here, that's why it was passed in.
779  //
780 
781  SetImportPassword(pImportPassword); // might be nullptr.
782 
783  const bool bLoaded = m_Masterkey.LoadContractFromString(strInput);
784  if (!bLoaded) {
785  otErr << __FUNCTION__
786  << ": Failed trying to load master credential from string.\n";
787  return false;
788  }
789 
790  SetImportPassword(nullptr); // It was only set during the
791  // m_Masterkey.LoadContractFromString (which
792  // references it.)
793 
794  m_strNymID = m_Masterkey.GetNymID();
795  m_strSourceForNymID = m_Masterkey.GetNymIDSource();
796 
797  ClearSubcredentials(); // The master is loaded first, and then any
798  // subcredentials. So this is probably already
799  // empty. Just looking ahead.
800 
801  m_Masterkey.SetMetadata();
802 
803  return true;
804 }
805 
806 bool OTCredential::Load_Master(const OTString& strNymID,
807  const OTString& strMasterCredID,
808  const OTPasswordData* pPWData)
809 {
810 
811  std::string str_Folder =
812  OTFolders::Credential().Get(); // Try private credential first. If that
813  // fails, then public.
814 
815  if (false ==
816  OTDB::Exists(str_Folder, strNymID.Get(), strMasterCredID.Get())) {
817  str_Folder = OTFolders::Pubcred().Get();
818 
819  if (false ==
820  OTDB::Exists(str_Folder, strNymID.Get(), strMasterCredID.Get())) {
821  otErr << __FUNCTION__ << ": Failure: Master Credential "
822  << strMasterCredID << " doesn't exist for Nym " << strNymID
823  << "\n";
824  return false;
825  }
826  }
827 
828  OTString strFileContents(OTDB::QueryPlainString(str_Folder, strNymID.Get(),
829  strMasterCredID.Get()));
830  if (!strFileContents.Exists()) {
831  otErr << __FUNCTION__ << ": Failed trying to load master credential "
832  "from local storage.\n";
833  return false;
834  }
835 
836  if (false ==
837  strFileContents.DecodeIfArmored()) // bEscapedIsAllowed=true by default.
838  {
839  otErr << __FUNCTION__ << ": File contents apparently were encoded and "
840  "then failed decoding. Contents: \n"
841  << strFileContents << "\n";
842  return false;
843  }
844 
845  return Load_MasterFromString(strFileContents, strNymID, strMasterCredID,
846  pPWData);
847 }
848 
850  const OTString& strSubID,
851  const OTPassword* pImportPassword)
852 {
853  // Make sure it's not already there.
854  //
855  auto it = m_mapSubcredentials.find(strSubID.Get());
856  if (it != m_mapSubcredentials.end()) // It was already there. (Reload it.)
857  {
858  otErr << __FUNCTION__ << ": Warning: Deleting and re-loading "
859  "keyCredential that was already loaded.\n";
860  OTSubcredential* pSub = it->second;
861  OT_ASSERT(nullptr != pSub);
862  delete pSub;
863  m_mapSubcredentials.erase(it);
864  }
865 
866  OTSubkey* pSub = new OTSubkey(*this);
867  std::unique_ptr<OTSubkey> theSubAngel(pSub);
868  OT_ASSERT(nullptr != pSub);
869 
870  pSub->SetIdentifier(strSubID);
871  pSub->SetNymIDandSource(GetNymID(),
872  GetSourceForNymID()); // Set NymID and source
873  // string that hashes to
874  // it.
875  pSub->SetMasterCredID(GetMasterCredID()); // Set master credential ID
876  // (onto this new
877  // subcredential...)
878 
879  SetImportPassword(pImportPassword); // might be nullptr.
880 
881  if (!pSub->LoadContractFromString(strInput)) {
882  otErr << __FUNCTION__
883  << ": Failed trying to load keyCredential from string.\n";
884  return false;
885  }
886 
887  SetImportPassword(nullptr); // Only set int64_t enough for
888  // LoadContractFromString above to use it.
889 
890  pSub->SetMetadata();
891 
892  m_mapSubcredentials.insert(std::pair<std::string, OTSubcredential*>(
893  strSubID.Get(), theSubAngel.release()));
894 
895  return true;
896 }
897 
898 bool OTCredential::LoadSubkey(const OTString& strSubID)
899 {
900 
901  std::string str_Folder =
902  OTFolders::Credential().Get(); // Try private credential first. If that
903  // fails, then public.
904 
905  if (!OTDB::Exists(str_Folder, GetNymID().Get(), strSubID.Get())) {
906  str_Folder = OTFolders::Pubcred().Get();
907 
908  if (false ==
909  OTDB::Exists(str_Folder, GetNymID().Get(), strSubID.Get())) {
910  otErr << __FUNCTION__ << ": Failure: Key Credential " << strSubID
911  << " doesn't exist for Nym " << GetNymID() << "\n";
912  return false;
913  }
914  }
915 
916  OTString strFileContents(
917  OTDB::QueryPlainString(str_Folder, GetNymID().Get(), strSubID.Get()));
918 
919  if (!strFileContents.Exists()) {
920  otErr << __FUNCTION__
921  << ": Failed trying to load keyCredential from local storage.\n";
922  return false;
923  }
924 
925  if (false ==
926  strFileContents.DecodeIfArmored()) // bEscapedIsAllowed=true by default.
927  {
928  otErr << __FUNCTION__ << ": File contents apparently were encoded and "
929  "then failed decoding. Contents: \n"
930  << strFileContents << "\n";
931  return false;
932  }
933 
934  return LoadSubkeyFromString(strFileContents, strSubID);
935 }
936 
938  const OTString& strInput, const OTString& strSubID,
939  const OTPassword* pImportPassword)
940 {
941  // Make sure it's not already there.
942  //
943  auto it = m_mapSubcredentials.find(strSubID.Get());
944  if (it != m_mapSubcredentials.end()) // It was already there. (Reload it.)
945  {
946  otErr << __FUNCTION__ << ": Warning: Deleting and re-loading "
947  "subCredential that was already loaded.\n";
948  OTSubcredential* pSub = it->second;
949  OT_ASSERT(nullptr != pSub);
950  delete pSub;
951  m_mapSubcredentials.erase(it);
952  }
953 
954  OTSubcredential* pSub = new OTSubcredential(*this);
955  std::unique_ptr<OTSubcredential> theSubAngel(pSub);
956  OT_ASSERT(nullptr != pSub);
957 
958  pSub->SetIdentifier(strSubID);
959  pSub->SetNymIDandSource(GetNymID(),
960  GetSourceForNymID()); // Set NymID and source
961  // string that hashes to
962  // it.
963  pSub->SetMasterCredID(GetMasterCredID()); // Set master credential ID
964  // (onto this new
965  // subcredential...)
966 
967  SetImportPassword(pImportPassword); // might be nullptr.
968 
969  if (!pSub->LoadContractFromString(strInput)) {
970  otErr << __FUNCTION__
971  << ": Failed trying to load subCredential from string.\n";
972  return false;
973  }
974 
975  SetImportPassword(nullptr); // This is only set int64_t enough for
976  // LoadContractFromString to use it. (Then
977  // back to nullptr.)
978 
979  m_mapSubcredentials.insert(std::pair<std::string, OTSubcredential*>(
980  strSubID.Get(), theSubAngel.release()));
981 
982  return true;
983 }
984 
986 {
987 
988  std::string str_Folder =
989  OTFolders::Credential().Get(); // Try private credential first. If that
990  // fails, then public.
991 
992  if (!OTDB::Exists(str_Folder, GetNymID().Get(), strSubID.Get())) {
993  str_Folder = OTFolders::Pubcred().Get();
994 
995  if (false ==
996  OTDB::Exists(str_Folder, GetNymID().Get(), strSubID.Get())) {
997  otErr << __FUNCTION__ << ": Failure: Credential " << strSubID
998  << " doesn't exist for Nym " << GetNymID() << "\n";
999  return false;
1000  }
1001  }
1002 
1003  OTString strFileContents(
1004  OTDB::QueryPlainString(str_Folder, GetNymID().Get(), strSubID.Get()));
1005  if (!strFileContents.Exists()) {
1006  otErr << __FUNCTION__
1007  << ": Failed trying to load subCredential from local storage.\n";
1008  return false;
1009  }
1010 
1011  if (false ==
1012  strFileContents.DecodeIfArmored()) // bEscapedIsAllowed=true by default.
1013  {
1014  otErr << __FUNCTION__ << ": File contents apparently were encoded and "
1015  "then failed decoding. Contents: \n"
1016  << strFileContents << "\n";
1017  return false;
1018  }
1019 
1020  return LoadSubcredentialFromString(strFileContents, strSubID);
1021 }
1022 
1023 // For adding subcredentials that are specifically *subkeys*. Meaning it will
1024 // contain 3 keypairs: signing, authentication, and encryption.
1025 //
1027  int32_t nBits, // Ignored unless pmapPrivate is nullptr
1028  const OTString::Map* pmapPrivate, // Public keys are derived from
1029  // the private.
1030  const OTPasswordData* pPWData, // The master key will sign the subkey.
1031  OTSubkey** ppSubkey) // output
1032 {
1033  OTSubkey* pSub = new OTSubkey(*this);
1034  OT_ASSERT(nullptr != pSub);
1035 
1036  pSub->SetNymIDandSource(GetNymID(),
1037  GetSourceForNymID()); // Set NymID and source
1038  // string that hashes to
1039  // it.
1040  pSub->SetMasterCredID(GetMasterCredID()); // Set master credential ID
1041  // (onto this new
1042  // subcredential...)
1043 
1044  // If a map of private certs was not passed in, we're expected to
1045  // generate the keys ourselves.
1046  //
1047  bool bContentsReady = false;
1048 
1049  if (nullptr !=
1050  pmapPrivate) // Pre-generated keys were passed in for us to use,
1051  bContentsReady = pSub->SetPrivateContents(
1052  *pmapPrivate); // so let's set them onto the sub key.
1053  else
1054  // No keys were provided, so let's generate them ourselves...
1055  bContentsReady = pSub->GenerateKeys(nBits);
1056 
1057  if (!bContentsReady) {
1058  otErr << "In " << __FILE__ << ", line " << __LINE__
1059  << ": Failed trying to SetPrivateContents or GenerateKeys\n";
1060  delete pSub;
1061  pSub = nullptr;
1062  return false;
1063  }
1064  else // By this point we've set up the subkey with its NymID, the source
1065  // string for that NymID,
1066  { // my master credential ID, and the public and private certs for the
1067  // subkey. Now let's
1068  // sign it...
1069  OTPasswordData thePWData(
1070  "Signing new subkey... OTCredential::AddNewSubkey");
1071  OTIdentifier theSubCredID;
1072 
1073  // SignNewSubcredential uses m_Masterkey's actual signing key to sign
1074  // "pSub the contract."
1075  //
1076  if (false ==
1077  SignNewSubcredential(*pSub, theSubCredID,
1078  nullptr == pPWData ? &thePWData : pPWData)) {
1079  otErr << "In " << __FILE__ << ", line " << __LINE__
1080  << ": Failed trying to call SignNewSubcredential\n";
1081  delete pSub;
1082  pSub = nullptr;
1083  return false;
1084  }
1085 
1086  const OTString strSubCredID(
1087  theSubCredID); // SignNewSubcredential also generates the ID.
1088 
1089  pSub->SetMetadata();
1090 
1091  // ADD IT TO THE MAP
1092  // Only after pSub is signed and saved can we then calculate its ID and
1093  // use that ID
1094  // as the key in m_mapSubcredentials (with pSub being the value.)
1095  //
1096  m_mapSubcredentials.insert(
1097  std::pair<std::string, OTSubcredential*>(strSubCredID.Get(), pSub));
1098 
1099  if (nullptr != ppSubkey) // output
1100  {
1101  *ppSubkey = pSub;
1102  }
1103 
1104  return true;
1105  }
1106 }
1107 
1108 // For adding non-key credentials, such as for 3rd-party authentication.
1109 //
1111  const OTString::Map& mapPrivate, const OTString::Map& mapPublic,
1112  const OTPasswordData* pPWData, // The master key will sign the
1113  // subcredential.
1114  OTSubcredential** ppSubcred) // output
1115 {
1116  OTSubcredential* pSub = new OTSubcredential(*this);
1117  OT_ASSERT(nullptr != pSub);
1118 
1119  pSub->SetNymIDandSource(m_strNymID, m_strSourceForNymID); // Set NymID and
1120  // source string
1121  // that hashes to
1122  // it.
1123  pSub->SetMasterCredID(GetMasterCredID()); // Set master credential ID
1124  // (onto this new
1125  // subcredential...)
1126 
1127  if (!pSub->SetPublicContents(mapPublic)) {
1128  otErr << "In " << __FILE__ << ", line " << __LINE__
1129  << ": Failed while calling pSub->SetPublicContents.\n";
1130  delete pSub;
1131  pSub = nullptr;
1132  return false;
1133  }
1134  else if (!pSub->SetPrivateContents(mapPrivate)) {
1135  otErr << "In " << __FILE__ << ", line " << __LINE__
1136  << ": Failed while trying to pSub->SetPrivateContents.\n";
1137  delete pSub;
1138  pSub = nullptr;
1139  return false;
1140  }
1141  else // By this point we've set up the subcredential with its NymID, the
1142  // source string for that NymID,
1143  { // my master credential ID, and the public and private contents for the
1144  // subcredential. Let's sign
1145  // it...
1146  OTPasswordData thePWData(
1147  "Signing new subcredential... OTCredential::AddNewSubcredential");
1148  OTIdentifier theSubCredID;
1149 
1150  // SignNewSubcredential uses m_Masterkey's actual signing key to sign
1151  // "pSub the contract."
1152  //
1153  if (false ==
1154  SignNewSubcredential(*pSub, theSubCredID,
1155  nullptr == pPWData ? &thePWData : pPWData)) {
1156  otErr << "In " << __FILE__ << ", line " << __LINE__
1157  << ": Failed trying to call SignNewSubcredential\n";
1158  delete pSub;
1159  pSub = nullptr;
1160  return false;
1161  }
1162 
1163  const OTString strSubCredID(theSubCredID);
1164 
1165  // ADD IT TO THE MAP
1166  // Only after pSub is signed and saved can we then calculate its ID and
1167  // use that ID
1168  // as the key in m_mapSubcredentials (with pSub being the value.)
1169  //
1170  m_mapSubcredentials.insert(
1171  std::pair<std::string, OTSubcredential*>(strSubCredID.Get(), pSub));
1172  if (nullptr != ppSubcred) // output
1173  *ppSubcred = pSub;
1174  return true;
1175  }
1176 }
1177 
1178 // After calling this, you still need to save it to disk (or not.) This function
1179 // alone
1180 // doesn't save anything to disk.
1181 //
1182 // static
1184  const OTString& strSourceForNymID,
1185  int32_t nBits, // Ignored unless pmapPrivate is nullptr.
1186  const OTString::Map* pmapPrivate, // If nullptr, then the keys are
1187  // generated in here.
1188  const OTString::Map* pmapPublic, // In the case of key credentials,
1189  // public is optional since it can
1190  // already be derived from
1191  // private. But not all
1192  // credentials are keys...
1193  const OTPasswordData* pPWData)
1194 {
1195  OTCredential* pCredential = new OTCredential;
1196  OT_ASSERT(nullptr != pCredential);
1197 
1198  pCredential->SetSourceForNymID(
1199  strSourceForNymID); // This also recalculates and sets ** m_strNymID **
1200 
1201  // OTKeyCredential::SetPrivateContents will already set the public keys,
1202  // which is why this argument is optional. But not all credentials are keys,
1203  // so we must still retain the ability to explicitly set the public info.
1204  // Even so, in the case of keys, private is below, so it will overwrite
1205  // this.
1206 
1207  if ((nullptr != pmapPublic) &&
1208  (nullptr != pmapPrivate)) // You cannot pass public
1209  // info in here unless
1210  // you also pass private
1211  // info.
1212  {
1213  if (!pCredential->SetPublicContents(*pmapPublic)) {
1214  otErr << "In " << __FILE__ << ", line " << __LINE__
1215  << ": Failed trying to call pCredential->SetPublicContents\n";
1216  delete pCredential;
1217  pCredential = nullptr;
1218  return nullptr;
1219  }
1220  }
1221 
1222  // Private info must be passed in to create a credential. This saves a copy
1223  // of the map, and for keys also loads the map all up into the OTKeypair
1224  // objects (in the case of OTKeyCredentials anyway -- not all credentials
1225  // are keys.)
1226  //
1227  bool bContentsReady = false;
1228 
1229  if (nullptr !=
1230  pmapPrivate) // Pre-generated keys were passed in for us to use.
1231  bContentsReady = pCredential->SetPrivateContents(
1232  *pmapPrivate); // So let's set them onto the master key.
1233  else
1234  // No keys were provided, so let's generate them ourselves...
1235  bContentsReady = pCredential->GenerateMasterkey(nBits);
1236 
1237  if (!bContentsReady) {
1238  otErr << "In " << __FILE__ << ", line " << __LINE__
1239  << ": Failed trying to SetPrivateContents or GenerateMasterkey\n";
1240  delete pCredential;
1241  pCredential = nullptr;
1242  return nullptr;
1243  }
1244  else {
1245  OTPasswordData thePWData(
1246  "Signing new master credential... OTCredential::CreateMaster");
1247 
1248  // Using m_Masterkey's actual signing key to sign "m_Masterkey the
1249  // contract."
1250  //
1251  if (false ==
1252  pCredential->SignNewMaster(nullptr == pPWData ? &thePWData
1253  : pPWData)) {
1254  otErr << "In " << __FILE__ << ", line " << __LINE__
1255  << ": Failed trying to call pCredential->SignNewMaster\n";
1256  delete pCredential;
1257  pCredential = nullptr;
1258  return nullptr;
1259  }
1260  }
1261 
1262  // By this point, we have instantiated a new OTCredential, set the source
1263  // string, hashed that
1264  // source string to get the NymID for this credential, and set the public
1265  // and private info for
1266  // this credential (each a map of strings.) Since pCredential->m_Masterkey
1267  // is derived from
1268  // OTKeyCredential, it also loaded up the 3 keypairs (authentication,
1269  // encryption, and signing.)
1270  // Then we signed that master key with itself, with its signing key. (It's
1271  // also an OTContract,
1272  // so it can be signed.) This also calculated the new master credential ID,
1273  // and called
1274  // pCredential->SetMasterCredID. That is, the OTCredential's "master
1275  // credential ID" is formed
1276  // as a hash of the signed contract that is its OTMasterkey.
1277  // BUT!!! We don't want to use a hash of the private key information, since
1278  // others cannot verify
1279  // the hash without seeing our private key. We want OTMasterkey to create an
1280  // 'official' signed
1281  // public version of itself, minus private keys, which is what can be sent
1282  // to servers and to
1283  // other users, and which can be hashed to form the master credential ID
1284  // (and verified later.)
1285  // ...Which is exactly what it does. Inside pCredential->SignNewMaster, a
1286  // public version is created
1287  // and signed, and set onto that masterkey as m_strContents. It's then
1288  // re-signed as the private
1289  // version, which contains m_strContents in encoded form, along with the
1290  // private keys.
1291  //
1292  return pCredential;
1293 }
1294 
1296 {
1297  return m_mapSubcredentials.size();
1298 }
1299 
1301  const OTString& strSubID, const OTString::List* plistRevokedIDs) const
1302 {
1303  for (const auto& it : m_mapSubcredentials) {
1304  const std::string str_cred_id = it.first;
1305  const OTSubcredential* pSub = it.second;
1306  OT_ASSERT(nullptr != pSub);
1307 
1308  // See if pSub, with ID str_cred_id, is on plistRevokedIDs...
1309  //
1310  if (nullptr != plistRevokedIDs) {
1311  auto iter = std::find(plistRevokedIDs->begin(),
1312  plistRevokedIDs->end(), str_cred_id);
1313  if (iter != plistRevokedIDs->end()) // It was on the revoked list.
1314  continue; // Skip this revoked credential.
1315  }
1316  // At this point we know it's not on the revoked list, if one was passed
1317  // in.
1318 
1319  if (strSubID.Compare(str_cred_id.c_str())) return pSub;
1320  }
1321  return nullptr;
1322 }
1323 
1325  int32_t nIndex) const
1326 {
1327  if ((nIndex < 0) ||
1328  (nIndex >= static_cast<int64_t>(m_mapSubcredentials.size()))) {
1329  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
1330  }
1331  else {
1332  int32_t nLoopIndex = -1;
1333 
1334  for (const auto& it : m_mapSubcredentials) {
1335  const OTSubcredential* pSub = it.second;
1336  OT_ASSERT(nullptr != pSub);
1337 
1338  ++nLoopIndex; // 0 on first iteration.
1339 
1340  if (nIndex == nLoopIndex) return pSub;
1341  }
1342  }
1343 
1344  return nullptr;
1345 }
1346 
1347 const std::string OTCredential::GetSubcredentialIDByIndex(size_t nIndex) const
1348 {
1349  if (nIndex >= m_mapSubcredentials.size()) {
1350  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
1351  }
1352  else {
1353  int32_t nLoopIndex = -1;
1354 
1355  for (const auto& it : m_mapSubcredentials) {
1356  const std::string str_cred_id = it.first;
1357  const OTSubcredential* pSub = it.second;
1358  OT_ASSERT(nullptr != pSub);
1359 
1360  ++nLoopIndex; // 0 on first iteration.
1361 
1362  if (static_cast<int64_t>(nIndex) == nLoopIndex) return str_cred_id;
1363  }
1364  }
1365 
1366  return nullptr;
1367 }
1368 
1370  const OTString::List* plistRevokedIDs) const
1371 {
1372  for (const auto& it : m_mapSubcredentials) {
1373  const std::string str_cred_id = it.first;
1374  const OTSubcredential* pSub = it.second;
1375  OT_ASSERT(nullptr != pSub);
1376 
1377  const OTSubkey* pKey = dynamic_cast<const OTSubkey*>(pSub);
1378  if (nullptr == pKey) continue;
1379 
1380  // See if pKey, with ID str_cred_id, is on plistRevokedIDs...
1381  //
1382  if (nullptr != plistRevokedIDs) {
1383  auto iter = std::find(plistRevokedIDs->begin(),
1384  plistRevokedIDs->end(), str_cred_id);
1385  if (iter != plistRevokedIDs->end()) // It was on the revoked list.
1386  continue; // Skip this revoked key.
1387  }
1388  // At this point we know it's a key credential, and we know it's not on
1389  // the revoked list. Therefore, let's return the key! (Any other future
1390  // smart criteria might go here before taking this final step...)
1391  //
1392  return pKey->m_AuthentKey;
1393  }
1394 
1395  // Didn't find any subcredentials we can use? For now, we'll return the
1396  // master key instead.
1397  // This is purely for backwards compatibility reasons and eventually should
1398  // be removed. That is,
1399  // masters should only be able to verify subkeys, and only subkeys should be
1400  // able to do actions.
1401  // Capiche?
1402  //
1403  return m_Masterkey.m_AuthentKey;
1404 }
1405 
1407  const OTString::List* plistRevokedIDs) const
1408 {
1409  for (const auto& it : m_mapSubcredentials) {
1410  const std::string str_cred_id = it.first;
1411  const OTSubcredential* pSub = it.second;
1412  OT_ASSERT(nullptr != pSub);
1413 
1414  const OTSubkey* pKey = dynamic_cast<const OTSubkey*>(pSub);
1415  if (nullptr == pKey) continue;
1416 
1417  // See if pKey, with ID str_cred_id, is on plistRevokedIDs...
1418  //
1419  if (nullptr != plistRevokedIDs) {
1420  auto iter = std::find(plistRevokedIDs->begin(),
1421  plistRevokedIDs->end(), str_cred_id);
1422  if (iter != plistRevokedIDs->end()) // It was on the revoked list.
1423  continue; // Skip this revoked key.
1424  }
1425  // At this point we know it's a key credential, and we know it's not on
1426  // the revoked list. Therefore, let's return the key! (Any other future
1427  // smart criteria might go here before taking this final step...)
1428  //
1429  return pKey->m_EncryptKey;
1430  }
1431 
1432  // Didn't find any subcredentials we can use? For now, we'll return the
1433  // master key instead.
1434  // This is purely for backwards compatibility reasons and eventually should
1435  // be removed. That is,
1436  // masters should only be able to verify subkeys, and only subkeys should be
1437  // able to do actions.
1438  // Capiche?
1439  //
1440  return m_Masterkey.m_EncryptKey;
1441 }
1442 
1444  const OTString::List* plistRevokedIDs) const
1445 {
1446  for (const auto& it : m_mapSubcredentials) {
1447  const std::string str_cred_id = it.first;
1448  const OTSubcredential* pSub = it.second;
1449  OT_ASSERT(nullptr != pSub);
1450 
1451  const OTSubkey* pKey = dynamic_cast<const OTSubkey*>(pSub);
1452  if (nullptr == pKey) continue;
1453 
1454  // See if pKey, with ID str_cred_id, is on plistRevokedIDs...
1455  //
1456  if (nullptr != plistRevokedIDs) {
1457  auto iter = std::find(plistRevokedIDs->begin(),
1458  plistRevokedIDs->end(), str_cred_id);
1459  if (iter != plistRevokedIDs->end()) // It was on the revoked list.
1460  continue; // Skip this revoked key.
1461  }
1462  // At this point we know it's a key credential, and we know it's not on
1463  // the revoked list. Therefore, let's return the key! (Any other future
1464  // smart criteria might go here before taking this final step...)
1465  //
1466  return pKey->m_SigningKey;
1467  }
1468 
1469  // Didn't find any subcredentials we can use? For now, we'll return the
1470  // master key instead.
1471  // This is purely for backwards compatibility reasons and eventually should
1472  // be removed. That is,
1473  // masters should only be able to verify subkeys, and only subkeys should be
1474  // able to do actions.
1475  // Capiche?
1476  //
1477  return m_Masterkey.m_SigningKey;
1478 }
1479 
1480 // NOTE: Until we figure out the rule by which we decide WHICH authentication
1481 // key is the right auth key,
1482 // or WHICH signing key is the right signing key, we'll just go with the first
1483 // one we find.
1484 // We'll also weed out any that appear on plistRevokedIDs, if it's passed in.
1485 // (Optional.)
1486 
1488  const OTString::List* plistRevokedIDs) const
1489 {
1490  return GetAuthKeypair(plistRevokedIDs).GetPublicKey();
1491 }
1492 
1494  const OTString::List* plistRevokedIDs) const
1495 {
1496  return GetEncrKeypair(plistRevokedIDs).GetPublicKey();
1497 }
1498 
1500  const OTString::List* plistRevokedIDs) const
1501 {
1502  return GetSignKeypair(plistRevokedIDs).GetPublicKey();
1503 }
1504 
1506  const OTString::List* plistRevokedIDs) const
1507 {
1508  return GetAuthKeypair(plistRevokedIDs).GetPrivateKey();
1509 }
1510 
1512  const OTString::List* plistRevokedIDs) const
1513 {
1514  return GetEncrKeypair(plistRevokedIDs).GetPrivateKey();
1515 }
1516 
1518  const OTString::List* plistRevokedIDs) const
1519 {
1520  return GetSignKeypair(plistRevokedIDs).GetPrivateKey();
1521 }
1522 
1524 {
1526 }
1527 
1529 {
1530 
1531  while (!m_mapSubcredentials.empty()) {
1532  OTSubcredential* pSub = m_mapSubcredentials.begin()->second;
1533  OT_ASSERT(nullptr != pSub);
1534 
1535  delete pSub;
1536  pSub = nullptr;
1537 
1538  m_mapSubcredentials.erase(m_mapSubcredentials.begin());
1539  } // while
1540 }
1541 
1542 // listRevokedIDs should contain a list of std::strings for IDs of
1543 // already-revoked subcredentials.
1544 // That way, SerializeIDs will know whether to mark them as valid while
1545 // serializing them.
1546 // bShowRevoked allows us to include/exclude the revoked credentials from the
1547 // output (filter for valid-only.)
1548 // bValid=true means we are saving OTPseudonym::m_mapCredentials. Whereas
1549 // bValid=false means we're saving m_mapRevoked.
1550 // pmapPubInfo is optional output, the public info for all the credentials will
1551 // be placed inside, if a pointer is provided.
1552 //
1554  const OTString::List& listRevokedIDs,
1555  OTString::Map* pmapPubInfo,
1556  OTString::Map* pmapPriInfo, bool bShowRevoked,
1557  bool bValid) const
1558 {
1559  if (bValid || bShowRevoked) {
1560  strOutput.Concatenate("<masterCredential\n"
1561  " ID=\"%s\"\n"
1562  " valid=\"%s\""
1563  "/>\n\n",
1564  GetMasterCredID().Get(),
1565  bValid ? "true" : "false");
1566 
1567  if (nullptr != pmapPubInfo) // optional out-param.
1568  pmapPubInfo->insert(std::pair<std::string, std::string>(
1569  GetMasterCredID().Get(), GetPubCredential().Get()));
1570 
1571  if (nullptr != pmapPriInfo) // optional out-param.
1572  pmapPriInfo->insert(std::pair<std::string, std::string>(
1573  GetMasterCredID().Get(), GetPriCredential().Get()));
1574  }
1575 
1576  for (const auto& it : m_mapSubcredentials) {
1577  const std::string str_cred_id = it.first;
1578  const OTSubcredential* pSub = it.second;
1579  OT_ASSERT(nullptr != pSub);
1580 
1581  // See if the current subcredential is on the Nym's list of "revoked"
1582  // subcredential IDs.
1583  // If so, we'll skip serializing it here.
1584  //
1585  auto iter = std::find(listRevokedIDs.begin(), listRevokedIDs.end(),
1586  str_cred_id);
1587 
1588  // Was it on the 'revoked' list?
1589  // If not, then the subcredential isn't revoked, so it's still valid.
1590  //
1591  const bool bSubcredValid =
1592  bValid ? (iter == listRevokedIDs.end()) : false;
1593 
1594  if (bSubcredValid || bShowRevoked) {
1595  const OTSubkey* pSubkey = dynamic_cast<const OTSubkey*>(pSub);
1596 
1597  if (nullptr != pSubkey)
1598  strOutput.Concatenate("<keyCredential\n"
1599  " ID=\"%s\"\n"
1600  " masterID=\"%s\"\n"
1601  " valid=\"%s\""
1602  "/>\n\n",
1603  str_cred_id.c_str(),
1604  pSubkey->GetMasterCredID().Get(),
1605  bSubcredValid ? "true" : "false");
1606  else
1607  strOutput.Concatenate("<subCredential\n"
1608  " ID=\"%s\"\n"
1609  " masterID=\"%s\"\n"
1610  " valid=\"%s\""
1611  "/>\n\n",
1612  str_cred_id.c_str(),
1613  pSub->GetMasterCredID().Get(),
1614  bSubcredValid ? "true" : "false");
1615 
1616  if (nullptr != pmapPubInfo) // optional out-param.
1617  pmapPubInfo->insert(std::pair<std::string, std::string>(
1618  str_cred_id.c_str(), pSub->GetPubCredential().Get()));
1619 
1620  if (nullptr != pmapPriInfo) // optional out-param.
1621  pmapPriInfo->insert(std::pair<std::string, std::string>(
1622  str_cred_id.c_str(), pSub->GetPriCredential().Get()));
1623 
1624  } // if (bSubcredValid)
1625  }
1626 }
1627 
1628 } // namespace opentxs
std::map< std::string, std::string > Map
Definition: OTString.hpp:162
EXPORT const OTAsymmetricKey & GetPublicSignKey(const OTString::List *plistRevokedIDs=nullptr) const
std::list< OTAsymmetricKey * > listOfAsymmetricKeys
EXPORT const OTAsymmetricKey & GetPublicKey() const
Definition: OTKeypair.cpp:229
EXPORT const OTSubcredential * GetSubcredential(const OTString &strSubID, const OTString::List *plistRevokedIDs=nullptr) const
EXPORT int32_t GetPublicKeysBySignature(listOfAsymmetricKeys &listOutput, const OTSignature &theSignature, char cKeyType= '0') const
EXPORT const OTString & GetNymID() const
EXPORT bool CalculateDigest(const OTData &dataInput)
EXPORT bool LoadSubcredentialFromString(const OTString &strInput, const OTString &strSubID, const OTPassword *pImportPassword=nullptr)
static EXPORT const OTString & Pubcred()
Definition: OTFolders.cpp:343
const OTString & GetMasterCredID() const
void SetMasterCredID(const OTString &strMasterCredID)
EXPORT bool LoadSubcredential(const OTString &strSubID)
const OTString::Map & GetPrivateMap() const
EXPORT bool SaveContract()
EXPORT const OTAsymmetricKey & GetPrivateAuthKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT bool AddNewSubkey(int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTPasswordData *pPWData=nullptr, OTSubkey **ppSubkey=nullptr)
bool Sign(OTContract &theContract, const OTPasswordData *pPWData=nullptr)
bool VerifyAgainstSource() const
EXPORT bool Load_MasterFromString(const OTString &strInput, const OTString &strNymID, const OTString &strMasterCredID, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT const OTKeypair & GetEncrKeypair(const OTString::List *plistRevokedIDs=nullptr) const
OTLOG_IMPORT OTLogStream otOut
EXPORT void ClearSubcredentials()
EXPORT bool SaveContractRaw(OTString &strOutput) const
EXPORT const OTKeypair & GetSignKeypair(const OTString::List *plistRevokedIDs=nullptr) const
virtual bool SetPrivateContents(const OTString::Map &mapPrivate, const OTPassword *pImportPassword=nullptr)
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
static OTCredential * CreateMaster(const OTString &strSourceForNymID, int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTString::Map *pmapPublic=nullptr, const OTPasswordData *pPWData=nullptr)
EXPORT bool ReEncryptPrivateCredentials(const OTPassword &theExportPassword, bool bImporting)
static OTCredential * LoadMaster(const OTString &strNymID, const OTString &strMasterCredID, const OTPasswordData *pPWData=nullptr)
EXPORT bool DecodeIfArmored(bool escapedIsAllowed=true)
Definition: OTString.cpp:1212
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
const OTString & GetPriCredential() const
EXPORT bool AddNewSubcredential(const OTString::Map &mapPrivate, const OTString::Map &mapPublic, const OTPasswordData *pPWData=nullptr, OTSubcredential **ppSubcred=nullptr)
void SetMasterSigned(const OTString &strMasterSigned)
static EXPORT const OTString & Credential()
Definition: OTFolders.cpp:307
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT const OTString & GetPriCredential() const
EXPORT const OTString & GetMasterCredID() const
void SetIdentifier(const OTIdentifier &theID)
Definition: OTContract.hpp:268
EXPORT bool LoadSubkeyFromString(const OTString &strInput, const OTString &strSubID, const OTPassword *pImportPassword=nullptr)
void SetNymIDandSource(const OTString &strNymID, const OTString &strSourceForNymID)
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static OTCredential * LoadMasterFromString(const OTString &strInput, const OTString &strNymID, const OTString &strMasterCredID, OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
virtual bool SetPrivateContents(const OTString::Map &mapPrivate, const OTPassword *pImportPassword=nullptr)
EXPORT const OTKeypair & GetAuthKeypair(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT const OTString & GetPubCredential() const
EXPORT const OTAsymmetricKey & GetPrivateKey() const
Definition: OTKeypair.cpp:236
const OTString & GetNymID() const
EXPORT const OTAsymmetricKey & GetPublicAuthKey(const OTString::List *plistRevokedIDs=nullptr) const
std::list< std::string > List
Definition: OTString.hpp:161
void SetContents(const OTString &strContents)
virtual bool SetPublicContents(const OTString::Map &mapPublic)
EXPORT size_t GetSubcredentialCount() const
OTLOG_IMPORT OTLogStream otWarn
EXPORT void SetImportPassword(const OTPassword *pImportPassword)
const OTString & GetNymIDSource() const
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT bool Load_Master(const OTString &strNymID, const OTString &strMasterCredID, const OTPasswordData *pPWData=nullptr)
EXPORT const OTAsymmetricKey & GetPublicEncrKey(const OTString::List *plistRevokedIDs=nullptr) const
bool ReEncryptKeys(const OTPassword &theExportPassword, bool bImporting)
OTLOG_IMPORT OTLogStream otErr
EXPORT const OTString & GetSourceForNymID() const
EXPORT const OTString & GetPubCredential() const
virtual bool SetPublicContents(const OTString::Map &mapPublic)
EXPORT void GetString(OTString &theStr) const
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
EXPORT bool LoadSubkey(const OTString &strSubID)
EXPORT const OTSubcredential * GetSubcredentialByIndex(int32_t nIndex) const
EXPORT bool LoadContractFromString(const OTString &theStr)
EXPORT const OTAsymmetricKey & GetPrivateEncrKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT const OTAsymmetricKey & GetPrivateSignKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT void SerializeIDs(OTString &strOutput, const OTString::List &listRevokedIDs, OTString::Map *pmapPubInfo=nullptr, OTString::Map *pmapPriInfo=nullptr, bool bShowRevoked=false, bool bValid=true) const
EXPORT bool VerifyAgainstSource() const
EXPORT bool VerifyInternally() const
bool GenerateKeys(int32_t nBits=1024)
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT const std::string GetSubcredentialIDByIndex(size_t nIndex) const
EXPORT int32_t GetPublicKeysBySignature(listOfAsymmetricKeys &listOutput, const OTSignature &theSignature, char cKeyType= '0') const