草庐IT

ios - Swift 3.0 (iOS) 中用于密码散列的 Scrypt 散列算法

coder 2023-09-16 原文

我正试图找到一个库来使用 Scrypt 算法实现密码散列(加盐)。 我的问题类似于已经在 stackoverflow ( Hash password in Swift application ) 中提出的问题

我在 swift 和 objective c 中分别找到了以下两个库,但是从这些库生成的哈希字符串与在服务器生成的哈希字符串不匹配。

  1. Swift-钠 ( https://github.com/jedisct1/swift-sodium )
  2. 氯化钠 ( https://github.com/gabriel/NAChloride )

有人可以帮助找到可用于 Swift 3.0 iOS 应用程序的库,以使用 salt 进行密码哈希处理。

谢谢。

问候,

纳格拉吉瓦德吉尔

最佳答案

我找到了我自己问题的答案,想分享一下,因为它对其他人有用。

服务器团队使用 Scrypt 库 ( https://github.com/wg/scrypt ) 为给定的密码和盐生成哈希字符串。

在分析服务器端库后,我们了解到生成的哈希字符串包含以下组件。

1) Scrypt 版本 ($s0$)

2) 参数 (这是使用以下公式计算的:

字符串参数 = Long.toString(log2(N) < 16l="" |="" r="">< 8="" |="" p,="">

3) base64 字符串格式的盐

4) 生成base64字符串格式的派生 key

最终哈希字符串的格式是$s0$params$salt$key

(有关更多信息,请参阅此问题 What's the is maximum length of scrypt output? )

如问题中所述,我在客户端使用了 NAChloride 库来生成哈希字符串。

此类包含以下生成哈希字符串的方法:

打开类 func scrypt(_ password: Data!, salt: Data!, n N: UInt64, r: UInt32, p: UInt32, length: Int) throws -> Data

在我们的示例中,我们传递了以下值:

n=16,

r=16,

p=16,

长度(字节)= 32,

盐 = 数据(字节:[0x73、0x61、0x6c、0x74、0x44、0x61、0x74、0x61、0x73、0x61、0x6c、0x74、0x44、0x61、0x74、0x61、0x73、0x61、0x76c、0 0x44、0x61、0x74、0x61、0x73、0x61、0x6c、0x74、0x44、0x61、0x74、0x61])

此方法将仅生成“数据”格式的派生 key ,因此我认为它与在服务器端生成的 key 相比有所不同。

我必须在生成派生 key 后编写一个逻辑,以匹配在服务器生成的哈希字符串的格式(服务器端哈希字符串格式)。

下面是用 Swift 3.0 编写的代码,使用内部使用 Scrypt 哈希算法的 NAChloride 库为给定密码生成哈希字符串:

    func passwordHashingUsingScrypt(password: String) -> String{
    let N = 16
    let r = 16
    let p = 16

    let term1 = Int(log2(Double(N))) << 16
    let term2 = r << 8
    let paramsDecimal = term1 | term2 | p

    let params = String(format:"%2X", paramsDecimal)
    print(params)

    let message = password.data(using:.utf8)!
    let salt = Data(bytes:[0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61,0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61,0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61,0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])

    let saltBase64String = salt.base64EncodedString()
    print(saltBase64String)

    let hashData = try! NAScrypt.scrypt(message, salt: salt, n: 16, r: 16, p: 16, length: 32)
    let hashBase64String = hashData.base64EncodedString()
    print(hashBase64String)
    let result = saltBase64String+"$"+hashBase64String
    print(result)

    var hashString = String()
    hashString.append("$s0$")
    hashString.append(params)
    hashString.append("$")
    hashString.append(saltBase64String)
    hashString.append("$")
    hashString.append(hashBase64String)
    print(hashString)
    return hashString
}

您还可以使用以下方法生成随机盐:

func randomBytes(numberOfBytes:Int) -> [UInt8] {
    var randomBytes = [UInt8](repeating: 0, count: numberOfBytes) // array to hold randoms bytes
    let result = SecRandomCopyBytes(kSecRandomDefault, numberOfBytes, &randomBytes)
    print(result)
    return randomBytes
}

结果:

密码: admin1234

哈希字符串: $s0$41010$c2FsdERhdGFzYWx0RGF0YXNhbHREYXRhc2FsdERhdGE=$GrMF1P3VH8YrgUEaOJDVSc4as/XTSWhCbbp4DLie00I=

关于ios - Swift 3.0 (iOS) 中用于密码散列的 Scrypt 散列算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45972686/

有关ios - Swift 3.0 (iOS) 中用于密码散列的 Scrypt 散列算法的更多相关文章

  1. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  2. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  3. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  4. ruby - 按值降序排列散列,然后按升序键入 ruby - 2

    我有这样的哈希trial_hash={"key1"=>1000,"key2"=>34,"key3"=>500,"key4"=>500,"key5"=>500,"key6"=>500}我按值降序排列:my_hash=trial_hash.sort_by{|k,v|v}.reverse我现在是这样理解的:[["key1",1000],["key4",500],["key5",500],["key6",500],["key3",500],["key2",34]]但我希望当值相同时按键的升序排序。我该怎么做?例如:上面的散列将以这种方式排序:[["key1",1000],["key3",500

  5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  6. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  7. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  8. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  9. ruby - 如何根据长度将路径数组转换为嵌套数组或散列 - 2

    我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa

  10. Ruby:如何使用带有散列的 'send' 方法调用方法? - 2

    假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而

随机推荐