问题描述
我正试图找到一个库,以使用Scrypt算法实现密码哈希(加盐).我的问题类似于在stackoverflow中已经问过的问题( Swift应用程序中的哈希密码)
I am trying to find a library to implement password hashing(with salt) using Scrypt algorithm.My question is similar to one already asked in stackoverflow (Hash password in Swift application)
我发现在swift和Objective c中分别遵循以下两个库,但是从这些库生成的哈希字符串与在服务器上生成的哈希字符串不匹配.
I have found following two libraries in swift and objective c respectively but the hash string generated from these is not matching with the one generated at server.
- Swift-Sodium( https://github.com/jedisct1/swift-sodium )
- NAChloride( https://github.com/gabriel/NAChloride )
- Swift-Sodium (https://github.com/jedisct1/swift-sodium)
- NAChloride (https://github.com/gabriel/NAChloride)
有人可以帮忙找到可用于Swift 3.0 iOS应用程序的带有盐的密码哈希的库.
Can someone please help in finding library which can be used for Swift 3.0 iOS application for password hashing with salt.
谢谢.
此致
Nagraj Wadgire
Nagraj Wadgire
推荐答案
我为自己的问题找到了答案,想到共享是有益的.
I had found answer for my own question, thought of sharing as it will be useful for others.
服务器团队正在使用Scrypt库( https://github.com/wg/scrypt )生成给定密码和盐的哈希字符串.
The server team was using Scrypt library (https://github.com/wg/scrypt) to generate hash string for given password and salt.
分析服务器端库后,我们知道生成的哈希字符串包含以下组件.
After analysing the server side library we came to know that the generated hash string contains following components.
1)加密版本($ s0 $)
1) Scrypt version ($s0$)
2)参数(这是使用以下公式计算的:
2) params (This is calculated using below formula:
字符串参数= Long.toString(log2(N)<<< 16L | r<< 8 | p,16))
String params = Long.toString(log2(N) << 16L | r << 8 | p, 16))
3)盐为base64字符串格式
3) Salt in base64 string format
4)以base64字符串格式生成的派生密钥
4) Generated derived key in base64 string format
最终哈希字符串的格式为 $ s0 $ params $ salt $ key
The Format of final hash string is $s0$params$salt$key
(有关更多信息,请参考此问题,什么是最大长度的scrypt输出?)
(Refer to this question for more information What's the is maximum length of scrypt output?)
正如问题中所述,我在客户端使用了 NAChloride 库来生成哈希字符串.
As stated in the question I have used NAChloride library at the client side to generate hash string.
此类包含以下用于生成哈希字符串的方法:
This class contains below method for generating hash string:
开放类func scrypt(_密码:数据!,盐:数据!,n N:UInt64,r:UInt32,p:UInt32,长度:Int)抛出->数据
open class func scrypt(_ password: Data!, salt: Data!, n N: UInt64, r: UInt32, p: UInt32, length: Int) throws -> Data
在我们的示例中,我们传递了以下值:
In our example we have passed below values:
n = 16,
r = 16,
p = 16,
长度(字节)= 32,
length (bytes) = 32,
盐=数据(字节:[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])
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])
此方法将仅生成数据"格式的派生密钥,因此我认为与在服务器端生成的密钥相比,它是不同的.
This method will generate only derived key in 'Data' format, thus I was thinking that it is different when compared to the key generated at server side.
在生成派生密钥以匹配服务器上生成的哈希字符串的格式(服务器端哈希字符串格式)之后,我不得不编写逻辑.
I had to write a logic after generating the derived key to match to the format of the hash string (server side hash string format) generated at the server.
下面是用Swift 3.0编写的代码,该代码使用 NAChloride 库生成给定密码的哈希字符串,该库在内部使用 Scrypt 哈希算法:
Below is the code written in Swift 3.0 to generate hash string for given password using NAChloride library which internally uses Scrypt hash algorithm:
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
}
您还可以使用以下方法生成随机盐:
You can also generate the random salt using below method:
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<
Password: admin1234<
哈希字符串: $ s0 $ 41010 $ c2FsdERhdGFzYWx0RGF0YXNhbHREYXRhc2FsdERhdGE = $ GrMF1P3VH8YrgUEaOJDVSc4as/XTSWhCbbp4DLie00I =
Hash String: $s0$41010$c2FsdERhdGFzYWx0RGF0YXNhbHREYXRhc2FsdERhdGE=$GrMF1P3VH8YrgUEaOJDVSc4as/XTSWhCbbp4DLie00I=
这篇关于Swift 3.0(iOS)中用于密码哈希的Scrypt哈希算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!