I would like to generate a UUID string from a random string, so that the same input string generates the same UUID.
I don't care about getting the input string back from the UUID. I need this to deterministically convert keys in a database as part of a migration, so that different clients acting in parallel converge to the same result.
The accepted answer of this post has the answer in Java, I would need the Swift version.
The official way to do this is with a version 5 UUID (RFC 4122 Section 4.3):
4.3 Algorithm for Creating a Name-Based UUID
The version 3 or 5 UUID is meant for generating UUIDs from "names" that are drawn from, and unique within, some "name space".
The process is to hash your string, and then insert that into a UUID. I'm going to carefully follow the spec here, but I'll mark the parts you could ignore and it'll still work correctly.
As matt notes, you can just use a SHA directly if you just need a hash. But if your system actually requires a UUID, this is how you do it.
let namespace = "com.example.mygreatsystem:"
let inputString = "arandomstring"
let fullString = namespace + inputString
import CryptoKit
let hash = Insecure.SHA1.hash(data: Data(fullString.utf8)) // SHA-1 by spec
or
let hash = SHA256.hash(data: Data(fullString.utf8)) // SHA-2 is generally better
var truncatedHash = Array(hash.prefix(16))
truncatedHash[6] &= 0x0F // Clear version field
truncatedHash[6] |= 0x50 // Set version to 5
truncatedHash[8] &= 0x3F // Clear variant field
truncatedHash[8] |= 0x80 // Set variant to DCE 1.1
let uuidString = NSUUID(uuidBytes: truncatedHash).uuidString