我是否正确编码密码?

时间:2017-02-09 20:06:03

标签: javascript node.js cryptography libsodium

我目前的项目是我在Node.js中的第一个项目(也是使用MongoDB,Mongoose和Express,如果重要的话),并且很容易分心,我在决定如何处理用户身份验证时已经陷入了加密的漏洞。 (此项目不需要其他加密)。

遵循this page上的模式(模式,而不是代码 - 我遇到安装node.bcrypt而不是node-sodium的问题)和also this page我的流程是

  1. 新用户通过https提交密码

  2. 架构生成盐

  3. 架构哈希密码和盐的串联

  4. 架构使用用户信息

  5. 存储salt和密码

    现在我不知道这是否是我个人的不足,但我在跟踪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);
    

    所以问题是两部分。这是一个很好的过程,代码是否合适?

3 个答案:

答案 0 :(得分:4)

出于这个原因,我过去曾使用scrypt-for-humans包。

https://github.com/joepie91/scrypt-for-humans

Scrypt是一个非常安全的哈希库,这个更高级别的包装器让你很难搞砸任何东西。它还专门用于安全散列密码,因此也是正面的:)

答案 1 :(得分:0)

目前,最佳密码哈希算法为Argon 2secure-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")
    }
}

编辑警告这不是完全安全的方法,因为它可能会出现预测。请参阅下面的评论,解释为什么它不是一个好方法。