Skip to content

Commit

Permalink
repo-sync-2024-09-30T16:00:47+0800 (#395)
Browse files Browse the repository at this point in the history
* repo-sync-2024-09-30T16:00:47+0800

* Update .licenserc.yaml

* Update BUILD.bazel
  • Loading branch information
Jamie authored Sep 30, 2024
1 parent d33801a commit cf598ab
Show file tree
Hide file tree
Showing 16 changed files with 416 additions and 12 deletions.
20 changes: 10 additions & 10 deletions GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ $ sudo mv bazel /usr/local/bin # you need sudo to do this
To build Yacl, at yacl's root directory, run the following

```sh
$ bazel build //...
$ bazel build //... -c opt # build as optimized mode
$ bazel build //... -c dbg # build as debug mode
$ bazel build //... --config gm # build with gm mode
$ bazel build //yacl/...
$ bazel build //yacl/... -c opt # build as optimized mode
$ bazel build //yacl/... -c dbg # build as debug mode
$ bazel build //yacl/... --config gm # build with gm mode
```

To test Yacl

```sh
$ bazel test //...
$ bazel test //yacl/...
```

### MacOS
Expand All @@ -83,16 +83,16 @@ $ brew install bazelisk cmake ninja nasm automake libtool libomp
To build Yacl, at yacl's root directory, run the following

```sh
$ bazel build //...
$ bazel build //... -c opt # build as optimized mode
$ bazel build //... -c dbg # build as debug mode
$ bazel build //... --config gm # build with gm mode
$ bazel build //yacl/...
$ bazel build //yacl/... -c opt # build as optimized mode
$ bazel build //yacl/... -c dbg # build as debug mode
$ bazel build //yacl/... --config gm # build with gm mode
```

To test Yacl

```sh
$ bazel test //...
$ bazel test //yacl/...
```

## Setup compilation database for your lsp
Expand Down
2 changes: 2 additions & 0 deletions yacl/base/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ yacl_cc_library(
srcs = ["int128.cc"],
hdrs = ["int128.h"],
deps = [
"@com_google_absl//absl/numeric:bits",
"@com_google_absl//absl/numeric:int128",
],
)
Expand All @@ -50,6 +51,7 @@ yacl_cc_test(
srcs = ["int128_test.cc"],
deps = [
":int128",
"//yacl/crypto/rand",
],
)

Expand Down
11 changes: 11 additions & 0 deletions yacl/base/int128.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <iostream>
#include <limits>

#include "absl/numeric/bits.h"

// NOTE:
// We add our own int128 due to:
// - absl::int128 forget to support fully `constexpr`, i.e. `operator>>`. Giving
Expand Down Expand Up @@ -75,6 +77,15 @@ std::pair<int64_t, uint64_t> DecomposeInt128(int128_t v);

std::pair<uint64_t, uint64_t> DecomposeUInt128(uint128_t v);

inline int CountLZ(uint128_t v) {
auto [hi, lo] = DecomposeUInt128(v);
return hi == 0 ? absl::countl_zero(lo) + 64 : absl::countl_zero(hi);
}

inline int CountBitWidth(uint128_t v) {
return std::numeric_limits<uint128_t>::digits - CountLZ(v);
}

} // namespace yacl

#if !defined(__GNUC__)
Expand Down
18 changes: 17 additions & 1 deletion yacl/base/int128_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "gtest/gtest.h"

#include "yacl/crypto/rand/rand.h"

TEST(Int128Test, NumericLimitsTest) {
#ifdef __clang__
#pragma clang diagnostic push
Expand Down Expand Up @@ -76,4 +78,18 @@ TEST(Int128Test, Decompose) {
}
}

TEST(Int128Test, RandomTest) {}
TEST(Int128Test, CountLzTest) {
uint128_t x = 0;
EXPECT_EQ(yacl::CountLZ(x), 128);

x = 1;
EXPECT_EQ(yacl::CountLZ(x), 127);

x = yacl::crypto::FastRandU128();
EXPECT_EQ(yacl::CountLZ(x), yacl::CountLZ(x));

x = std::numeric_limits<uint128_t>::max();
int offset = yacl::crypto::RandLtN(128);
x >>= offset;
EXPECT_EQ(yacl::CountLZ(x), offset);
}
10 changes: 9 additions & 1 deletion yacl/crypto/ecc/lib25519/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test")

package(default_visibility = ["//visibility:public"])

config_setting(
name = "linux_x64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)

yacl_cc_library(
name = "lib25519",
deps = select({
"@platforms//cpu:x86_64": [
":linux_x64": [
":lib25519_factory",
],
"//conditions:default": [],
Expand Down
7 changes: 7 additions & 0 deletions yacl/crypto/rand/rand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ void FillRand(char *buf, size_t len, bool fast_mode) {
// ---------------------
// Other Implementations
// ---------------------
//
uint32_t RandU32(bool fast_mode) {
uint32_t rand32 = 0;
FillRand(reinterpret_cast<char *>(&rand32), sizeof(uint32_t), fast_mode);
return rand32;
}

uint64_t RandU64(bool fast_mode) {
uint64_t rand64 = 0;
FillRand(reinterpret_cast<char *>(&rand64), sizeof(uint64_t), fast_mode);
Expand Down
41 changes: 41 additions & 0 deletions yacl/crypto/rand/rand.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ void FillRand(char *buf, size_t len, bool fast_mode = false);
// Random Support for Generic Types
// --------------------------------

// Generate uint32_t random value
uint32_t RandU32(bool fast_mode = false);

// Generate uint32_t random value, in a faster but less secure way
inline uint32_t FastRandU32() { return RandU32(true); }

// Generate uint32_t random value, in a slower but more secure way
// (randomness comes directly from an random entropy source)
inline uint32_t SecureRandU32() { return RandU32(false); }

// Generate uint64_t random value
uint64_t RandU64(bool fast_mode = false);

Expand Down Expand Up @@ -225,4 +235,35 @@ class YaclReplayUrbg {
const CType ctype_;
};

template <class RandomIt>
void ReplayShuffle(RandomIt first, RandomIt last, uint128_t seed,
uint64_t *ctr) {
YACL_ENFORCE(ctr != nullptr);

using diff_t = typename std::iterator_traits<RandomIt>::difference_type;
diff_t n = last - first;

// prepare n-1 random numbers
// ind[0] in [0, 1], ind[1] in [0, 2] ... ind[n-2] in [0, n-1]
std::vector<uint128_t> ind(n - 1);

*ctr = yacl::crypto::FillPRand(
yacl::crypto::SymmetricCrypto::CryptoType::AES128_CTR, seed, 0, *ctr,
(char *)ind.data(), (n - 1) * sizeof(uint128_t));

// Though this is not strictly uniform random. it will
// provide statistical security of no less than 40 bits.
// i.e. for some fixed k, the statistical distance between our random
// variables and the ground truth uniform distribution over [0, k-1] is no
// more that 1/2 * (k / 2^{128}) < 2^{-64} (if we assume k < 2^64).
for (int64_t idx = 0; idx < n - 1; ++idx) {
ind[idx] = ind[idx] % (idx + 2);
}

// Knuth-Durstenfeld Shuffle
for (diff_t i = n - 1; i > 0; --i) { //
std::swap(first[i], first[ind[i - 1]]);
}
}

} // namespace yacl::crypto
36 changes: 36 additions & 0 deletions yacl/crypto/rand/rand_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,40 @@ TEST(GenericRandTest, ReplayRandomShuffleTest) {
EXPECT_EQ(std::memcmp(vec1.data(), vec4.data(), sizeof(uint128_t) * n), 0);
}
}

TEST(GenericRandTest, QuickShuffleTest) {
int n = 257;

auto vec = FastRandVec<uint128_t>(n);
auto ctr = FastRandU64();
auto seed = SecureRandSeed();

// copy
auto vec_bkup = vec;
// copy
auto vec_1 = vec;
auto ctr_1 = ctr;
// copy
auto vec_2 = vec;
auto ctr_2 = FastRandU64();

ReplayShuffle(vec.begin(), vec.end(), seed, &ctr);

// replay
ReplayShuffle(vec_1.begin(), vec_1.end(), seed, &ctr_1);
EXPECT_EQ(std::memcmp(vec.data(), vec_1.data(), sizeof(uint128_t) * n), 0);

// different state gives different shuffle
ReplayShuffle(vec_2.begin(), vec_2.end(), SecureRandSeed(), &ctr_2);
EXPECT_NE(std::memcmp(vec.data(), vec_2.data(), sizeof(uint128_t) * n), 0);

// values are exactly the same
std::sort(vec_bkup.begin(), vec_bkup.end());
std::sort(vec_1.begin(), vec_1.end());
std::sort(vec_2.begin(), vec_2.end());
EXPECT_EQ(std::memcmp(vec_bkup.data(), vec_1.data(), sizeof(uint128_t) * n),
0);
EXPECT_EQ(std::memcmp(vec_bkup.data(), vec_2.data(), sizeof(uint128_t) * n),
0);
}
} // namespace yacl::crypto
1 change: 1 addition & 0 deletions yacl/crypto/tools/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ yacl_cc_test(
srcs = ["prg_test.cc"],
deps = [
":prg",
"//yacl/crypto/rand",
],
)

Expand Down
43 changes: 43 additions & 0 deletions yacl/crypto/tools/prg.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,49 @@ uint64_t FillPRandWithMersennePrime(SymmetricCrypto::CryptoType crypto_type,
}
}

// -----------------------------
// Fill Pseudorandoms within mod
// -----------------------------

// type traits, currently we only support 3 types:
// uint128_t, uint64_t, uint32_t
template <typename T>
struct IsSupportedLtNContainerType
: public std::disjunction<std::is_same<uint128_t, T>,
std::is_same<uint64_t, T>,
std::is_same<uint32_t, T>> {};

template <typename T,
std::enable_if_t<IsSupportedLtNContainerType<T>::value, bool> = true>
uint64_t FillPRandWithLtN(SymmetricCrypto::CryptoType crypto_type,
uint128_t seed, uint64_t iv, uint64_t count,
absl::Span<T> out, T n) {
size_t n_bit_width = 0;
// first, fill all outputs with randomness
if constexpr (std::is_same_v<T, uint128_t>) {
n_bit_width = CountBitWidth(n);
} else {
n_bit_width = absl::bit_width(n);
}

auto required_size =
(n_bit_width + YACL_MODULE_SECPARAM_S_UINT("prg") + 7) / 8;
Buffer rand_bytes(out.size() * required_size);
auto ret = FillPRand(crypto_type, seed, iv, count, (char*)rand_bytes.data(),
out.size() * required_size);

// then, perform mod
ByteContainerView rand_view(rand_bytes);
for (size_t i = 0; i < out.size(); ++i) {
math::MPInt r;
r.FromMagBytes(rand_view.subspan(i * required_size, required_size),
Endian::little);
math::MPInt::Mod(r, math::MPInt(n), &r);
out[i] = r.Get<T>();
}
return ret;
}

// ---------------------------
// PRG with cache
// ---------------------------
Expand Down
35 changes: 35 additions & 0 deletions yacl/crypto/tools/prg_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "gtest/gtest.h"

#include "yacl/crypto/rand/rand.h"

namespace yacl::crypto {
namespace {

Expand Down Expand Up @@ -324,4 +326,37 @@ TEST(PRTest, MersennePrime8) {
}
}

TEST(PRTest, Ltn128) {
std::vector<uint128_t> out(1000);
uint128_t n = FastRandU128();
FillPRandWithLtN<uint128_t>(SymmetricCrypto::CryptoType::AES128_ECB, 0, 0, 0,
absl::MakeSpan(out), n);
EXPECT_NE(out[0], out[1]);
for (auto e : out) {
EXPECT_LT(e, n);
}
}

TEST(PRTest, Ltn64) {
std::vector<uint64_t> out(1000);
uint64_t n = FastRandU64();
FillPRandWithLtN<uint64_t>(SymmetricCrypto::CryptoType::AES128_ECB, 0, 0, 0,
absl::MakeSpan(out), n);
EXPECT_NE(out[0], out[1]);
for (auto e : out) {
EXPECT_LT(e, n);
}
}

TEST(PRTest, Ltn32) {
std::vector<uint64_t> out(1000);
uint32_t n = FastRandU32();
FillPRandWithLtN<uint64_t>(SymmetricCrypto::CryptoType::AES128_ECB, 0, 0, 0,
absl::MakeSpan(out), n);
EXPECT_NE(out[0], out[1]);
for (auto e : out) {
EXPECT_LT(e, n);
}
}

} // namespace yacl::crypto
24 changes: 24 additions & 0 deletions yacl/math/galois_field/benchmark/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2024 Ant Group Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("//bazel:yacl.bzl", "yacl_cc_binary")

yacl_cc_binary(
name = "operation_bench",
srcs = ["operation_bench.cc"],
deps = [
"//yacl/math/galois_field:gf",
"@com_github_google_benchmark//:benchmark_main",
],
)
Loading

0 comments on commit cf598ab

Please sign in to comment.