AFAIK (no crypto expert), what you would want in that case is a "cryptographic hash function" (=practically non-reversible), which you use with a salt to prevent dictionary attacks.

 

But is it so bad, if the used name can be guessed?

 

Dictionary attacks are quite difficult with unique names.

Instead of a more or less random salt, one could use it as the set seed value.

And best the seed is also quite random (auto-generated) than simple numbers to prevent simple seed + simple name.

 

 

 

Just as example: The name then can be hierarchical in the sense of: COMPANY.PROJECT.SUBPROJECT.COMPONENT.SUBCOMPONENT.VERSION.

 

or whatever the caller chooses to do.

 


 

-----Ursprüngliche Nachricht-----
Von: Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org>
Gesendet: Di 11.03.2025 15:29
Betreff: Re: [std-proposals] Random numbers in identical builds
An: std-proposals@lists.isocpp.org;
CC: Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>;
On Tue, Mar 11, 2025 at 12:25 PM Sebastian Wittmeier wrote:
>
> If you want reproducible numbers,
>
> why not use a parameter to identify the specific id instead of using counters or hashing files?
>
> Seed + Parameter = uuid
>
> That would work with multiple TUs, too



Yeah that sounds like a good idea . . . I think the name should be
hashed to produce a 128-Bit number, and then encrypted, like as
follows:

   https://godbolt.org/z/vx9fjYjKv

Encrypting it after getting the hash means that hackers won't be able
to brute force it by trying a dictionary of different names.

and here it is copy-pasted from GodBolt:

   #include <cstdint>            // uint_least32_t
   #include <source_location>    // source_location::current
   #include <string>             // string
   #include <type_traits>        // is_unsigned

   // Here is a 128-Bit number which we use sort
   // of like a 'seed' for generating UUID's
   // (really it's an encryption key)
   constexpr __uint128_t my_secret_key = (0x1122334455667788u |
((__uint128_t)0x99aabbccddeeff00u << 64));

   // The C++ standard library hasn't got a
   // constexpr way of converting a number
   // to a string, hence this:
   template<typename T> requires std::is_unsigned_v<T>
   constexpr std::string uint_to_base10_string(T num)
   {
       if ( 0u == num ) return "0";
       std::string s;
       while ( num )
       {
           s.insert( s.begin(), '0' + (num % 10u) );
           num /= 10u;
       }
       return s;
   }

   // Hash algorithm for hashing a string
   constexpr __uint128_t get_hash_of_string(char const *str)
   {
       // Let's pretend that this is a constexpr
       // implementation of the MD5 algorithm
       __uint128_t retval = 0u;
       while ( *str ) retval += *str++;
       return retval;
   }

   // Encryption algorithm for encrypting a 128-Bit number
   constexpr void encrypt_one_block(__uint128_t &block, __uint128_t const &key)
   {
       // Let's pretend that this is a constexpr
       // implementation of the AES128 algorithm
       block ^= key;
   }

   // We can create a 'named' or an 'unnamed' UUID
   constexpr __uint128_t uuid( char const *const name = nullptr )
   {
       __uint128_t retval = 0u;

       if ( nullptr == name )
       {
           auto const location = std::source_location::current();
           retval ^= get_hash_of_string( location.file_name()     );
           retval ^= get_hash_of_string( location.function_name() );
           constexpr auto *to_str = &uint_to_base10_string<
std::uint_least32_t >;
           retval ^= get_hash_of_string( to_str(location.column()).c_str() );
           retval ^= get_hash_of_string( to_str(location.line  ()).c_str() );
       }
       else
       {
           retval = get_hash_of_string(name);
       }

       encrypt_one_block(retval, my_secret_key);
       return retval;
   }

   int main(void)
   {
       constexpr auto x = uuid();
       constexpr auto y = uuid("frogs");
   }
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals