Skip to content

Commit

Permalink
add signed integers and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksandr-Tkachenko authored Aug 27, 2022
1 parent 875d278 commit 56fa049
Show file tree
Hide file tree
Showing 16 changed files with 705 additions and 119 deletions.
1 change: 1 addition & 0 deletions src/motioncore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ add_library(motion
protocols/share.cpp
protocols/share_wrapper.cpp
protocols/wire.cpp
secure_type/secure_signed_integer.cpp
secure_type/secure_unsigned_integer.cpp
statistics/analysis.cpp
statistics/run_time_statistics.cpp
Expand Down
6 changes: 6 additions & 0 deletions src/motioncore/algorithm/boolean_algorithms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@

#include "boolean_algorithms.h"

#include <algorithm>
#include <cassert>
#include <cmath>

#include "protocols/share.h"

namespace encrypto::motion::algorithm {

std::pair<ShareWrapper, ShareWrapper> FullAdder(const ShareWrapper& a, const ShareWrapper& b,
Expand Down
37 changes: 27 additions & 10 deletions src/motioncore/base/party.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,25 @@ class Party {
}
}

template <MpcProtocol P, typename T = std::uint8_t,
typename = std::enable_if_t<std::is_unsigned_v<T>>>
template <MpcProtocol P, typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
SharePointer In(const std::vector<T>& input,
std::size_t party_id = std::numeric_limits<std::size_t>::max()) {
switch (P) {
case MpcProtocol::kArithmeticConstant: {
return backend_->ConstantArithmeticGmwInput(input);
if constexpr (std::is_unsigned_v<T>) {
return backend_->ConstantArithmeticGmwInput<T>(input);
} else {
return backend_->ConstantArithmeticGmwInput<std::make_unsigned_t<T>>(
ToTwosComplement<T>(input));
}
}
case MpcProtocol::kArithmeticGmw: {
return backend_->ArithmeticGmwInput<T>(party_id, input);
if constexpr (std::is_unsigned_v<T>) {
return backend_->ArithmeticGmwInput<T>(party_id, input);
} else {
return backend_->ArithmeticGmwInput<std::make_unsigned_t<T>>(party_id,
ToTwosComplement<T>(input));
}
}
case MpcProtocol::kAstra: {
return backend_->AstraInput<T>(party_id, input);
Expand All @@ -227,16 +236,25 @@ class Party {
}
}

template <MpcProtocol P, typename T = std::uint8_t,
typename = std::enable_if_t<std::is_unsigned_v<T>>>
template <MpcProtocol P, typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
SharePointer In(std::vector<T>&& input,
std::size_t party_id = std::numeric_limits<std::size_t>::max()) {
switch (P) {
case MpcProtocol::kArithmeticConstant: {
return backend_->ConstantArithmeticGmwInput(std::move(input));
if constexpr (std::is_unsigned_v<T>) {
return backend_->ConstantArithmeticGmwInput<T>(input);
} else {
return backend_->ConstantArithmeticGmwInput<std::make_unsigned_t<T>>(
ToTwosComplement<T>(input));
}
}
case MpcProtocol::kArithmeticGmw: {
return backend_->ArithmeticGmwInput<T>(party_id, std::move(input));
if constexpr (std::is_unsigned_v<T>) {
return backend_->ArithmeticGmwInput<T>(party_id, input);
} else {
return backend_->ArithmeticGmwInput<std::make_unsigned_t<T>>(party_id,
ToTwosComplement<T>(input));
}
}
case MpcProtocol::kAstra: {
return backend_->AstraInput<T>(party_id, std::move(input));
Expand All @@ -258,8 +276,7 @@ class Party {
}
}

template <MpcProtocol P, typename T = std::uint8_t,
typename = std::enable_if_t<std::is_unsigned_v<T>>>
template <MpcProtocol P, typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
SharePointer In(T input, std::size_t party_id = std::numeric_limits<std::size_t>::max()) {
if constexpr (std::is_same_v<T, bool>) {
if constexpr (P == MpcProtocol::kBooleanGmw)
Expand Down
2 changes: 1 addition & 1 deletion src/motioncore/primitives/random/aes128_ctr_rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#include "aes128_ctr_rng.h"

#include <array>
#include <openssl/rand.h>
#include <fstream>
#include <openssl/rand.h>

#include "primitives/aes/aesni_primitives.h"

Expand Down
21 changes: 21 additions & 0 deletions src/motioncore/protocols/share_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "share_wrapper.h"

#include <cassert>
#include <stdexcept>
#include <typeinfo>

Expand Down Expand Up @@ -52,6 +53,8 @@
#include "protocols/data_management/unsimdify_gate.h"
#include "protocols/garbled_circuit/garbled_circuit_provider.h"
#include "secure_type/secure_unsigned_integer.h"
#include "share.h"
#include "utility/bit_vector.h"

namespace encrypto::motion {

Expand Down Expand Up @@ -240,10 +243,12 @@ ShareWrapper ShareWrapper::operator*(const ShareWrapper& other) const {
assert(*other);
assert(share_);
assert(share_->GetNumberOfSimdValues() == other->GetNumberOfSimdValues());

bool lhs_is_arith = share_->GetCircuitType() == CircuitType::kArithmetic;
bool rhs_is_arith = other->GetCircuitType() == CircuitType::kArithmetic;
bool lhs_is_bool = share_->GetCircuitType() == CircuitType::kBoolean;
bool rhs_is_bool = other->GetCircuitType() == CircuitType::kBoolean;

if (!lhs_is_arith || !rhs_is_arith) {
if (lhs_is_bool && rhs_is_arith) {
if (other->GetBitLength() == 8u) {
Expand Down Expand Up @@ -815,6 +820,11 @@ T ShareWrapper::As() const {
} else {
throw std::invalid_argument("Unsupported arithmetic protocol in ShareWrapper::As()");
}
} else if constexpr (std::is_signed<T>()) {
std::make_unsigned_t<T> unsigned_value{As<std::make_unsigned_t<T>>()};
bool msb{(unsigned_value >> sizeof(T) * 8 - 1) == 1};
T signed_value{msb ? -static_cast<T>(-unsigned_value) : static_cast<T>(unsigned_value)};
return signed_value;
} else if constexpr (is_specialization<T, std::vector>::value &&
std::is_unsigned<typename T::value_type>()) {
// std::vector of unsigned integers
Expand Down Expand Up @@ -847,6 +857,17 @@ T ShareWrapper::As() const {
} else {
throw std::invalid_argument("Unsupported arithmetic protocol in ShareWrapper::As()");
}
} else if constexpr (is_specialization<T, std::vector>::value &&
std::is_signed<typename T::value_type>()) {
auto unsigned_values{As<std::vector<std::make_unsigned_t<typename T::value_type>>>()};
T signed_values;
signed_values.reserve(unsigned_values.size());
for (auto& v : unsigned_values) {
bool msb{(v >> sizeof(T) * 8 - 1) == 1};
T signed_value{msb ? -static_cast<T>(-v) : static_cast<T>(v)};
signed_values.emplace_back(signed_value);
}
return unsigned_values;
} else {
throw std::invalid_argument(
fmt::format("Unsupported output type in ShareWrapper::As<{}>()", typeid(T).name()));
Expand Down
3 changes: 0 additions & 3 deletions src/motioncore/protocols/share_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@

#pragma once

#include <cassert>
#include <limits>
#include <memory>
#include <span>
#include <vector>

#include "share.h"
#include "utility/bit_vector.h"
#include "utility/typedefs.h"

namespace encrypto::motion {
Expand Down
104 changes: 104 additions & 0 deletions src/motioncore/secure_type/secure_signed_integer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// MIT License
//
// Copyright (c) 2022 Oleksandr Tkachenko
// Cryptography and Privacy Engineering Group (ENCRYPTO)
// TU Darmstadt, Germany
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "secure_signed_integer.h"

#include "protocols/share.h"
#include "utility/bit_vector.h"

namespace encrypto::motion {

SecureSignedInteger SecureSignedInteger::Simdify(std::span<SecureSignedInteger> input) {
std::vector<SharePointer> input_as_shares;
input_as_shares.reserve(input.size());
std::transform(input.begin(), input.end(), std::back_inserter(input_as_shares),
[&](SecureSignedInteger& i) -> SharePointer { return i.Get().Get(); });
return SecureSignedInteger(ShareWrapper::Simdify(input_as_shares));
}

SecureSignedInteger SecureSignedInteger::Simdify(std::vector<SecureSignedInteger>&& input) {
return Simdify(input);
}

SecureSignedInteger SecureSignedInteger::Subset(std::span<const size_t> positions) {
ShareWrapper unwrap{this->Get()};
return SecureUnsignedInteger(unwrap.Subset(positions));
}

SecureSignedInteger SecureSignedInteger::Subset(std::vector<size_t>&& positions) {
return Subset(std::span<const std::size_t>(positions));
}

std::vector<SecureSignedInteger> SecureSignedInteger::Unsimdify() const {
auto unsigned_ints{share_.Unsimdify()};
std::vector<SecureSignedInteger> result(unsigned_ints.begin(), unsigned_ints.end());
return result;
}

SecureSignedInteger SecureSignedInteger::Out(std::size_t output_owner) const {
return SecureSignedInteger(share_.Out(output_owner));
}

template <typename T>
T SecureSignedInteger::As() const {
if (share_.Get()->GetProtocol() == MpcProtocol::kArithmeticGmw) {
if constexpr (std::is_signed_v<T>) {
using U = typename std::make_unsigned<T>::type;
return FromTwosComplement<U>(share_.Get().As<U>());
} else {
using value_type = typename T::value_type;
using unsigned_value_type = typename std::make_unsigned<value_type>::type;
using U = typename std::vector<unsigned_value_type>;
return FromTwosComplement<unsigned_value_type>(share_.Get().As<U>());
}
} else if (share_.Get()->GetProtocol() == MpcProtocol::kBooleanGmw ||
share_.Get()->GetProtocol() == MpcProtocol::kBmr) {
auto share_out = share_.Get().As<std::vector<encrypto::motion::BitVector<>>>();
if constexpr (std::is_signed<T>()) {
using U = typename std::make_unsigned<T>::type;
U unsigned_output{encrypto::motion::ToOutput<U>(share_out)};
return FromTwosComplement(unsigned_output);
} else {
using value_type = typename T::value_type;
using unsigned_value_type = typename std::make_unsigned<value_type>::type;
using U = typename std::vector<unsigned_value_type>;
U unsigned_output{encrypto::motion::ToVectorOutput<unsigned_value_type>(share_out)};
return FromTwosComplement(unsigned_output);
}
} else {
throw std::invalid_argument("Unsupported protocol for SecureSignedInteger::As()");
}
}

template std::int8_t SecureSignedInteger::As() const;
template std::int16_t SecureSignedInteger::As() const;
template std::int32_t SecureSignedInteger::As() const;
template std::int64_t SecureSignedInteger::As() const;

template std::vector<std::int8_t> SecureSignedInteger::As() const;
template std::vector<std::int16_t> SecureSignedInteger::As() const;
template std::vector<std::int32_t> SecureSignedInteger::As() const;
template std::vector<std::int64_t> SecureSignedInteger::As() const;

} // namespace encrypto::motion
Loading

0 comments on commit 56fa049

Please sign in to comment.