1 /*** 2 * © 2020 Duality Technologies, Inc. All rights reserved. 3 * This is a proprietary software product of Duality Technologies, Inc. 4 *protected under copyright laws and international copyright treaties, patent 5 *law, trade secret law and other intellectual property rights of general 6 *applicability. Any use of this software is strictly prohibited absent a 7 *written agreement executed by Duality Technologies, Inc., which provides 8 *certain limited rights to use this software. You may not copy, distribute, 9 *make publicly available, publicly perform, disassemble, de-compile or reverse 10 *engineer any part of this software, breach its security, or circumvent, 11 *manipulate, impair or disrupt its operation. 12 ***/ 13 14 #ifndef LBCRYPTO_CRYPTO_METADATA_H 15 #define LBCRYPTO_CRYPTO_METADATA_H 16 17 namespace lbcrypto { 18 19 /** 20 * @brief Empty metadata container 21 */ 22 class Metadata { 23 public: 24 /** 25 * Default constructor 26 */ Metadata()27 Metadata() {} 28 29 /** 30 * Copy constructor 31 */ Metadata(const Metadata & mdata)32 Metadata(const Metadata& mdata) { Metadata(); } 33 34 /** 35 * Destructor 36 */ ~Metadata()37 virtual ~Metadata() {} 38 39 /** 40 * This method creates a copy of the Metadata object 41 * wrapped in a shared_ptr 42 */ Clone()43 virtual std::shared_ptr<Metadata> Clone() const { 44 return std::make_shared<Metadata>(); 45 } 46 47 /** 48 * Equality operator for Metadata. 49 * Unless overriden by subclasses, Metadata does not carry any 50 * metadata, so all Metadata objects are equal. 51 */ 52 virtual bool operator==(const Metadata& mdata) const { return true; } 53 54 /** 55 * Inequality operator, implemented by a call to the 56 * equality operator. 57 */ 58 virtual bool operator!=(const Metadata& mdata) const { 59 return !(*this == mdata); 60 } 61 62 /** 63 * A method that prints the contents of metadata objects. 64 * Please override in subclasses to print all members. 65 */ print(std::ostream & out)66 virtual std::ostream& print(std::ostream& out) const { 67 out << "[ ]" << std::endl; 68 return out; 69 } 70 71 /** 72 * << operator implements by calling member method print. 73 * This is a friend method and cannot be overriden by subclasses. 74 */ 75 friend std::ostream& operator<<(std::ostream& out, const Metadata& m) { 76 m.print(out); 77 return out; 78 } 79 80 /** 81 * save method for serialization 82 */ 83 template <class Archive> save(Archive & ar,std::uint32_t const version)84 void save(Archive& ar, std::uint32_t const version) const {} 85 86 /** 87 * load method for serialization 88 */ 89 template <class Archive> load(Archive & ar,std::uint32_t const version)90 void load(Archive& ar, std::uint32_t const version) { 91 if (version > SerializedVersion()) { 92 PALISADE_THROW(deserialize_error, 93 "serialized object version " + std::to_string(version) + 94 " is from a later version of the library"); 95 } 96 } 97 98 /** 99 * SerializedObjectName method for serialization 100 */ SerializedObjectName()101 virtual std::string SerializedObjectName() const { return "Metadata"; } 102 103 /** 104 * SerializedVersion method for serialization 105 */ SerializedVersion()106 static uint32_t SerializedVersion() { return 1; } 107 }; 108 109 /** 110 * @brief Example class inheriting from Metadata and adding a member. 111 * This is used in unit tests. 112 */ 113 class MetadataTest : public Metadata { 114 public: 115 /** 116 * Default constructor 117 */ MetadataTest()118 MetadataTest() : Metadata(), m_s("") {} 119 /** 120 * Destructor 121 */ ~MetadataTest()122 virtual ~MetadataTest() {} 123 124 /** 125 * Copy constructor 126 */ MetadataTest(const MetadataTest & mdata)127 MetadataTest(const MetadataTest& mdata) : Metadata() { m_s = mdata.m_s; } 128 129 /** 130 * This method creates a new MetadataTest object. 131 * 132 * Since Ciphertexts have a map of shared_ptr<Metadata>, 133 * whenever we retrieve the contents of the map, we actually 134 * get the shared pointer and we do not create a new object. 135 * 136 * If we do want to create a new object (e.g., because we 137 * want to modify it only for a new Ciphertext), we can use 138 * the Clone method. 139 * 140 */ Clone()141 std::shared_ptr<Metadata> Clone() const { 142 auto mdata = std::make_shared<MetadataTest>(); 143 mdata->m_s = this->m_s; 144 return mdata; 145 } 146 147 /** 148 * Setter method for the only value stored in this Metadata container. 149 */ SetMetadata(string str)150 void SetMetadata(string str) { m_s = string(str); } 151 152 /** 153 * This method returns the (only) value stored in this Metadata container 154 */ GetMetadata()155 string GetMetadata() const { return m_s; } 156 157 /** 158 * Defines how to check equality between objects of this class. 159 */ 160 bool operator==(const Metadata& mdata) const { 161 try { 162 const MetadataTest& mdataTest = dynamic_cast<const MetadataTest&>(mdata); 163 return m_s == mdataTest.GetMetadata(); // All Metadata objects without 164 // any members are equal catch(const std::bad_cast & e)165 } catch (const std::bad_cast& e) { 166 PALISADE_THROW( 167 palisade_error, 168 "Tried to downcast an object of different class to MetadataTest"); 169 } 170 } 171 172 /** 173 * Defines how to print the contents of objects of this class. 174 */ print(std::ostream & out)175 std::ostream& print(std::ostream& out) const { 176 out << "[ " << m_s << " ]"; 177 return out; 178 } 179 180 /** 181 * save method for serialization 182 */ 183 template <class Archive> save(Archive & ar,std::uint32_t const version)184 void save(Archive& ar, std::uint32_t const version) const { 185 ar(cereal::base_class<Metadata>(this)); 186 ar(cereal::make_nvp("str", m_s)); 187 } 188 189 /** 190 * load method for serialization 191 */ 192 template <class Archive> load(Archive & ar,std::uint32_t const version)193 void load(Archive& ar, std::uint32_t const version) { 194 if (version > SerializedVersion()) { 195 PALISADE_THROW(deserialize_error, 196 "serialized object version " + std::to_string(version) + 197 " is from a later version of the library"); 198 } 199 ar(cereal::base_class<Metadata>(this)); 200 ar(cereal::make_nvp("str", m_s)); 201 } 202 203 /** 204 * This static method retrieves a MetadataTest object 205 * from a Ciphertext, and clones it so we can further 206 * modify it. 207 * 208 * @param ciphertext the ciphertext whose metadata to retrieve. 209 */ 210 template <class Element> CloneMetadata(ConstCiphertext<Element> ciphertext)211 static const shared_ptr<MetadataTest> CloneMetadata( 212 ConstCiphertext<Element> ciphertext) { 213 auto it = ciphertext->FindMetadataByKey("test"); 214 215 if (ciphertext->MetadataFound(it)) { 216 return std::dynamic_pointer_cast<MetadataTest>( 217 ciphertext->GetMetadata(it)->Clone()); 218 } else { 219 PALISADE_THROW( 220 palisade_error, 221 "Attempt to access metadata (MetadataTest) that has not been set."); 222 } 223 } 224 225 /** 226 * This static method retrieves a MetadataTest object 227 * from a Ciphertext, without cloning it. This means that any 228 * modifications on the MetadataTest object will affect the 229 * original Ciphertext we retrieved the metadata from. 230 * 231 * @param ciphertext the ciphertext whose metadata to retrieve. 232 */ 233 template <class Element> GetMetadata(ConstCiphertext<Element> ciphertext)234 static const shared_ptr<MetadataTest> GetMetadata( 235 ConstCiphertext<Element> ciphertext) { 236 auto it = ciphertext->FindMetadataByKey("test"); 237 238 if (ciphertext->MetadataFound(it)) { 239 return std::dynamic_pointer_cast<MetadataTest>( 240 ciphertext->GetMetadata(it)); 241 } else { 242 PALISADE_THROW( 243 palisade_error, 244 "Attempt to access metadata (MetadataTest) that has not been set."); 245 } 246 } 247 248 /** 249 * This static method stores a MetadataTest object 250 * to a Ciphertext. If the Ciphertext already has another MetadataTest 251 * object stored in its map, it will get overwritten by this MetadataTest 252 * object. 253 * 254 * Whenever we want to modify the metadata of a ciphertext, it is 255 * recommended to (1) clone the MetadataTest object from another 256 * ciphertext or create a new MetadataTest object with 257 * make_shared<MetadataTest>(), (2) modify it using the Setter methods 258 * of MetadataTest, and (3) store it to the ciphertext we want using 259 * this method. 260 * 261 * @param ciphertext the ciphertext whose metadata to retrieve. 262 */ 263 template <class Element> StoreMetadata(Ciphertext<Element> ciphertext,shared_ptr<MetadataTest> mdata)264 static void StoreMetadata(Ciphertext<Element> ciphertext, 265 shared_ptr<MetadataTest> mdata) { 266 ciphertext->SetMetadataByKey("test", mdata); 267 } 268 269 protected: 270 string m_s; 271 }; 272 273 } // end namespace lbcrypto 274 275 #endif 276