我想从一个随机字符串生成一个UUID字符串,这样相同的输入字符串生成相同的UUID。
我不关心从 UUID 取回输入字符串。作为迁移的一部分,我需要它来确定性地转换数据库中的键,以便并行操作的不同客户端收敛到相同的结果。
这篇文章的接受答案有Java的答案,我需要Swift版本。
执行此操作的官方方法是使用版本 5 UUID(RFC 4122 第 4.3 节):
4.3 创建基于名称的 UUID 的算法
版本 3 或 5 UUID 用于从“名称”生成 UUID 取自某些“名称空间”,并且在其中是唯一的。
过程是散列你的字符串,然后将其插入到 UUID 中。我将在这里仔细遵循规范,但我会标记您可以忽略的部分,它仍然可以正常工作。
正如 matt 所说,如果你只需要一个散列,你可以直接使用 SHA。但是,如果您的系统确实需要一个 UUID,这就是您的做法。
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
或
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
我想从一个随机字符串生成一个UUID字符串,这样相同的输入字符串生成相同的UUID。
您描述的是哈希值,而不是 UUID。 UUID中的U代表unique;你每次都会得到不同的。 SHA-1 散列(例如)对于相同的字符串是相同的,对于不同的字符串是不同的。
UUIDKit @Nicolas Bachschmidt 在 Swift 中有完整的 UUID v5 实现。
它还支持 RFC 1808 中的所有命名空间,例如 NameSpace_URL:
import UUIDKit
UUID.v5(name: "http://example.com/index.html", namespace: .url)
因为它遵循规范,所以它使用 SHA-1 并且输出与其他平台实现相匹配,所以上面的行输出与此 python 代码相同的值:
import uuid
uuid.uuid5(uuid.NAMESPACE_URL, 'http://example.com/index.html')