diff --git a/src/ristretto255.h b/src/ristretto255.h index 2247bc3..229caed 100644 --- a/src/ristretto255.h +++ b/src/ristretto255.h @@ -334,7 +334,11 @@ namespace ristretto255 { std::array blob; static_assert(sizeof(blob) == 32, "watch for size and alignment bugs. Everyone should standarize on 256 bit secret keys except for special needs"); explicit scalar() = default; - ~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); } + ~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); } /*calls wipe to avoid leaving secrets around in memory. + Because wxSecretValue::Wipe is in a different optimisation unit, a separately compiled library, + optimisation of the destructor cannot optimise away the call to the wipe, + because the destructor optimiser does not know that all wipe does is + write to memory that is about to be discarded, nor can the wipe optimiser know that. */ explicit constexpr scalar(std::array&& in) : blob{ in } {}; explicit constexpr scalar(std::array* in) :blob(*in) {}; explicit constexpr scalar(uintmax_t k){ for (auto& j : blob) { j = k; k = k >> 8; } } @@ -345,9 +349,9 @@ namespace ristretto255 { static_assert (ro::is_standard_signed_integer); if (i < 0) crypto_core_ristretto255_scalar_negate(&blob[0], &blob[0]); } - scalar(scalar&&) = default; // Move constructor + scalar(scalar&&) = default; // Move constructor. Does not need to call wipe, because destructor will be called on source scalar(const scalar&) = default; // Copy constructor - scalar& operator=(scalar&&) = default; // Move assignment. + scalar& operator=(scalar&&) = default; // Move assignment. Does not need to call wipe, because destructor will be called on source scalar& operator=(const scalar&) = default; // Copy assignment. /* Don't need constant time equality test bool operator==(const scalar& sc) const& {