Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/lib/math/bigint/bigint.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef BOTAN_BIGINT_H_
#define BOTAN_BIGINT_H_

#include <botan/concepts.h>
#include <botan/secmem.h>
#include <botan/types.h>
#include <iosfwd>
Expand Down Expand Up @@ -708,11 +709,8 @@ class BOTAN_PUBLIC_API(2, 0) BigInt final {
* Throws if the BigInt is too large to encode in the length
* specified.
*/
template <typename T = std::vector<uint8_t>>
template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
T serialize(size_t len) const {
// TODO this supports std::vector and secure_vector
// it would be nice if this also could work with std::array as in
// bn.serialize_to<std::array<uint8_t, 32>>(32);
T out(len);
this->serialize_to(out);
return out;
Expand All @@ -721,11 +719,27 @@ class BOTAN_PUBLIC_API(2, 0) BigInt final {
/**
* Serialize the value of this BigInt as a big endian encoding.
*/
template <typename T = std::vector<uint8_t>>
template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
T serialize() const {
return serialize<T>(this->bytes());
}

/**
* Serialize the BigInt into a fixed-size std::array.
*
* This is a convenience method for serialization into compile-time fixed
* size arrays.
*
* @tparam len the size of the output array in bytes
* @return std::array containing the serialized BigInt (big-endian)
*/
template <size_t len>
std::array<uint8_t, len> serialize_to_array() const {
std::array<uint8_t, len> out{};
serialize_to(out);
return out;
}

/**
* Store BigInt-value in a given byte array
* @param buf destination byte array for the integer value
Expand Down
42 changes: 42 additions & 0 deletions src/tests/test_bigint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,48 @@ std::vector<Test::Result> test_bigint_serialization() {
b.binary_encode(enc5.data(), enc5.size());
res.test_bin_eq("BigInt::binary_encode", enc5, "000000000000000000000000FEDCBA9876543210BAADC0FFEE");
}),

CHECK("BigInt std::array serialization",
[](Test::Result& res) {
const Botan::BigInt testData(0x1234567890ABCDEF);

const auto arr32 = testData.serialize_to_array<32>();
res.test_sz_eq("BigInt::serialize std::array size", arr32.size(), size_t{32});
res.test_bin_eq("BigInt::serialize array compare",
arr32,
"0000000000000000000000000000000000000000000000001234567890ABCDEF");

const auto vec32 = testData.serialize<std::vector<uint8_t>>(32);
res.test_bin_eq("BigInt::serialize std::array matches vector",
std::span<const uint8_t>(arr32),
std::span<const uint8_t>(vec32));

res.test_u8_eq("BigInt::serialize std::array last byte", arr32[31], uint8_t{0xEF});
res.test_u8_eq("BigInt::serialize std::array first bytes zeroed", arr32[0], uint8_t{0x00});

res.test_throws<Botan::Invalid_Argument>("BigInt::serialize_to_array too small", [&testData]() {
[[maybe_unused]] const auto arr = testData.serialize_to_array<4>();
});

const Botan::BigInt smallTestData = Botan::BigInt::from_u64(0xFF);
const auto arr8 = smallTestData.serialize_to_array<8>();
res.test_sz_eq("BigInt::serialize std::array small size", arr8.size(), size_t{8});
res.test_u8_eq("BigInt::serialize std::array small value last byte", arr8[7], uint8_t{0xFF});
res.test_u8_eq("BigInt::serialize std::array small value zeroed", arr8[0], uint8_t{0x00});

const Botan::BigInt zero = Botan::BigInt::zero();
const auto arr0 = zero.serialize_to_array<4>();
res.test_sz_eq("BigInt::serialize std::array zero serialization size", arr0.size(), 4);
res.test_bin_eq("BigInt::serialize std::array all zeros",
std::span<const uint8_t>(arr0),
std::vector<uint8_t>(arr0.size(), 0x00));

const Botan::BigInt large("0xFEDCBA9876543210FEDCBA9876543210");
const auto arr16 = large.serialize_to_array<16>();
res.test_sz_eq("BigInt::serialize std::array large size", arr16.size(), size_t{16});
res.test_u8_eq("BigInt::serialize std::array large first byte", arr16[0], uint8_t{0xFE});
res.test_u8_eq("BigInt::serialize std::array large last byte", arr16[15], uint8_t{0x10});
}),
};
}

Expand Down
Loading