diff --git a/internal/crypto/random.cc b/internal/crypto/random.cc index 6f68e7b5..07615b21 100644 --- a/internal/crypto/random.cc +++ b/internal/crypto/random.cc @@ -16,6 +16,8 @@ #include +#include + #include namespace crypto { @@ -28,4 +30,11 @@ void RandBytes(absl::Span bytes) { RandBytes(bytes.data(), bytes.size()); } +std::string RandBytes(size_t length) { + std::string result(length, 0); + RandBytes(const_cast(result.data()), + result.size()); + return result; +} + } // namespace crypto diff --git a/internal/crypto/random.h b/internal/crypto/random.h index 72adde00..213bedc8 100644 --- a/internal/crypto/random.h +++ b/internal/crypto/random.h @@ -17,6 +17,8 @@ #include +#include + #include "absl/types/span.h" #include "internal/crypto/crypto_export.h" @@ -29,6 +31,19 @@ CRYPTO_EXPORT void RandBytes(void *bytes, size_t length); // Fills |bytes| with cryptographically-secure random bits. CRYPTO_EXPORT void RandBytes(absl::Span bytes); + +// Returns |length| random bytes. +CRYPTO_EXPORT std::string RandBytes(size_t length); + +// Creates an object of type T initialized with random data. +// This template should be used for simple data types: int, char, etc. +template +T RandData() { + T data; + RandBytes(&data, sizeof(data)); + return data; +} + } // namespace crypto #endif // THIRD_PARTY_NEARBY_INTERNAL_CRYPTO_RANDOM_H_ diff --git a/internal/crypto/random_unittest.cc b/internal/crypto/random_unittest.cc index 3854da62..0c30222e 100644 --- a/internal/crypto/random_unittest.cc +++ b/internal/crypto/random_unittest.cc @@ -23,6 +23,9 @@ // Basic functionality tests. Does NOT test the security of the random data. +namespace crypto { +namespace { + // Ensures we don't have all trivial data, i.e. that the data is indeed random. // Currently, that means the bytes cannot be all the same (e.g. all zeros). bool IsTrivial(const std::string& bytes) { @@ -36,6 +39,28 @@ bool IsTrivial(const std::string& bytes) { TEST(RandBytes, RandBytes) { std::string bytes(16, '\0'); - crypto::RandBytes(nearbybase::WriteInto(&bytes, bytes.size()), bytes.size()); + RandBytes(nearbybase::WriteInto(&bytes, bytes.size()), bytes.size()); EXPECT_TRUE(!IsTrivial(bytes)); } + +TEST(RandBytes, RandomString) { + constexpr size_t kSize = 30; + + std::string bytes = RandBytes(kSize); + + EXPECT_EQ(bytes.size(), kSize); + EXPECT_TRUE(!IsTrivial(bytes)); +} + +TEST(RandBytes, RandData) { + uint64_t x = RandData(); + uint64_t y = RandData(); + + // Once in a billion years, consecutively generated random numbers will be + // the same and the test will fail. + EXPECT_NE(x, y); + EXPECT_NE(x >> 32, x & 0xFFFFFFFF); +} + +} // namespace +} // namespace crypto