From d336633ca3a024e6fff20300d521847bf7ebfdcc Mon Sep 17 00:00:00 2001 From: Anders Dalskov Date: Tue, 21 Jun 2022 21:20:05 +0200 Subject: [PATCH] new version --- CMakeLists.txt | 3 +- RELEASE.txt | 12 +- include/scl/math/ff.h | 220 ++++++++++++++++++++++++----------- include/scl/math/field_ops.h | 136 ++++++++++++++++++++++ include/scl/math/fields.h | 105 ----------------- src/scl/math/mersenne127.cc | 78 ++++++++----- src/scl/math/mersenne61.cc | 71 ++++++----- test/scl/gf7.cc | 102 ++++++++++++++++ test/scl/gf7.h | 58 --------- 9 files changed, 494 insertions(+), 291 deletions(-) create mode 100644 include/scl/math/field_ops.h delete mode 100644 include/scl/math/fields.h create mode 100644 test/scl/gf7.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 22907fa..b7665b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ cmake_minimum_required( VERSION 3.14 ) -project( scl VERSION 1.0.1 DESCRIPTION "Secure Computation Library" ) +project( scl VERSION 1.1.1 DESCRIPTION "Secure Computation Library" ) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) @@ -74,6 +74,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug") test/scl/test_hash.cc test/scl/test_prg.cc + test/scl/gf7.cc test/scl/math/test_mersenne61.cc test/scl/math/test_mersenne127.cc test/scl/math/test_vec.cc diff --git a/RELEASE.txt b/RELEASE.txt index 49e8db9..170602c 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -1,3 +1,9 @@ +1.1: Refactoring of finite field internals +- Finite field operations are now defined by individual specializations of + templated functions +- Remove DEFINE_FINITE_FIELD macro +- Move Mersenne61 and Mersenne127 definitions into ff.h + 1.0: Initial public version of SCL. - Features: - Math: @@ -10,9 +16,9 @@ - PRG based on AES-CTR - IUF Hash based on SHA3 - Networking: - - Basic support for peer-to-peer communication via TCP. Channels are designed - in such a way that writing custom ones (or decorators for existing channels) - is easy + - Basic support for peer-to-peer communication via TCP. Channels are + designed in such a way that writing custom ones (or decorators for + existing channels) is easy - Peer discovery functionality to make it easier to setup working networks - Secret Sharing: - Shamir secret sharing with support for both error detection and correction diff --git a/include/scl/math/ff.h b/include/scl/math/ff.h index ec86340..90e6b80 100644 --- a/include/scl/math/ff.h +++ b/include/scl/math/ff.h @@ -26,7 +26,7 @@ #include #include "scl/math/bases.h" -#include "scl/math/fields.h" +#include "scl/math/field_ops.h" #include "scl/math/ring.h" #include "scl/prg.h" @@ -34,21 +34,50 @@ namespace scl { namespace details { /** - * @brief Elements of the finite field \f$\mathbb{F}_p\f$ for prime \f$p\f$. + * @brief Elements of the finite field \f$\mathbb{F}\f$. * - *

This class defines finite field element that behaves according to some - * finite field definition as specified by the \p Field template parameter. The - * \p Bits parameter is used to indicate the number of available bits of the - * field, but is otherwise ignored.

+ *

The FF class provides the high level interface for "finite field elements" + * in SCL.

* - *

FF uses will call a number of static methods on \p Field, so these must be - * defined in order for FF to work. The interface of these methods can be seen - * in #DEFINE_FINITE_FIELD or by reading the documentation of the methods on - * FF.

+ *

An instantiation of this template consists of two parameters: A \p Bits + * parameter, indicating the number of bits that the field supports, and a \p + * Field type which determines the behaviour of the field. The \p Bits parameter + * is purely for documenting purposes and can be used to indicate that a + * particular field instantiation supports a particular number of bits for + * computing.

+ * + *

The \p Field parameter must be a class of the following form

+ * + * \code + * struct SomeField { + * using ValueType = ... // the internal type of a field element + * constexpr static const char* kName = ... // readable name of this field + * constexpr static const std::size_t kByteSize = ... // size in bytes + * constexpr static const std::size_t kBitSize = ... // size in bits + * }; + * \endcode + * + *

The kBitSize does not need to have any relation to the \p + * Bits parameter, although it's assumed that Bits <= kBitSize.

+ * + *

In order to make a field definition useful, overloads must be defined for + * some or all of the functions in field_ops.h. For example, to support addition + * operations on the field (that is, the operators + and + * +=) we would need to define

+ * + * \code + * template <> + * void scl::details::FieldAdd(SomeField::ValueType& out, + * const SomeField::ValueType& in) { + * // definition of addition for SomeField + * } + * \endcode + * + *

Refer to the documentation for methods on FF to see which specializations + * are needed where.

* * @tparam Bits the desired bit size of the field - * @tparam Field a class defining operations on field elements - * @see DEFINE_FINITE_FIELD + * @tparam Field the field */ template class FF final : details::RingBase> { @@ -92,16 +121,13 @@ class FF final : details::RingBase> { /** * @brief Read a field element from a buffer. - * - * The de-serialization of field elements are defined by a static method - * Field::FromBytes(ValueType&, const unsigned char*). - * * @param src the buffer * @return a field element. + * @see scl::details::FieldFromBytes */ static FF Read(const unsigned char* src) { FF e; - Field::FromBytes(e.mValue, src); + details::FieldFromBytes(e.mValue, src); return e; } @@ -118,18 +144,14 @@ class FF final : details::RingBase> { /** * @brief Create a field element from a string. - * - * De-stringification is determined by the static method - * Field::FromString(ValueType&, const std::string&, enum - * NumberBase). - * * @param str the string * @param base the base of the string * @return a finite field element. + * @see scl::details::FieldFromString */ static FF FromString(const std::string& str, enum NumberBase base) { FF e; - Field::FromString(e.mValue, str, base); + details::FieldFromString(e.mValue, str, base); return e; }; @@ -137,7 +159,6 @@ class FF final : details::RingBase> { * @brief Create a field element from a base 10 string. * @param str the string * @return a finite field element. - * @see FF::FromString */ static FF FromString(const std::string& str) { return FF::FromString(str, NumberBase::DECIMAL); @@ -145,13 +166,12 @@ class FF final : details::RingBase> { /** * @brief Create a new element from an int. - * - * The resulting field element is created according to the static method - * Field::FromInt(int). - * * @param value the value to interpret as a field element + * @see scl::details::FieldConvertIn */ - explicit constexpr FF(int value) : mValue(Field::FromInt(value)){}; + explicit constexpr FF(int value) { + details::FieldConvertIn(mValue, value); + }; /** * @brief Create a new element equal to 0 in the field. @@ -160,43 +180,34 @@ class FF final : details::RingBase> { /** * @brief Add another field element to this. - * - * Field element addition is defined by the static method - * Field::Add(ValueType&, const ValueType&). - * * @param other the other element * @return this set to this + \p other. + * @see scl::details::FieldAdd */ FF& operator+=(const FF& other) { - Field::Add(mValue, other.mValue); + details::FieldAdd(mValue, other.mValue); return *this; }; /** * @brief Subtract another field element to this. - * - * Field element subtraction is defined by the static method - * Field::Subtract(ValueType&, const ValueType&). - * * @param other the other element * @return this set to this - \p other. + * @see scl::details::FieldSubtract */ FF& operator-=(const FF& other) { - Field::Subtract(mValue, other.mValue); + details::FieldSubtract(mValue, other.mValue); return *this; }; /** * @brief Multiply another field element to this. - * - * Field element multiplication is defined by the static method - * Field::Multiply(ValueType&, const ValueType&). - * * @param other the other element * @return this set to this * \p other. + * @see scl::details::FieldMultiply */ FF& operator*=(const FF& other) { - Field::Multiply(mValue, other.mValue); + details::FieldMultiply(mValue, other.mValue); return *this; }; @@ -213,14 +224,11 @@ class FF final : details::RingBase> { /** * @brief Negates this element. - * - * Field element negation is defined by - * Field::Negate(ValueType&). - * * @return this set to -this. + * @see scl::details::FieldNegate */ FF& Negate() { - Field::Negate(mValue); + details::FieldNegate(mValue); return *this; }; @@ -232,21 +240,18 @@ class FF final : details::RingBase> { FF Negated() { auto copy = mValue; FF r; - Field::Negate(copy); + details::FieldNegate(copy); r.mValue = copy; return r; }; /** * @brief Inverts this element. - * - * Computation of field element inverses is defined by - * Field::Invert(ValueType). - * * @return this set to its inverse. + * @see scl::details::FieldInvert */ FF& Invert() { - Field::Invert(mValue); + details::FieldInvert(mValue); return *this; }; @@ -264,40 +269,113 @@ class FF final : details::RingBase> { * @brief Checks if this element is equal to another. * @param other the other element * @return true if this is equal to \p other. + * @see scl::details::FieldEqual */ bool Equal(const FF& other) const { - return Field::Equal(mValue, other.mValue); + return details::FieldEqual(mValue, other.mValue); }; /** * @brief Returns a string representation of this element. - * - * Stringification of an element is defined by - * Field::ToString(ValueType). - * * @return a string representation of this field element. + * @see scl::details::FieldToString */ - std::string ToString() const { return Field::ToString(mValue); }; + std::string ToString() const { + return details::FieldToString(mValue); + }; /** * @brief Write this element to a byte buffer. - * - *

Serializes this field element. Serialization is defined by - * Field::ToBytes(unsigned char*, const ValueType&). In general, - * it should be the case that \p dest has space for \ref ByteSize() amount of - * bytes, although more may be needed depending on Field.

- * - *

For pre-defined fields in SCL, \p dest must have space for \ref - * ByteSize() amount of bytes.

- * * @param dest the buffer. Must have space for \ref ByteSize() bytes. + * @see scl::details::FieldToBytes */ - void Write(unsigned char* dest) const { Field::ToBytes(dest, mValue); } + void Write(unsigned char* dest) const { + details::FieldToBytes(dest, mValue); + }; private: ValueType mValue; }; +/** + * @brief The field \f$\mathbb{F}_p\f$ with \f$p=2^{61}-1\f$. + */ +struct Mersenne61 { + /** + * @brief Internal type elements of this field. + */ + using ValueType = std::uint64_t; + + /** + * @brief The name of this field. + */ + constexpr static const char* kName = "Mersenne61"; + + /** + * @brief The size of field elements of this field in bytes. + */ + constexpr static const std::size_t kByteSize = sizeof(ValueType); + + /** + * @brief The size of field elements of this field in bits. + */ + constexpr static const std::size_t kBitSize = 61; +}; + +/** + * @brief The field \f$\mathbb{F}_p\f$ with \f$p=2^{127}-1\f$. + */ +struct Mersenne127 { + /** + * @brief Internal type elements of this field. + */ + using ValueType = __uint128_t; + + /** + * @brief The name of this field. + */ + constexpr static const char* kName = "Mersenne127"; + + /** + * @brief The size of field elements of this field in bytes. + */ + constexpr static const std::size_t kByteSize = sizeof(ValueType); + + /** + * @brief The size of field elements of this field in bits. + */ + constexpr static const std::size_t kBitSize = 127; +}; + +#define _SCL_LE(a, b) ((a) <= (b)) +#define _SCL_GE(a, b) ((a) >= (b)) + +/** + * @brief Select a suitable Finite Field based on a provided bitlevel. + */ +template +struct FieldSelector { + /** + * @brief The field. + */ + // clang-format off + using Field = + std::conditional_t< + _SCL_GE(Bits, 1) && _SCL_LE(Bits, 61), + Mersenne61, + + std::conditional_t< + _SCL_GE(Bits, 62) && _SCL_LE(Bits, 127), + Mersenne127, + + void>>; + + // clang-format on +}; + +#undef _SCL_LE +#undef _SCL_GE + } // namespace details /** diff --git a/include/scl/math/field_ops.h b/include/scl/math/field_ops.h new file mode 100644 index 0000000..b6254d5 --- /dev/null +++ b/include/scl/math/field_ops.h @@ -0,0 +1,136 @@ +/** + * @file field_ops.h + * + * SCL --- Secure Computation Library + * Copyright (C) 2022 Anders Dalskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _SCL_MATH_FIELD_OPS_H +#define _SCL_MATH_FIELD_OPS_H + +#include +#include +#include +#include + +#include "scl/math/bases.h" +#include "scl/math/str.h" + +namespace scl { +namespace details { + +/** + * @brief Convert an int into a field element. + * @param out where to store the converted element + * @param value the integer to convert + */ +template +void FieldConvertIn(typename F::ValueType& out, const int value); + +/** + * @brief Add two field elements in-place. + * @param out the first operand and output + * @param op the second operand + */ +template +void FieldAdd(typename F::ValueType& out, const typename F::ValueType& op); + +/** + * @brief Subtract two field elements in-place. + * @param out the first operand and output + * @param op the second operand + */ +template +void FieldSubtract(typename F::ValueType& out, const typename F::ValueType& op); + +/** + * @brief Multiply two field elements in-place. + * @param out the first operand and output + * @param op the second operand + */ +template +void FieldMultiply(typename F::ValueType& out, const typename F::ValueType& op); + +/** + * @brief Negate a field element in-place. + * @param out the element to negate + */ +template +void FieldNegate(typename F::ValueType& out); + +/** + * @brief Invert a field element in-place. + * @param out the element to invert + */ +template +void FieldInvert(typename F::ValueType& out); + +/** + * @brief Check if two field elements are the same. + * @param in1 the first element + * @param in2 the second element + * @return true if \p in1 and \p in2 are the same and false otherwise + */ +template +bool FieldEqual(const typename F::ValueType& in1, + const typename F::ValueType& in2); + +/** + * @brief Convert a field element to bytes. + * + * For types that are trivially copyable, this function has a default + * implementation based on std::memcpy. + * + * @param dest the field element to convert + * @param src where to store the converted element + */ +template , + int> = 0> +void FieldToBytes(unsigned char* dest, const typename F::ValueType& src) { + std::memcpy(dest, &src, sizeof(typename F::ValueType)); +} + +/** + * @brief Convert the content of a buffer to a field element. + * @param dest where to store the converted element + * @param src the buffer + */ +template +void FieldFromBytes(typename F::ValueType& dest, const unsigned char* src); + +/** + * @brief Convert a field element to a string. + * @param in the field element to convert + * @return an STL string representation of \p in. + */ +template +std::string FieldToString(const typename F::ValueType& in); + +/** + * @brief Read a field element from a string. + * @param out where to store the resulting element + * @param src the string + * @param base the base that the string is in + */ +template +void FieldFromString(typename F::ValueType& out, const std::string& src, + enum NumberBase base); + +} // namespace details +} // namespace scl + +#endif // _SCL_MATH_FIELD_OPS_H diff --git a/include/scl/math/fields.h b/include/scl/math/fields.h deleted file mode 100644 index ee06e2b..0000000 --- a/include/scl/math/fields.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file fields.h - * - * SCL --- Secure Computation Library - * Copyright (C) 2022 Anders Dalskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef _SCL_MATH_FIELDS_H -#define _SCL_MATH_FIELDS_H - -#include -#include -#include - -#include "scl/math/bases.h" - -namespace scl { -namespace details { - -#define _SCL_STR(x) #x - -/** - * @def DEFINE_FINITE_FIELD(name, bits, internal_type) - * @brief Helper macro for defining custom Finite Fields. - * - *

This macro can be used to define a class with all the required methods for - * working with \ref scl::details::FF.

- * - * @param[in] finite_field_name the type name of the finite field - * @param[in] bits the bitsize of the field. Must be unique - * @param[in] internal_type the type used for internally representing - elements - */ -#define DEFINE_FINITE_FIELD(finite_field_name, bits, internal_type) \ - struct finite_field_name { \ - using ValueType = internal_type; \ - constexpr static const char* kName = _SCL_STR(finite_field_name); \ - constexpr static const std::size_t kByteSize = sizeof(ValueType); \ - constexpr static const std::size_t kBitSize = bits; \ - static ValueType FromInt(int); \ - static void Add(ValueType&, const ValueType&); \ - static void Subtract(ValueType&, const ValueType&); \ - static void Multiply(ValueType&, const ValueType&); \ - static void Negate(ValueType&); \ - static void Invert(ValueType&); \ - static bool Equal(const ValueType&, const ValueType&); \ - static void ToBytes(unsigned char*, const ValueType&); \ - static void FromBytes(ValueType&, const unsigned char*); \ - static std::string ToString(const ValueType&); \ - static void FromString(ValueType&, const std::string&, enum NumberBase); \ - } - -#define _SCL_DEFINE_FINITE_FIELD(n, b, t) DEFINE_FINITE_FIELD(n, b, t) - -_SCL_DEFINE_FINITE_FIELD(Mersenne61, 61, std::uint64_t); - -_SCL_DEFINE_FINITE_FIELD(Mersenne127, 127, __uint128_t); - -#define _SCL_LE(a, b) ((a) <= (b)) -#define _SCL_GE(a, b) ((a) >= (b)) - -/** - * @brief Select a suitable Finite Field based on a provided bitlevel. - */ -template -struct FieldSelector { - /** - * @brief The field. - */ - // clang-format off - using Field = - std::conditional_t< - _SCL_GE(Bits, 1) && _SCL_LE(Bits, 61), - Mersenne61, - - std::conditional_t< - _SCL_GE(Bits, 62) && _SCL_LE(Bits, 127), - Mersenne127, - - void>>; - - // clang-format on -}; - -#undef _SCL_STR -#undef _SCL_LE -#undef _SCL_GE - -} // namespace details -} // namespace scl - -#endif // _SCL_MATH_FIELDS_H diff --git a/src/scl/math/mersenne127.cc b/src/scl/math/mersenne127.cc index a4ef10f..5d19946 100644 --- a/src/scl/math/mersenne127.cc +++ b/src/scl/math/mersenne127.cc @@ -22,39 +22,39 @@ #include #include "./simple_ff.h" -#include "scl/math/fields.h" +#include "scl/math/ff.h" #include "scl/math/str.h" using u64 = std::uint64_t; using u128 = __uint128_t; static const u128 p = (((u128)0x7FFFFFFFFFFFFFFF) << 64) | 0xFFFFFFFFFFFFFFFF; -using _ = scl::details::Mersenne127; +using Mersenne127 = scl::details::Mersenne127; -u128 _::FromInt(int v) { return v < 0 ? v + p : v; } - -void _::Add(u128 &t, const u128 &v) { ModAdd(t, v, p); } - -void _::Subtract(u128 &t, const u128 &v) { ModSub(t, v, p); } - -void _::Negate(u128 &t) { ModNeg(t, p); } - -bool _::Equal(const u128 &a, const u128 &b) { return a == b; } +template <> +void scl::details::FieldConvertIn(u128& out, const int value) { + out = value < 0 ? value + p : value; +} -void _::Invert(u128 &t) { ModInv(t, t, p); } +template <> +void scl::details::FieldAdd(u128& out, const u128& op) { + ModAdd(out, op, p); +} -void _::FromString(u128 &dest, const std::string &str, - enum scl::NumberBase base) { - FromStringSimpleType(dest, str, base); +template <> +void scl::details::FieldSubtract(u128& out, const u128& op) { + ModSub(out, op, p); } +namespace { + struct u256 { u128 high; u128 low; }; // https://cp-algorithms.com/algebra/montgomery_multiplication.html -static inline u256 MultiplyFull(const u128 x, const u128 y) { +u256 MultiplyFull(const u128 x, const u128 y) { u64 a = x >> 64, b = x; u64 c = y >> 64, d = y; // (a*2^64 + b) * (c*2^64 + d) = @@ -71,24 +71,50 @@ static inline u256 MultiplyFull(const u128 x, const u128 y) { return {high, low}; } -void _::Multiply(u128 &t, const u128 &v) { - u256 z = MultiplyFull(t, v); - t = z.high << 1; +} // namespace + +template <> +void scl::details::FieldMultiply(u128& out, const u128& op) { + u256 z = MultiplyFull(out, op); + out = z.high << 1; u128 b = z.low; - t |= b >> 127; + out |= b >> 127; b &= p; - Add(t, b); + ModAdd(out, b, p); } -std::string _::ToString(const u128 &v) { return scl::details::ToString(v); } +template <> +void scl::details::FieldNegate(u128& out) { + ModNeg(out, p); +} + +template <> +void scl::details::FieldInvert(u128& out) { + ModInv(out, out, p); +} + +template <> +bool scl::details::FieldEqual(const u128& in1, const u128& in2) { + return in1 == in2; +} -void _::FromBytes(u128 &dest, const unsigned char *src) { - dest = *(const u128 *)src; +template <> +void scl::details::FieldFromBytes(u128& dest, + const unsigned char* src) { + dest = *(const u128*)src; dest = dest % p; } -void _::ToBytes(unsigned char *dest, const u128 &src) { - std::memcpy(dest, (unsigned char *)&src, 16); +template <> +std::string scl::details::FieldToString(const u128& in) { + return ToString(in); +} + +template <> +void scl::details::FieldFromString(u128& dest, + const std::string& str, + enum scl::NumberBase base) { + FromStringSimpleType(dest, str, base); } diff --git a/src/scl/math/mersenne61.cc b/src/scl/math/mersenne61.cc index d7751cc..a0fa447 100644 --- a/src/scl/math/mersenne61.cc +++ b/src/scl/math/mersenne61.cc @@ -23,56 +23,73 @@ #include #include "./simple_ff.h" -#include "scl/math/fields.h" +#include "scl/math/ff.h" #include "scl/math/str.h" using u64 = std::uint64_t; using u128 = __uint128_t; static const u64 p = 0x1FFFFFFFFFFFFFFF; -using _ = scl::details::Mersenne61; +using Mersenne61 = scl::details::Mersenne61; -u64 _::FromInt(int v) { return v < 0 ? v + p : v; } - -void _::Add(u64& t, const u64& v) { ModAdd(t, v, p); } - -void _::Subtract(u64& t, const u64& v) { ModSub(t, v, p); } - -void _::Negate(u64& t) { ModNeg(t, p); } - -bool _::Equal(const u64& a, const u64& b) { - // This is fine since this method should never be called directly, but is - // instead called by the surrounding FF object which makes sure to only pass - // values that are in a valid range. - return a == b; +template <> +void scl::details::FieldConvertIn(u64& out, const int value) { + out = value < 0 ? value + p : value; } -void _::Invert(u64& t) { ModInv(t, t, p); } +template <> +void scl::details::FieldAdd(u64& out, const u64& op) { + ModAdd(out, op, p); +} -void _::FromString(u64& dest, const std::string& str, - enum scl::NumberBase base) { - FromStringSimpleType(dest, str, base); +template <> +void scl::details::FieldSubtract(u64& out, const u64& op) { + ModSub(out, op, p); } -void _::Multiply(u64& t, const u64& v) { - u128 z = (u128)t * v; +template <> +void scl::details::FieldMultiply(u64& out, const u64& op) { + u128 z = (u128)out * op; u64 a = z >> 61; u64 b = (u64)z; a |= b >> 61; b &= p; - Add(a, b); - t = a; + ModAdd(a, b, p); + out = a; +} + +template <> +void scl::details::FieldNegate(u64& out) { + ModNeg(out, p); +} + +template <> +void scl::details::FieldInvert(u64& out) { + ModInv(out, out, p); } -std::string _::ToString(const u64& v) { return scl::details::ToString(v); } +template <> +bool scl::details::FieldEqual(const u64& in1, const u64& in2) { + return in1 == in2; +} -void _::FromBytes(u64& dest, const unsigned char* src) { +template <> +void scl::details::FieldFromBytes(u64& dest, + const unsigned char* src) { dest = *(const u64*)src; dest = dest % p; } -void _::ToBytes(unsigned char* dest, const u64& src) { - std::memcpy(dest, &src, sizeof(u64)); +template <> +std::string scl::details::FieldToString(const u64& in) { + return ToString(in); +} + +template <> +void scl::details::FieldFromString(u64& dest, + const std::string& str, + enum scl::NumberBase base) { + FromStringSimpleType(dest, str, base); } diff --git a/test/scl/gf7.cc b/test/scl/gf7.cc new file mode 100644 index 0000000..35ffc58 --- /dev/null +++ b/test/scl/gf7.cc @@ -0,0 +1,102 @@ +/** + * @file gf7.cc + * + * SCL --- Secure Computation Library + * Copyright (C) 2022 Anders Dalskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "./gf7.h" + +#include "scl/math/field_ops.h" + +using GF7 = scl::details::GF7; + +template <> +void scl::details::FieldConvertIn(unsigned char& out, int v) { + auto r = v % 7; + out = r < 0 ? 7 + r : r; +} + +template <> +void scl::details::FieldAdd(unsigned char& out, const unsigned char& op) { + out = (out + op) % 7; +} + +template <> +void scl::details::FieldSubtract(unsigned char& out, + const unsigned char& op) { + if (out < op) + out = 7 + out - op; + else + out = out - op; +} + +template <> +void scl::details::FieldMultiply(unsigned char& out, + const unsigned char& op) { + out = (out * op) % 7; +} + +template <> +void scl::details::FieldNegate(unsigned char& out) { + out = (7 - out) % 7; +} + +template <> +void scl::details::FieldInvert(unsigned char& out) { + unsigned char inv; + switch (out) { + case 1: + case 6: + inv = out; + break; + case 2: + inv = 4; + break; + case 3: + inv = 5; + break; + case 4: + inv = 2; + break; + case 5: + inv = 3; + break; + default: + throw std::logic_error("0 not invertible modulo prime"); + } + out = inv; +} + +template <> +bool scl::details::FieldEqual(const unsigned char& in1, + const unsigned char& in2) { + return in1 == in2; +} + +template <> +void scl::details::FieldFromBytes(unsigned char& dest, + const unsigned char* src) { + dest = *src; + dest = dest % 7; +} + +template <> +std::string scl::details::FieldToString(const unsigned char& value) { + std::stringstream ss; + ss << (int)value; + return ss.str(); +} diff --git a/test/scl/gf7.h b/test/scl/gf7.h index 9de71da..1dda8ed 100644 --- a/test/scl/gf7.h +++ b/test/scl/gf7.h @@ -34,64 +34,6 @@ struct GF7 { constexpr static const char* kName = "GF(7)"; constexpr static const std::size_t kByteSize = 1; constexpr static const std::size_t kBitSize = 8; - static ValueType FromInt(int x) { - auto r = x % 7; - auto v = r < 0 ? 7 + r : r; - return v; - }; - static void Add(ValueType& t, const ValueType& b) { t = (t + b) % 7; }; - static void Subtract(ValueType& t, const ValueType& v) { - if (t < v) - t = 7 + t - v; - else - t = t - v; - }; - static void Multiply(ValueType& t, const ValueType& v) { t = (t * v) % 7; }; - static void Negate(ValueType& t) { t = (7 - t) % 7; } - static void Invert(ValueType& t) { - ValueType inv; - switch (t) { - case 1: - case 6: - inv = t; - break; - case 2: - inv = 4; - break; - case 3: - inv = 5; - break; - case 4: - inv = 2; - break; - case 5: - inv = 3; - break; - default: - throw std::logic_error("0 not invertible modulo prime"); - } - - t = inv; - }; - static bool Equal(const ValueType& a, const ValueType& b) { return a == b; } - static void ToBytes(unsigned char* dest, const ValueType& src) { - *dest = src; - } - static void FromBytes(ValueType& dest, const unsigned char* src) { - dest = *src; - dest = dest % 7; - } - static void FromString(ValueType& dest, const std::string& str, - enum NumberBase base) { - (void)str; - (void)base; - dest = 0; - } - static std::string ToString(const ValueType& v) { - std::stringstream ss; - ss << (int)v; - return ss.str(); - }; }; } // namespace details