Palisade utils

Palisade utils

\core\include\utils\inttypes.h

stdint.h 中定义了 uint8_t , uint16_t , uint32_t , uint64_t 等类型,其实它们只是 char , short 等类型的别名。

关于<stdint.h>

/**
 * @brief Type used for representing unsigned 8-bit integers.
 */
typedef uint8_t uschar;

/**
 * @brief Type used for representing unsigned 16-bit short integers.
 */
typedef uint16_t usshort;

/**
 * @brief Type used for representing unsigned 32-bit integers.
 */
typedef uint32_t usint;

typedef uint64_t PlaintextModulus;

PlaintextModulus 是在这里被定义的!

定义了一个枚举,代表多项式是计算表示还是系数表示,计算表示是经过 FFT/NTT(Canondial embedding) 后的结果。

/**
 * @brief Represents whether the polynomial ring is in EVALUATION or COEFFICIENT
 * representation.
 */
enum Format { EVALUATION = 0, COEFFICIENT = 1 };

inline std::ostream &operator<<(std::ostream &s, Format f) {
  switch (f) {
    case EVALUATION:
      s << "EVALUATION";
      break;
    case COEFFICIENT:
      s << "COEFFICIENT";
      break;
    default:
      s << "UKNOWN";
      break;
  }
  return s;
}

接下来定义了 enable() 函数可以接受的参数

/**
 * @brief Lists all features supported by public key encryption schemes
 */
enum PKESchemeFeature {
  ENCRYPTION = 0x01,
  PRE = 0x02,
  SHE = 0x04,
  FHE = 0x08,
  LEVELEDSHE = 0x10,
  MULTIPARTY = 0x20,
  ADVANCEDSHE = 0x40
};


inline std::ostream &operator<<(std::ostream &s, PKESchemeFeature f) {
  switch (f) {
    case ENCRYPTION:
      s << "ENCRYPTION";
      break;
    case PRE:
      s << "PRE";
      break;
    case SHE:
      s << "SHE";
      break;
    case FHE:
      s << "FHE";
      break;
    case LEVELEDSHE:
      s << "LEVELEDSHE";
      break;
    case MULTIPARTY:
      s << "MULTIPARTY";
      break;
    case ADVANCEDSHE:
      s << "ADVANCEDSHE";
      break;
    default:
      s << "UKNOWN";
      break;
  }
  return s;
}

接下来定义的 optimization mode,是方案初始化时需要传输的参数。

/**
 * @brief Lists all modes for RLWE schemes, such as BGV and BFV
 */
enum MODE { RLWE = 0, OPTIMIZED = 1, SPARSE = 2 };

inline std::ostream &operator<<(std::ostream &s, MODE m) {
  switch (m) {
    case RLWE:
      s << "RLWE";
      break;
    case OPTIMIZED:
      s << "OPTIMIZED";
      break;
    case SPARSE:
      s << "SPARSE";
      break;
    default:
      s << "UKNOWN";
      break;
  }
  return s;
}

\core\include\utils\palisadebase64.h

以64为基,6个比特一组。

#ifndef SRC_CORE_LIB_UTILS_PALISADEBASE64_H_
#define SRC_CORE_LIB_UTILS_PALISADEBASE64_H_

#include <utils/exception.h>
#include <cctype>
#include <cstdint>

namespace lbcrypto {

extern const char to_base64_char[];

inline unsigned char value_to_base64(int c) { return to_base64_char[c]; }

 A 到 Z为 0-25,a 到 z 为 26-51,0952-61+加号为 62,剩余所有都是 63.
inline unsigned char base64_to_value(unsigned char b64) {
  if (isupper(b64))
    return b64 - 'A';
  else if (islower(b64))
    return b64 - 'a' + 26;
  else if (isdigit(b64))
    return b64 - '0' + 52;
  else if (b64 == '+')
    return 62;
  else
    return 63;
}

高位index大,低位index小,smallmask从0开始,依次为0位,1位,2位,3位,4位,5位,6位;
从index开始向低位截取6个比特。
inline unsigned char get_6bits_atoffset(uint64_t m_value, uint32_t index) {
  static unsigned char smallmask[] = {0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f};

  if (index == 0) {
    PALISADE_THROW(math_error, "Zero index in GetBitAtIndex");
  }
  if (index <= 6) {
    return m_value & smallmask[index];
  }

  return (m_value >> (index - 6)) & 0x3f;
}

} /* namespace lbcrypto */

#endif /* SRC_CORE_LIB_UTILS_PALISADEBASE64_H_ */

\core\lib\utils\palisadebase64.cpp

#include "utils/palisadebase64.h"

namespace lbcrypto {

const char to_base64_char[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

} /* namespace lbcrypto */

\core\include\utils\exception.h

处理所有可能出现的异常

#ifndef SRC_CORE_LIB_UTILS_EXCEPTION_H_
#define SRC_CORE_LIB_UTILS_EXCEPTION_H_

#include <exception>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <string>

namespace lbcrypto {

// Exceptions thrown inside of a critical region, or inside of an omp thread,
// must be caught in the same thread where thrown, or Bad Things Happen
//
// This class is used to catch and rethrow exceptions from threads/critical
// regions (thank you stack overflow)
class ThreadException {
  std::exception_ptr Ptr;
  std::mutex Lock;

 public:
  ThreadException() : Ptr(nullptr) {}
  ~ThreadException() {}
  void Rethrow() {
    if (this->Ptr) std::rethrow_exception(this->Ptr);
  }
  void CaptureException() {
    std::unique_lock<std::mutex> guard(this->Lock);
    this->Ptr = std::current_exception();
  }

  template <typename Function, typename... Parameters>
  void Run(Function f, Parameters... params) {
    try {
      f(params...);
    } catch (...) {
      CaptureException();
    }
  }
};

// how  to use ThreadException
// To use this, declare an instance of the object before the critical
// region/thread, catch exceptions in thread with CaptureException, then after
// the region call object.Rethrow()
// #pragma omp parallel for
// for (unsigned i = 0; i < rv.size(); i++) try {
//     rv.polys[i] = (polys[i].*f)();
//   } catch (...) {
//     e.CaptureException();
//   }
// e.Rethrow();
//
// // use of Run looks like:
// ThreadException e;
// #pragma omp parallel for
// for (int i = 0; i < n; i++) {
//   e.Run([=] {
//     // code that might throw
//     // ...
//   });
// }
// e.Rethrow();
class palisade_error : public std::runtime_error {
  std::string filename;
  int linenum;
  std::string message;

 public:
  palisade_error(const std::string& file, int line, const std::string& what)
      : std::runtime_error(what), filename(file), linenum(line) {
    message = filename + ":" + std::to_string(linenum) + " " + what;
  }

  const char* what() const throw() { return message.c_str(); }

  const std::string& GetFilename() const { return filename; }
  int GetLinenum() const { return linenum; }
};

class config_error : public palisade_error {
 public:
  config_error(const std::string& file, int line, const std::string& what)
      : palisade_error(file, line, what) {}
};

class math_error : public palisade_error {
 public:
  math_error(const std::string& file, int line, const std::string& what)
      : palisade_error(file, line, what) {}
};

class not_implemented_error : public palisade_error {
 public:
  not_implemented_error(const std::string& file, int line,
                        const std::string& what)
      : palisade_error(file, line, what) {}
};

class not_available_error : public palisade_error {
 public:
  not_available_error(const std::string& file, int line,
                      const std::string& what)
      : palisade_error(file, line, what) {}
};

class type_error : public palisade_error {
 public:
  type_error(const std::string& file, int line, const std::string& what)
      : palisade_error(file, line, what) {}
};

// use this error when serializing palisade objects
class serialize_error : public palisade_error {
 public:
  serialize_error(const std::string& file, int line, const std::string& what)
      : palisade_error(file, line, what) {}
};

// use this error when deserializing palisade objects
class deserialize_error : public palisade_error {
 public:
  deserialize_error(const std::string& file, int line, const std::string& what)
      : palisade_error(file, line, what) {}
};

#define PALISADE_THROW(exc, expr) throw exc(__FILE__, __LINE__, (expr))

}  // namespace lbcrypto

#endif /* SRC_CORE_LIB_UTILS_EXCEPTION_H_ */

\core\include\utils\parallel.h

里面的函数都是根据 PARALLEL 是否被定义来判断的。

#ifdef PARALLEL
#include <omp.h>
#endif
namespace lbcrypto {

class ParallelControls {
  int machineThreads;

 public:
  // @Brief CTOR, enables parallel operations as default
  // Cache the number of machine threads the system reports (can be
  // overridden by environment variables)
  // enable on startup by default
  ParallelControls() {
#ifdef PARALLEL
    machineThreads = omp_get_max_threads();
    Enable();
#else
    machineThreads = 1;
#endif
  }
  // @Brief Enable() enables parallel operation
  void Enable() {
#ifdef PARALLEL
    omp_set_num_threads(machineThreads);
#endif
  }
  // @Brief Disable() disables parallel operation
  void Disable() {
#ifdef PARALLEL
    omp_set_num_threads(0);
#endif
  }

  int GetMachineThreads() const { return machineThreads; }

  static int GetNumProcs() {
#ifdef PARALLEL
    return omp_get_num_procs();
#else
    return 1;
#endif
  }

  // @Brief returns current number of threads that are usable
  // @return int # threads
  int GetNumThreads() {
#ifdef PARALLEL
    int nthreads = 1;
    int tid = 1;
    // Fork a team of threads giving them their own copies of variables
    // so we can see how many threads we have to work with
#pragma omp parallel private(tid)
    {
      /* Obtain thread number */
      tid = omp_get_thread_num();

      /* Only master thread does this */
      if (tid == 0) {
        nthreads = omp_get_num_threads();
      }
    }
    // std::cout << "\nNumber of threads = " << nthreads << std::endl;
    return nthreads;

#else
    return machineThreads;
#endif
  }

  // @Brief sets number of threads to use (limited by system value)

  void SetNumThreads(int nthreads) {
#ifdef PARALLEL
    // set number of thread, but limit it to the system set
    // number of machine threads...
    if (nthreads > machineThreads) {
      nthreads = machineThreads;
    }
    omp_set_num_threads(nthreads);
#endif
  }
};

extern ParallelControls PalisadeParallelControls;

}  // namespace lbcrypto

\core\lib\utils\parallel.cpp

#include "utils/parallel.h"

namespace lbcrypto {

ParallelControls PalisadeParallelControls;
}

\core\include\utils\serializable.h

所有需要序列化的类都需要继承这个类

#ifndef LBCRYPTO_SERIALIZABLE_H
#define LBCRYPTO_SERIALIZABLE_H

// TODO (dsuponit): purge the headers below and combine #pragma for GNU and clang
#include <iostream>
#include <string>

#ifndef CEREAL_RAPIDJSON_HAS_STDSTRING
#define CEREAL_RAPIDJSON_HAS_STDSTRING 1
#endif
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#endif
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0

#ifdef __GNUC__
#if __GNUC__ >= 8
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif

#include "cereal/cereal.hpp"
#include "cereal/types/polymorphic.hpp"

#ifdef __GNUC__
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif

#ifdef __clang__
#pragma clang diagnostic pop
#endif

namespace lbcrypto {

using Serialized = void*;

/**
 * \class Serializable
 *
 * \brief Base class for PALISADE serialization
 *
 * This class is inherited by every class that needs to be serialized.
 * The class contains some deprecated(弃用的) methods from the older mechanisms
 * for serialization
 */
class Serializable {
 public:
  virtual ~Serializable() {}

  virtual std::string SerializedObjectName() const = 0;

};

// helper template to stream vector contents provided T has an stream operator<<
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "[";
  for (auto i = v.begin(); i != v.end(); ++i) {
    os << " " << *i;
  }
  os << " ]";
  return os;
}

}  // namespace lbcrypto

#endif

\core\include\utils\serial.h

调用C++序列化库cereal来进行序列化。

#ifndef LBCRYPTO_SERIAL_H
#define LBCRYPTO_SERIAL_H

// TODO (dsuponit): purge the headers below and combine #pragma for GNU and clang
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#ifndef CEREAL_RAPIDJSON_HAS_STDSTRING
#define CEREAL_RAPIDJSON_HAS_STDSTRING 1
#endif
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#endif
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0

#ifdef __GNUC__
#if __GNUC__ >= 8
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif

#include "utils/sertype.h"

#include "cereal/archives/portable_binary.hpp"
#include "cereal/archives/json.hpp"
#include "cereal/cereal.hpp"
#include "cereal/types/map.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/types/polymorphic.hpp"
#include "cereal/types/string.hpp"
#include "cereal/types/vector.hpp"

#ifdef __GNUC__
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif

#ifdef __clang__
#pragma clang diagnostic pop
#endif


namespace lbcrypto {

	namespace Serial {
		//========================== BINARY serialization ==========================
		/**
		 * Serialize an object
		 * @param obj - object to serialize
		 * @param stream - Stream to serialize to
		 * @param sertype - type of serialization; default is BINARY
		 */
		template <typename T>
		void Serialize(const T& obj, std::ostream& stream, const SerType::SERBINARY& st) {
			cereal::PortableBinaryOutputArchive archive(stream);
			archive(obj);
		}

		/**
		 * Deserialize an object
		 * @param obj - object to deserialize into
		 * @param stream - Stream to deserialize from
		 * @param sertype - type of de-serialization; default is BINARY
		 */
		template <typename T>
		void Deserialize(T& obj, std::istream& stream, const SerType::SERBINARY& st) {
			cereal::PortableBinaryInputArchive archive(stream);
			archive(obj);
		}

		template <typename T>
		bool SerializeToFile(const std::string& filename, const T& obj, const SerType::SERBINARY& sertype) {
			std::ofstream file(filename, std::ios::out | std::ios::binary);
			if (file.is_open()) {
				Serial::Serialize(obj, file, sertype);
				file.close();
				return true;
			}
			return false;
		}

		template <typename T>
		bool DeserializeFromFile(const std::string& filename, T& obj, const SerType::SERBINARY& sertype) {
			std::ifstream file(filename, std::ios::in | std::ios::binary);
			if (file.is_open()) {
				Serial::Deserialize(obj, file, sertype);
				file.close();
				return true;
			}
			return false;
		}

		//========================== JSON serialization ==========================
		/**
		 * Serialize an object
		 * @param obj - object to serialize
		 * @param stream - Stream to serialize to
		 * @param sertype - type of serialization; default is BINARY
		 */
		template <typename T>
		void Serialize(const T& obj, std::ostream& stream, const SerType::SERJSON& ser) {
			cereal::JSONOutputArchive archive(stream);
			archive(obj);
		}

		/**
		 * Deserialize an object
		 * @param obj - object to deserialize into
		 * @param stream - Stream to deserialize from
		 * @param sertype - type of serialization; default is BINARY
		 */
		template <typename T>
		void Deserialize(T& obj, std::istream& stream, const SerType::SERJSON& ser) {
			cereal::JSONInputArchive archive(stream);
			archive(obj);
		}

		template <typename T>
		bool SerializeToFile(const std::string& filename, const T& obj, const SerType::SERJSON& sertype) {
			std::ofstream file(filename, std::ios::out | std::ios::binary);
			if (file.is_open()) {
				Serial::Serialize(obj, file, sertype);
				file.close();
				return true;
			}
			return false;
		}

		template <typename T>
		bool DeserializeFromFile(const std::string& filename, T& obj, const SerType::SERJSON& sertype) {
			std::ifstream file(filename, std::ios::in | std::ios::binary);
			if (file.is_open()) {
				Serial::Deserialize(obj, file, sertype);
				file.close();
				return true;
			}
			return false;
		}

		/**
		 * SerializeToString - serialize the object to a JSON string and return the
		 * string
		 * @param t - any serializable object
		 * @return JSON string
		 */
		template <typename T>
		std::string SerializeToString(const T& t) {
			std::stringstream s;
			Serialize(t, s, SerType::JSON);
			return s.str();
		}


	}  // namespace Serial

}  // namespace lbcrypto

#endif

\core\include\utils\serialize-binary.h

弃用了,现在使用 serial.h

#include "serial.h"

#pragma message "utils/serialize-binary.h is deprecated and will be removed in the 3rd quarter of 2021. serial.h should be used instead"

\core\include\utils\serialize-json.h

同样弃用了。

#include "serial.h"

#pragma message "utils/serialize-json.h is deprecated and will be removed in the 3rd quarter of 2021. serial.h should be used instead"

\core\include\utils\sertype.h

Definition of serialization type.

#ifndef LBCRYPTO_SERTYPE_H
#define LBCRYPTO_SERTYPE_H


namespace lbcrypto {

namespace SerType {

class SERJSON { };
const static SERJSON JSON; // should be const static to avoid compilation failure

class SERBINARY { };
const static SERBINARY BINARY; // should be const static to avoid compilation failure

}  // namespace SerType

}  // namespace lbcrypto

#endif

\core\include\utils\testcasegen.h

Helper methods for serialization.

#ifndef SRC_CORE_LIB_UTILS_TESTCASEGEN_H_
#define SRC_CORE_LIB_UTILS_TESTCASEGEN_H_

#define GENERATE_PKE_TEST_CASE(TOPNAME, FUNC, ELEMENT, SCHEME, ORD, PTM) \
  TEST_F(TOPNAME, FUNC##_##ELEMENT##_##SCHEME) {                         \
    CryptoContext<ELEMENT> cc;                                           \
    try {                                                                \
      cc = GenTestCryptoContext<ELEMENT>(#SCHEME, ORD, PTM);             \
    } catch (const not_implemented_error&) {                             \
      return;                                                            \
    } catch (const not_available_error&) {                               \
      return;                                                            \
    } catch (const std::exception& ex) {                                 \
      std::cerr << "Exception occurred: " << ex.what() << std::endl;     \
    } catch (...) {                                                      \
      std::cerr << "Unknown failure occurred." << std::endl;             \
    }                                                                    \
    FUNC<ELEMENT>(cc, #SCHEME);                                          \
  }

#define GENERATE_PKE_TEST_CASE_BITS(TOPNAME, FUNC, ELEMENT, SCHEME, ORD, PTM, \
                                    BITS)                                     \
  TEST_F(TOPNAME, FUNC##_##ELEMENT##_##SCHEME) {                              \
    CryptoContext<ELEMENT> cc;                                                \
    try {                                                                     \
      cc = GenTestCryptoContext<ELEMENT>(#SCHEME, ORD, PTM, BITS);            \
    } catch (const not_implemented_error&) {                                  \
      return;                                                                 \
    } catch (const not_available_error&) {                                    \
      return;                                                                 \
    } catch (const std::exception& ex) {                                      \
      std::cerr << "Exception occurred: " << ex.what() << std::endl;          \
    } catch (...) {                                                           \
      std::cerr << "Unknown failure occurred." << std::endl;                  \
    }                                                                         \
    FUNC<ELEMENT>(cc, #SCHEME);                                               \
  }

#define GENERATE_BGVrns_TEST_CASE(TOPNAME, FUNC, ELEMENT, SCHEME, ORD, PTM, \
                                  SIZEMODULI, NUMPRIME, RELIN, KEYSWITCH,   \
                                  BATCH, RESCALEALG, MODSWITCHMETHOD)       \
  TEST_F(TOPNAME,                                                           \
         FUNC##_##ELEMENT##_##SCHEME##_##KEYSWITCH##_##MODSWITCHMETHOD) {   \
    CryptoContext<ELEMENT> cc;                                              \
    try {                                                                   \
      cc = GenTestCryptoContext<ELEMENT>(#SCHEME, ORD, PTM, SIZEMODULI,     \
                                         NUMPRIME, RELIN, BATCH, KEYSWITCH, \
                                         RESCALEALG, MODSWITCHMETHOD);      \
    } catch (const not_implemented_error&) {                                \
      return;                                                               \
    } catch (const not_available_error&) {                                  \
      return;                                                               \
    } catch (const std::exception& ex) {                                    \
      std::cerr << "Exception occurred: " << ex.what() << std::endl;        \
    } catch (...) {                                                         \
      std::cerr << "Unknown failure occurred." << std::endl;                \
    }                                                                       \
    FUNC<ELEMENT>(cc, #SCHEME);                                             \
  }

#define GENERATE_CKKS_TEST_CASE(TOPNAME, FUNC, ELEMENT, SCHEME, ORD, SCALE,    \
                                NUMPRIME, RELIN, BATCH, KEYSWITCH, RESCALEALG) \
  TEST_F(TOPNAME, FUNC##_##ELEMENT##_##SCHEME##_##KEYSWITCH##_##RESCALEALG) {  \
    CryptoContext<ELEMENT> cc;                                                 \
    try {                                                                      \
      cc = GenTestCryptoContext<ELEMENT>(#SCHEME, ORD, SCALE, SCALE, NUMPRIME, \
                                         RELIN, BATCH, KEYSWITCH, RESCALEALG); \
    } catch (const not_implemented_error&) {                                   \
      return;                                                                  \
    } catch (const not_available_error&) {                                     \
      return;                                                                  \
    } catch (const std::exception& ex) {                                       \
      std::cerr << "Exception occurred: " << ex.what() << std::endl;           \
    } catch (...) {                                                            \
      std::cerr << "Unknown failure occurred." << std::endl;                   \
    }                                                                          \
    FUNC<ELEMENT>(cc, #SCHEME);                                                \
  }

#endif /* SRC_CORE_LIB_UTILS_TESTCASEGEN_H_ */

\core\include\utils\utilities.h

This file contains the utility function functionality.

#include <string>
#include <iomanip>

#include "math/backend.h"
#include "math/distributiongenerator.h"
#include "math/nbtheory.h"

依旧是定义在 namespace lbcrypto 中。
zero padding:

/**
 * Zero Padding of Elements.
 * Adds zeros to form a polynomial of length 2n  (corresponding to cyclotomic
 * order m = 2n). It is used by the forward transform of
 * ChineseRemainderTransform (a modified version of ZeroPadd will be used for
 * the non-power-of-2 case).
 *
 * @param &InputPoly is the element to perform the transform on.
 * @param target_order is the intended target ordering.
 * @return is the output of the zero padding.
 */
template <typename V>
V ZeroPadForward(const V &InputPoly, usint target_order);

/**
 * Zero Pad Inverse of Elements.
 * Adds alternating zeroes to form a polynomial of length of length 2n
 * (corresponding to cyclotomic order m = 2n). It is used by the inverse
 * transform of ChineseRemainderTransform (a modified version of ZeroPadInverse
 * will be used for the non-power-of-2 case).
 *
 * @param &InputPoly is the element to perform the transform on.
 * @param target_order is the intended target ordering.
 * @return is the output of the zero padding.
 */
template <typename V>
V ZeroPadInverse(const V &InputPoly, usint target_order);

判断一个数是不是2的幂

/**
 * Determines if a number is a power of 2.
 *
 * @param Input to test if it is a power of 2.
 * @return is true if the unsigned int is a power of 2.
 */
inline bool IsPowerOfTwo(usint Input) {
  return Input && !(Input & (Input - 1));
}

Auxiliary function to replace a specific character “in” with another character “out”

/**
 * Auxiliary function to replace a specific character "in" with another
 * character "out"
 *
 * @param str string where in which characters are replaced
 * @param in character being replaced
 * @param out character to be replaced with
 * @return the modified string.
 */
// auxiliary function to replace a specific character "in" with another
// character "out"
std::string replaceChar(std::string str, char in, char out);
// Lazy Reduction functions: 64-bit multiplier and 128-bit Barrett reducer
// Originally proposed for BFVrnsB
/**
 * check if adding two 64-bit number can cause overflow
 * @param a: operand 1
 * @param b: operand 2
 * @return 1 if overflow occurs, 0 otherwise
 */
inline uint32_t IsAdditionOverflow(uint64_t a, uint64_t b) {
  a += b;
  if (a < b)
    return 1;
  else
    return 0;
}

/**
 * add two 64-bit number with carry out, c = a + b
 * @param a: operand 1
 * @param b: operand 2
 * @param c: c = a + b
 * @return 1 if overflow occurs, 0 otherwise
 */

inline uint32_t AdditionWithCarryOut(uint64_t a, uint64_t b, uint64_t &c) {
  a += b;
  c = a;
  if (a < b)
    return 1;
  else
    return 0;
}
#if defined(HAVE_INT128)
/**
 * 64-bit uint multiplier, result is 128-bit
 * @param a: operand 1
 * @param b: operand 2
 * @return result: 128-bit result = a * b
 */
inline DoubleNativeInt Mul128(uint64_t a, uint64_t b) {
  return DoubleNativeInt(a) * DoubleNativeInt(b);
}

/**
 * Barrett reduction of 128-bit integer modulo 64-bit integer. Source: Menezes,
 * Alfred; Oorschot, Paul; Vanstone, Scott. Handbook of Applied Cryptography,
 * Section 14.3.3.
 * @param a: operand (128-bit)
 * @param m: modulus (64-bit)
 * @param mu: 2^128/modulus (128-bit)
 * @return result: 64-bit result = a mod m
 */
inline uint64_t BarrettUint128ModUint64(const DoubleNativeInt &a,
                                        uint64_t modulus,
                                        const DoubleNativeInt &mu) {
  // (a * mu)/2^128 // we need the upper 128-bit of (256-bit product)
  uint64_t result = 0, a_lo = 0, a_hi = 0, mu_lo = 0, mu_hi = 0, left_hi = 0,
           middle_lo = 0, middle_hi = 0, tmp1 = 0, tmp2 = 0, carry = 0;
  DoubleNativeInt middle = 0;

  a_lo = (uint64_t)a;
  a_hi = a >> 64;
  mu_lo = (uint64_t)mu;
  mu_hi = mu >> 64;

  left_hi = (Mul128(a_lo, mu_lo)) >> 64;  // mul left parts, discard lower word

  middle = Mul128(a_lo, mu_hi);  // mul middle first
  middle_lo = (uint64_t)middle;
  middle_hi = middle >> 64;

  // accumulate and check carry
  carry = AdditionWithCarryOut(middle_lo, left_hi, tmp1);

  tmp2 = middle_hi + carry;  // accumulate

  middle = Mul128(a_hi, mu_lo);  // mul middle second
  middle_lo = (uint64_t)middle;
  middle_hi = middle >> 64;

  carry = IsAdditionOverflow(middle_lo, tmp1);  // check carry

  left_hi = middle_hi + carry;  // accumulate

  // now we have the lower word of (a * mu)/2^128, no need for higher word
  tmp1 = a_hi * mu_hi + tmp2 + left_hi;

  // subtract lower words only, higher words should be the same
  result = a_lo - tmp1 * modulus;

  while (result >= modulus) result -= modulus;

  return result;
}
#endif
/**
 * Generates a random 128-bit hash
 */
inline std::string GenerateUniqueKeyID() {
  const size_t intsInID = 128 / (sizeof(uint32_t) * 8);
  std::uniform_int_distribution<uint32_t> distribution(
      0, std::numeric_limits<uint32_t>::max());
  std::stringstream s;
  s.fill('0');
  s << std::hex;
  for (size_t i = 0; i < intsInID; i++)
    s << std::setw(8) << distribution(PseudoRandomNumberGenerator::GetPRNG());
  return s.str();
}

\core\lib\utils\utilities.cpp

#include "utils/utilities.h"

namespace lbcrypto {

// Zero-Padd adds extra zeros to the Input polynomial
// if Input polynomial has a length n less than CycloOrder,
// then it adds CycloOrder-n zeros in the Input Polynomial
template <typename V>
V ZeroPadForward(const V &InputPoly, usint target_order) {    // 在最后补 0
  if (InputPoly.GetLength() < target_order) {
    V ans(target_order);

    for (usint i = 0; i < InputPoly.GetLength(); i++)
      ans.at(i) = InputPoly.at(i);

    for (usint i = InputPoly.GetLength(); i < target_order; i++)
      ans.at(i) = typename V::Integer(0); // 告诉编译器这是类型不是变量

    ans.SetModulus(InputPoly.GetModulus());

    return ans;

  } else {
    return V(InputPoly);
  }
}

// Adds 0 between each BigInteger to support conversion from Inverse FFT to
// Inverse CRT
template <typename V>
V ZeroPadInverse(const V &InputPoly, usint target_order) {
  if (InputPoly.GetLength() < target_order) {       // 偶数位补 0
    V ans(target_order);

    for (usint i = 0; i < InputPoly.GetLength(); i++) {
      ans.at(2 * i) = typename V::Integer("0");
      ans.at(2 * i + 1) = InputPoly.at(i);
    }

    ans.SetModulus(InputPoly.GetModulus());

    return ans;
  } else {
    return V(InputPoly);
  }
}

// auxiliary function to replace a specific character "in" with another
// character "out"
std::string replaceChar(std::string str, char in, char out) {
  // set our locator equal to the first appearance of any character in replace
  size_t found = str.find_first_of(in);

  // While our position in the string is in range.
  while (found != std::string::npos) {
    str[found] = out;  // Change the character at position.
    found = str.find_first_of(in, found + 1);  // Relocate again.
  }

  return str;  // return our new string.
}

}  // namespace lbcrypto

\core\include\utils\parmfactory.h

parameter factory. 暂时没看懂。

#ifndef SRC_CORE_LIB_UTILS_PARMFACTORY_H_
#define SRC_CORE_LIB_UTILS_PARMFACTORY_H_

// useful for testing

#include <memory>
#include <vector>

#include "lattice/dcrtpoly.h"
#include "math/backend.h"
#include "math/distrgen.h"

#include "utils/inttypes.h"

#include "lattice/elemparams.h"
#include "lattice/ildcrtparams.h"
#include "lattice/ilelement.h"
#include "lattice/ilparams.h"
#include "lattice/poly.h"

using namespace lbcrypto;

/**
 * Generate an ILDCRTParams with a given number of parms, with cyphertext moduli
 * of at least a given size
 * @param m - order
 * @param numOfTower - # of polynomials
 * @param pbits - number of bits in the prime, to start with
 * @return
 */
template <typename I>
inline shared_ptr<ILDCRTParams<I>> GenerateDCRTParams(usint m, usint numOfTower,
                                                      usint pbits) {
  DEBUG_FLAG(false);
  DEBUG("in GenerateDCRTParams");
  DEBUGEXP(m);
  DEBUGEXP(numOfTower);
  DEBUGEXP(pbits);
  if (numOfTower == 0) {
    PALISADE_THROW(math_error, "Can't make parms with numOfTower == 0");
  }

  std::vector<NativeInteger> moduli(numOfTower);
  std::vector<NativeInteger> rootsOfUnity(numOfTower);

  NativeInteger q = FirstPrime<NativeInteger>(pbits, m);
  I modulus(1);

  usint j = 0;
  DEBUGEXP(q);

  for (;;) {
    moduli[j] = q;
    rootsOfUnity[j] = RootOfUnity(m, q);
    modulus = modulus * I(q.ConvertToInt());
    DEBUG("j " << j << " modulus " << q << " rou " << rootsOfUnity[j]);
    if (++j == numOfTower) break;

    q = NextPrime(q, m);
  }

  auto params = std::make_shared<ILDCRTParams<I>>(m, moduli, rootsOfUnity);

  return params;
}

#endif /* SRC_CORE_LIB_UTILS_PARMFACTORY_H_ */

\core\include\utils\memory.h

_MSC_VER 为微软C编译器版本
https://blog.csdn.net/a135138/article/details/114325057

#ifndef LBCRYPTO_UTILS_MEMORY_H
#define LBCRYPTO_UTILS_MEMORY_H

#include <algorithm>
#include <iterator>
#include <memory>
#include <utility>
#include <vector>

using std::unique_ptr;
using std::vector;

namespace lbcrypto {

//  make_unique was left out of c++11, these are the accepted implementation
#if _MSC_VER == 1700

//  MSVC11 does not support variadic templates
#define _MAKE_UNIQUE(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4) \
                                                                               \
  template <class T COMMA LIST(_CLASS_TYPE)>                                   \
  inline std::unique_ptr<T> make_unique(LIST(_TYPE_REFREF_ARG)) {              \
    return std::unique_ptr<T>(new T(LIST(_FORWARD_ARG)));                      \
  }
_VARIADIC_EXPAND_0X(_MAKE_UNIQUE, , , , )
#undef _MAKE_UNIQUE

#else

//  *nix implementation
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

#endif

template <class X>
void MoveAppend(std::vector<X>& dst, std::vector<X>& src) {
  if (dst.empty()) {
    dst = std::move(src);
  } else {
    dst.reserve(dst.size() + src.size());
    std::move(std::begin(src), std::end(src), std::back_inserter(dst));
    src.clear();
  }
}

}  // namespace lbcrypto

#endif  // LBCRYPTO_UTILS_MEMORY_H

\core\include\utils\hashutil.h

#ifndef _SRC_LIB_UTILS_HASHUTIL_H
#define _SRC_LIB_UTILS_HASHUTIL_H

#include <utils/exception.h>
#include <iostream>
#include <string>
#include <vector>
using std::string;
using std::vector;

namespace lbcrypto {

enum HashAlgorithm { SHA_256 = 0, SHA_512 = 1 };

class HashUtil {
 public:
  static void Hash(string message, HashAlgorithm algo,
                   vector<int64_t>& digest) {
    switch (algo) {
      case SHA_256:
        SHA256(message, digest);
        return;

      case SHA_512:
        // TODO SHA512 disabled, returning SHA256 instead
        SHA256(message, digest);
        return;

      default:
        PALISADE_THROW(not_available_error, "ERROR: Unknown Hash Algorithm");
    }
  }

  static std::string HashString(std::string message);

 private:
  static void SHA256(string message, vector<int64_t>& digest);
  static void SHA512(string message, vector<int64_t>& digest);
  static const uint32_t k_256[64];
  static const uint64_t k_512[80];
};

}  // namespace lbcrypto

#endif

\core\include\utils\define.h

config.h – Declarations of global configuration parameters

#ifndef SRC_CORE_INCLUDE_UTILS_DEFINES_H
#define SRC_CORE_INCLUDE_UTILS_DEFINES_H

// Avoid unused variable warnings
#define PALISADE_UNUSED(x) (void)(x)

#endif  // SRC_CORE_INCLUDE_UTILS_DEFINES_H

\core\include\utils\debug.h

This file contains macros and associated helper functions for quick cerr oriented debugging that can be quickly enabled and disabled. It also contains functions for timing code.
这个文件包含宏和相关的辅助函数,用于快速的面向cerr的调试,可以快速地启用和禁用这些调试。它还包含用于计时代码的函数。

#ifndef __dbg_h__
#define __dbg_h__

// include <iostream>
// include <cstdlib.h>

/* defining NDEBUG in the compile line turns everything off.
   unless PROFILE is defined in the file before all includes,'
   in which case TIC/TOC will still work and PROFILELOG() can be
   used for logging results to std::cout, and DEBUG() will remain
   silent. dbg_flag does not get used by PROFILELOG()
 */

#include <time.h>
#include <chrono>  // for timing
#include <utility>

#include "utils/inttypes.h"

#if !defined(NDEBUG)

// note that for the following dbg_flag needs to be defined in some scope using
// DEBUG_FLAG
#define DEBUG_FLAG(x) bool dbg_flag = x;

// debugging macro prints value of x on cerr
#define DEBUG(x)                   \
  do {                             \
    if (dbg_flag) {                \
      std::cerr << x << std::endl; \
    }                              \
  } while (0)

// debugging macro prints typography of x and value of x on cerr
#define DEBUGEXP(x)                             \
  do {                                          \
    if (dbg_flag) {                             \
      std::cerr << #x << ":" << x << std::endl; \
    }                                           \
  } while (0)

// debugging macro prints value of x and location in codex on cerr
#define DEBUGWHERE(x)                                               \
  do {                                                              \
    if (dbg_flag) {                                                 \
      std::cerr << __FILE__ << ":" << __LINE__ << ": "              \
                << #x << ":" << x << std::endl;                     \
    }                                                               \
  } while (0)

#if defined(PROFILE)  // Profiler works

#define PROFILELOG(x)              \
  do {                             \
    if (true) {                    \
      std::cout << x << std::endl; \
    }                              \
  } while (0)

// debugging macro prints typography of x and value of x on cerr
#define PROFILELOGEXP(x)                        \
  do {                                          \
    if (true) {                                 \
      std::cout << #x << ":" << x << std::endl; \
    }                                           \
  } while (0)

// debugging macro prints value of x and location in codex on cerr
#define PROFILELOGWHERE(x)                                          \
  do {                                                              \
    if (true) {                                                     \
      std::cout << #x << ":" << x << " at " << __FILE__ << " line " \
                << __LINE__ << std::endl;                           \
    }                                                               \
  } while (0)

#else  // #if!defined(PROFILE) // profiling a noop
#define PROFILELOG(x)
#define PROFILELOGEXP(x)
#define PROFILELOGWHERE(x)

#endif  // PROFILE

#define TIC(t) t = timeNow()
#define TOC(t) duration(timeNow() - t)
#define TOC_NS(t) duration_ns(timeNow() - t)
#define TOC_US(t) duration_us(timeNow() - t)
#define TOC_MS(t) duration_ms(timeNow() - t)

#else  // NDEBUG

// #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__,
// __LINE__, ##__VA_ARGS__)

#if !defined(PROFILE)

// these are turned off functions

#define DEBUG_FLAG(x)
#define DEBUG(x)
#define DEBUGEXP(x)
#define DEBUGWHERE(x)

#define PROFILELOG(x)
#define PROFILELOGEXP(x)
#define PROFILELOGWHERE(x)

#define TIC(t) t = timeNow()
#define TOC(t) std::chrono::steady_clock::duration::zero().count()
#define TOC_NS(t) std::chrono::steady_clock::duration::zero().count()
#define TOC_US(t) std::chrono::steady_clock::duration::zero().count()
#define TOC_MS(t) std::chrono::steady_clock::duration::zero().count()

#else  // PROFILE
// if PROFILE is turned on, then TIC TOC still work and

#define DEBUG_FLAG(x)
#define DEBUG(x)
#define DEBUGEXP(x)
#define DEBUGWHERE(x)

#define PROFILELOG(x)              \
  do {                             \
    if (true) {                    \
      std::cerr << x << std::endl; \
    }                              \
  } while (0)

// debugging macro prints typography of x and value of x on cerr
#define PROFILELOGEXP(x)                        \
  do {                                          \
    if (true) {                                 \
      std::cout << #x << ":" << x << std::endl; \
    }                                           \
  } while (0)

// debugging macro prints value of x and location in codex on cerr
#define PROFILELOGWHERE(x)                                          \
  do {                                                              \
    if (true) {                                                     \
      std::cout << #x << ":" << x << " at " << __FILE__ << " line " \
                << __LINE__ LL std::endl;                           \
    }                                                               \
  } while (0)

#define TIC(t) t = timeNow()
#define TOC(t) duration(timeNow() - t)
#define TOC_NS(t) duration_ns(timeNow() - t)
#define TOC_US(t) duration_us(timeNow() - t)
#define TOC_MS(t) duration_ms(timeNow() - t)

#endif  // PROFILE

#endif  // NDEBUG

typedef std::chrono::high_resolution_clock::time_point TimeVar;

#define duration(a) \
  std::chrono::duration_cast<std::chrono::milliseconds>(a).count()
#define duration_ns(a) \
  std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define duration_us(a) \
  std::chrono::duration_cast<std::chrono::microseconds>(a).count()
#define duration_ms(a) \
  std::chrono::duration_cast<std::chrono::milliseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()

double currentDateTime();

template <typename F, typename... Args>
double funcTime(F func, Args&&... args) {
  TimeVar t1 = timeNow();
  func(std::forward<Args>(args)...);
  return duration(timeNow() - t1);
}

#endif  // #__dbg_h__

\core\include\utils\caller_info.h

This file contains macros to help access caller function information

#ifndef _CALLER_INFO_H_
#define _CALLER_INFO_H_

#include <string>

/*
 *  ATTN: the caller information is accessible if BUILTIN_INFO_AVAILABLE is defined in CMakeLists.txt.
 *        Currently, USE_BUILTIN_INFO is defined for GCC only.
 *  Instructions how to use the macros defined below:
 *  if you want to access the caller information from within a function
 *  you should add CALLER_INFO_ARGS_HDR as the last argument to your function
 *  in the header file where the function is declared and add
 *  CALLER_INFO_ARGS_CPP as the last argument to your function in the source
 *  file where it is implemented. if you have the function definition only then
 *  CALLER_INFO_ARGS_HDR should be added. After that you can use the string
 *  CALLER_INFO inside the function.
 *  
 *  Example:
 *  before adding caller information
 *  *.h:
 *      void foo(int x);
 *  *.cpp:
 *      void foo(int x) {
 *          std::cout << "foo() input: " << x << std::endl;
 *      }
 *  
 *  after adding caller information
 *  *.h:
 *      void foo(int x, CALLER_INFO_ARGS_HDR);
 *  *.cpp:
 *      void foo(int x, CALLER_INFO_ARGS_CPP) {
 *          std::cout << "foo() input: " << x << CALLER_INFO << std::endl;
 *      }
 */

#ifdef BUILTIN_INFO_AVAILABLE

#define CALLER_INFO_ARGS_HDR                       \
    const char* callerFile = __builtin_FILE(),     \
    const char* callerFunc = __builtin_FUNCTION(), \
    size_t      callerLine = __builtin_LINE()

#define CALLER_INFO std::string(" [called from: ") + callerFile + ":" + \
                    callerFunc + "():l." + std::to_string(callerLine) + "]"

#else

#define CALLER_INFO_ARGS_HDR     \
    const char* callerFile = "", \
    const char* callerFunc = "", \
    size_t      callerLine = 0

#define CALLER_INFO std::string("")

#endif // BUILTIN_INFO_AVAILABLE


#define CALLER_INFO_ARGS_CPP \
    const char* callerFile,  \
    const char* callerFunc,  \
    size_t      callerLine


#endif // _CALLER_INFO_H_ 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值