diff --git a/src/ristretto255.h b/src/ristretto255.h index 30cc919..f571ea5 100644 --- a/src/ristretto255.h +++ b/src/ristretto255.h @@ -119,6 +119,8 @@ namespace ristretto255 { assert(i == 0); } + operator hash(); + template hsh& hashinto(const T& j, Args... args) { auto sj = ro::serialize(j); @@ -150,24 +152,51 @@ namespace ristretto255 { static_assert(!has_machine_independent_representation >, "Don't want to partially hash partial hashes"); // This constructs a finalized hash. - // If it has one argument, and that argument is hsh (unfinalized hash) object, - // it finalizes the hash. (see hsh) - // Usage - // hash(a, b, c ...); - // hash and hsh serialize all their arguments, converting them into machine - // and compiler independent form. If they don't know how to serialize an - // argument type, you get a compile time error. To serialize a new type, + // + // Usage: + // hash c(x, y, z ...); + // creates the variable c, and initializes and finalizes it with the hash of x, y, z ... + // + // is equivalent to + // hsh b(); + // b << x << y; b << z << ...; //unfinalized hash + // hash c(b); //creates c and finalizes b + // // Any subsequent operations on b should cause a run time exception. + // + // and equivalent to + // hash<256> c = hsh() << x << y << z << ...; + // + // and equivalent to + // hash<256> c(hsh() << x << y << z << ... ) + // + // hash and hsh serialize all their arguments, converting them into machine, + // compiler, and locale independent form. If they don't know how to serialize + // an argument type, you get a compile time error. + // "the concept 'ro::has_machine_independent_representation<...>' evaluated to false" + // + // Suppose you don't want hsh finalized, perhaps because you are creating many + // hashes each with same very lengthy preamble but different suffixes: Then: + // hsh(b); + // b << preamble; + // hash cfoo = hsh(b) << suffix_foo; + // hash cbar = hsh(b) << suffix_bar; + // + // To serialize a new type, // create a new overload for the function "serialize" // to hash a wxString, use its ToUTF8 member // wxString wxsHello(L"Hello world"); // hash hashHello(wxsHello.ToUTF8()); - // C array arguments after the first are vulnerable to array decay to pointer, so use hsh and "<<" - // for them. or wrap them in std::span(OldTypeCarray) + // Old type C array arguments after the first are vulnerable to array decay + // to pointer, which will generate a compile time error. If this happens use + // hsh and "<<" for them. or wrap them in std::span // It always a wise precaution to not use old type C arays, or wrap them // in a span. - // Old type zero terminated utf8 strings work. The trailing zero is included. + // std::strings and old type zero terminated utf8 strings work. The trailing + // zero is included in the hash so that hash("tea", "spoon") != hash("teaspoon") // The program should by running in the UTF8 locale, attempts to set that - // locale on startup. and tests for success in the unit test. + // locale on startup. and tests for success in the unit test, so that the + // same string will yield the same hash no matter where in the world the code + // is running. template class hash { static_assert( hashsize > 63 && hashsize % 64 == 0 @@ -220,6 +249,10 @@ namespace ristretto255 { return blob != pt.blob; //Do not need constant time equality test on hashes } }; + template + hsh::operator hash() { + return hash(*this); + } // a class representing ristretto255 elliptic points, // which are conveniently of prime order.