wallet/ristretto255.cpp

132 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
void randombytes_buf(std::span<byte> in) { randombytes_buf(&in[0], in.size_bytes()); }
void randombytes_buf(std::span< char> in) { randombytes_buf(&in[0], in.size_bytes()); }
bool operator ==(const std::span<byte>& p, const std::span<byte>& q) {
bool breturn{ true };
for (auto xq = q.begin(); auto xp:p) {
if (xp != *xq++) {
breturn = false;
break;
}
}
return breturn;
}
bool operator !=(const std::span<byte>& p, const std::span<byte>& q) {
bool breturn{ false };
for (auto xq = q.begin(); auto xp:p) {
if (xp != *xq++) {
breturn = true;
break;
}
}
return breturn;
}
namespace ristretto255 {
bool scalar::constant_time_required{ true };
bool point::constant_time_required{ true };
scalar::scalar(int i) {
if (i >= 0) {
auto k{ unsigned int(i) };
for (auto& j : blob) { j = k; k = k >> 8; }
}
else{
std::array<uint8_t, crypto_core_ristretto255_BYTES> absdata;
auto k{ unsigned int(-i) };
for (auto& j : absdata) { j = k; k = k >> 8; }
crypto_core_ristretto255_scalar_negate(&blob[0], &absdata[0]);
}
}
point point::operator*(const scalar &sclr) const& noexcept {
point me;
auto i{ crypto_scalarmult_ristretto255(&me.blob[0], &sclr.blob[0], &blob[0]) };
assert(i == 0);
return me;
}
point point::operator*(int i) const& noexcept {
return scalar(i) * (*this);
}
point point::ptZero({
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
point point::ptBase({
0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71, 0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f, 0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d, 0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76});
signed_text::signed_text(
const scalar &k, // Signer's secret key
const point &Kin, // Signer's public key
std::span<char> txtin // Text to be signed.
)
: txt(txtin), K(Kin)
{
assert(k.valid());
assert(K.valid());
/* • Compute r = H(k|M), a per message private key. Or r can be an unpredictable secret scalar.
• Compute R = r*B, a per message public key<br/>
• Compute c = H(R|M).<br/>
• Compute s = r+c*k. (Note that sB = r*B+c*k*B = R+c*K.)*/
scalar r(hash<512>(k, txtin));
point R(r.timesBase());
c = scalar (hash<512>(R, txtin));
s = r + c * k;
}
bool signed_text::verify() {
/* • Check that c, s are valid scalars
• Check that K, the signing public key, is a valid member of the prime order group
• Compute R = sB cK
• Check that c = H(R | M) */
if (!c.valid() || !s.valid() || !K.valid())return false;
else {
point R = s.timesBase() - c * K;
return c==scalar(hash<512>(R, txt));
}
}
} //end ristretto255 namespace
using ristretto255::scalar, ro::CompileSizedString, ro::bin2hex, ro::to_base64_string;
auto reverse_byte_order(std::array < uint8_t, sizeof(scalar)>const& ac) {
std::array <uint8_t, sizeof(scalar)> ar;
auto p = ar.rbegin();
for (auto x : ac) {
*p++ = x;
}
return ar;
}
template<> CompileSizedString < 2 * sizeof(scalar)>
bin2hex<scalar>(const scalar& sc) {
CompileSizedString <2 * sizeof(scalar)>sz;
auto bigendian = reverse_byte_order(sc.blob);
sodium_bin2hex(&sz[0], sizeof(sc.blob) * 2 + 1, &bigendian[0], bigendian.size());
return sz;
}
template<> scalar ro::hex2bin<scalar>(const CompileSizedString< (2 * sizeof(scalar))>& sz) {
scalar sc;
sc.blob = reverse_byte_order(ro::hex2bin<decltype(sc.blob)>(sz));
return sc;
}
template<> CompileSizedString < (sizeof(scalar) * 8 + 5) / 6>
to_base64_string<scalar>(const scalar& sc) {
CompileSizedString < (sizeof(sc.blob) * 8 + 4) / 6> sz;
auto bigendian = reverse_byte_order(sc.blob);
bits2base64(
&(bigendian[0]), 4, sizeof(bigendian)*8-4,
std::span<char>(sz)
);
return sz;
}
namespace mpir {
mpz ristretto25519_curve_order("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16);
}