No se conoce ninguna propiedad de los primeros / últimos / medios / whatev 60 bits de una salida SHA-256 que los haga más / menos "aleatorios" que los últimos / whatev / middle / primeros 60 bits. En otras palabras, podrías tomar los primeros 60 bits, y eso será lo mejor que puedas obtener.
Con una generación tan aleatoria, puede esperar que aparezcan las primeras colisiones después de que se hayan acumulado más de mil millones (2 30 ). Incluso si obtienes tu primera colisión en ese punto, las colisiones seguirán siendo un evento raro. Con las ID de 60 bits, cuando tenga, digamos, 2 35 de ellas (más de treinta mil millones), solo una de cada 2 25 de las nuevas ID colisionará uno existente (por lo que esto aún sucedería menos de una vez en 30 millones de casos). Si tiene una base de datos y puede tolerar la colisión ocasional pero bastante rara, entonces el camino a seguir es la generación aleatoria de la ID de 60 bits.
(O, dicho de otro modo, si tiene colisiones con frecuencia, esto significa que ya ha reunido una gran cantidad de ID y su base de datos central debe tener proporciones bíblicas).
Si desea más singularidad que eso, entonces necesita algún tipo de generador de ID central. Por ejemplo, hay un servidor central que puede ser interrogado y devuelve el siguiente valor de un contador. El servidor siempre aumenta el valor del contador después de ser interrogado, por lo que nunca devuelve dos veces el mismo valor. El servidor no se quedará sin enteros de 60 bits en mucho tiempo, porque, seamos sinceros, 2 60 sigue siendo enorme.
Ahora viene la parte difícil, que es de la que no hablaste: ¿deben ser impredecibles las ID? Ésta no es una pregunta fácil; Depende de lo que hagas con ellos y, básicamente, todo en tu sistema. Si necesita ID impredecibles, entonces un contador central no funcionará, porque todos pueden obtener un valor de ID y predecir el siguiente con el 100% de precisión. La solución habitual, en ese caso, sería tener un contador, pero cifrar los valores sucesivos con un cifrado de bloque cuyo tamaño de bloque es idéntico al del ID. Aquí necesitaría un cifrado de bloque con bloques de 60 bits; esto se puede construir a partir de un cifrado de bloque con bloques ligeramente más grandes, por ejemplo. 3DES (bloques de 64 bits). Sin embargo, esto tiene sentido solo en el contexto de un generador de ID central.
Si debe permitir la generación de ID desde varias máquinas "cliente" sin que hablen juntos o con algún sistema central, entonces tendrá que confiar en la aleatoriedad y tolerar las pocas colisiones ocasionales (que será bastante raro durante mucho tiempo) ). Si necesita imprevisibilidad, utilice un PRNG criptográficamente seguro . Dependiendo de su sistema operativo y marco de programación, esto puede llamarse /dev/urandom
(sistemas Linux / Solaris / * BSD), CryptGenRandom()
(Windows C / C ++), java.security.SecureRandom
(Java), System.Security.Cryptography.RNGCryptoServiceProvider
(.NET) ... ¿Es posible que el sistema de generación de UUID inherente de su entorno de programación local se base en un PRNG criptográficamente seguro (por lo que el hashing de un UUID con SHA-256 estaría bien, incluso por imprevisibilidad), pero ¿Por qué arriesgarse? Solo usa un PRNG fuerte directamente.