我目前的项目是我在Node.js中的第一个项目(也是使用MongoDB,Mongoose和Express,如果重要的话),并且很容易分心,我在决定如何处理用户身份验证时已经陷入了加密的漏洞。 (此项目不需要其他加密)。
遵循this page上的模式(模式,而不是代码 - 我遇到安装node.bcrypt而不是node-sodium的问题)和also this page我的流程是
新用户通过https提交密码
架构生成盐
架构哈希密码和盐的串联
架构使用用户信息
现在我不知道这是否是我个人的不足,但我在跟踪the libsodium documentation时遇到了麻烦。 node-sodium没有提供任何有关散列的附加信息(尽管它有一个加密示例)。
这是我想用来生成哈希的代码:
let buf = new Buffer(sodium.crypto_pwhash_STRBYTES);
sodium.randombytes_buf(buf, sodium.crypto_pwhash_STRBYTES);
let salt = buf.toString();
let preBuffer = "somePass" + salt;
let passwordBuf = Buffer.from(preBuffer);
let hash = sodium.crypto_pwhash_str(passwordBuf, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
所以问题是两部分。这是一个很好的过程,代码是否合适?
答案 0 :(得分:4)
出于这个原因,我过去曾使用scrypt-for-humans
包。
https://github.com/joepie91/scrypt-for-humans
Scrypt是一个非常安全的哈希库,这个更高级别的包装器让你很难搞砸任何东西。它还专门用于安全散列密码,因此也是正面的:)
答案 1 :(得分:0)
目前,最佳密码哈希算法为Argon 2。 secure-password编写了一个名为Emil Bay的模块。他更多地讨论了加密安全密码散列和最佳实践on this podcast。以下是他对Argon 2所说的内容。
通常,当您布置威胁模型时,从数学角度来看,完美的安全性几乎是不可行的。 (在密码学中,可以称为完美保密,这意味着,即使你拥有一台庞大的宇宙大小的计算机,无论它有多大,你都无法破坏安全性,但这并不是真正的实用性现实世界。)相反,你会去做一些叫做计算保密的事情。这意味着你可以打破这个,但它会花费你太多的钱并花费太多时间。
这些哈希函数的目标是使这些算法暴力破坏如此昂贵,以至于没有必要尝试。在威胁模型中,你知道你不会获得完美的安全性,但你可以让你的对手攻击你这么贵。
Argon 2有两个参数可以使其免受大规模GPU攻击。您可以控制允许函数使用多少内存,并且可以控制进行哈希所需的计算时间。 CPU通常有很多内存但有几个内核。 GPU拥有非常少的内存,但有数千个内核。 Argon 2拨出大量内存,只能在一个GPU上同时执行大约4或8个Argon 2哈希,这使得尝试破解成本太高。在secure-password中,我采用了弗兰克·丹尼斯(Frank Denise)制造的钠的价值,而这种价值是建立在它上面的。它位于交互式服务的范围内,就像网站可以在不减速的情况下创建合理的安全性。要对密码进行哈希处理,您需要大约16或32 Mb的内存,并且可以在Argon 2中控制这些参数。
答案 2 :(得分:-3)
就我个人而言,我已经使用了crypto,而且我现在正在做同样的4个步骤(在检查了几个条件后,7个字符通过,一个符号,一个数字......)。我将使用crypto分享代码。
var inputstream: InputStream?
var outputstream: OutputStream?
var host: CFString?
var port: UInt32?
override func viewDidLoad() {
super.viewDidLoad()
initNetworkCommunication()
}
func initNetworkCommunication(){
host = "192.168.1.187" as CFString
port = 55555
var readstream : Unmanaged<CFReadStream>?
var writestream : Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host!, port!, &readstream, &writestream)
inputstream? = readstream!.takeRetainedValue()
outputstream? = writestream!.takeRetainedValue()
inputstream?.delegate = self as! StreamDelegate
outputstream?.delegate = self as! StreamDelegate
inputstream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputstream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
inputstream?.open()
Status.text = "Input Stream Opened"
outputstream?.open()
Status.text = "Output Stream Opened"
}
func stream(_ aStream: Stream, handleEvent eventCode: Stream.Event) {
switch (eventCode){
case Stream.Event.errorOccurred:
print("Can not connect to the host!")
Status.text = "Cannot connect to: \(host ?? "Null Host" as CFString)"
break
case Stream.Event.endEncountered:
outputstream?.close()
outputstream?.remove(from: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputstream = nil
break
case Stream.Event.hasBytesAvailable:
Status.text = "Recieving data..."
NSLog("HasBytesAvaible")
var buffer = [UInt8](repeating: 0, count: 4096)
if ( aStream == inputstream){
while (inputstream?.hasBytesAvailable)!{
var len = inputstream?.read(&buffer, maxLength: buffer.count)
if(len! > 0){
Status.text = "Collected data..."
var data1 = NSData(bytes: buffer, length: buffer.count)
Status.text = "Converted Data to NSData..."
var str64 = data1.base64EncodedData(options: .lineLength64Characters)
Status.text = "Decode Base64..."
let data: NSData = NSData(base64Encoded: str64 , options: .ignoreUnknownCharacters)!
// turn Decoded String into Data
Status.text = "Turning Base64 data into image..."
let dataImage = UIImage(data: data as Data)
Status.text = "Done"
// pass the data image to image View.:)
Display.image = dataImage
Status.text = "Image Displayed"
}
}
}
break
case Stream.Event.openCompleted:
NSLog("OpenCompleted")
break
case Stream.Event.hasSpaceAvailable:
NSLog("HasSpaceAvailable")
break
default:
print("Unknown event")
}
}
编辑:警告这不是完全安全的方法,因为它可能会出现预测。请参阅下面的评论,解释为什么它不是一个好方法。