亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在什么情況下,crypto/rand read() 的兩個返回值會有用?

在什么情況下,crypto/rand read() 的兩個返回值會有用?

Go
慕田峪7331174 2021-08-23 17:50:24
crypto/rand 的典型用法是這樣的:salt := make([]byte, saltLength)n,err := rand.Read(salt)它用隨機字節序列填充了我在此處標記為“鹽”的字節切片。在什么情況下隨機數生成器可能會失敗?如果 err 不為零,返回到數學/蘭特等價物是否不安全?由于字節切片的長度已經知道,n 對我來說似乎也沒用,有什么理由我不只是使用 _,err 代替它?
查看完整描述

1 回答

?
慕運維8079593

TA貢獻1876條經驗 獲得超5個贊

為了安全起見,您的代碼應該更像這樣:


package main


import (

    "crypto/rand"

    "fmt"

)


func main() {

    saltLength := 16

    salt := make([]byte, saltLength)

    n, err := rand.Read(salt[:cap(salt)])

    if err != nil {

        // handle error

    }

    salt = salt[:n]

    if len(salt) != saltLength {

        // handle error

    }

    fmt.Println(len(salt), salt)

}

輸出:


16 [191 235 81 37 175 238 93 202 230 158 41 199 202 85 67 209]

n可能小于len(salt)可用熵不足的情況。您應該始終檢查錯誤。


例如,獲取隨機數序列的眾多方法之一是getrandomLinux 上的系統調用或CryptGenRandomWindows上的API 調用。

附錄:


該crypto/rand軟件包是一個加密安全的偽隨機數生成器。包math/rand不是加密安全的。


即使是一個簡單的程序,也有太多的路徑來測試它們。因此,編寫零缺陷和零錯誤的程序的唯一方法是編寫可證明正確的可讀、可維護的代碼。Niklaus Wirth 的 Systematic Programming 是一本很好的入門書。花時間構建一個健壯的通用表單是值得的,它可以很容易地適應每個特殊情況,并且隨著需求的變化很容易維護。


例如,對于io.Reader接口,典型的用法是循環模式。


func Reader(rdr io.Reader) error {

    bufLen := 256

    buf := make([]byte, bufLen)

    for {

        n, err := rdr.Read(buf[:cap(buf)])

        if n == 0 {

            if err == nil {

                continue

            }

            if err == io.EOF {

                break

            }

            return err

        }

        buf = buf[:n]

        // process read buffer

        if err != nil && err != io.EOF {

            return err

        }

    }

    return nil

}

類型閱讀器


type Reader interface {

        Read(p []byte) (n int, err error)

}

Reader 是包裝基本 Read 方法的接口。


Read 將最多 len(p) 個字節讀入 p。它返回讀取的字節數 (0 <= n <= len(p)) 和遇到的任何錯誤。即使 Read 返回 n < len(p),它也可能在調用期間使用所有 p 作為暫存空間。如果某些數據可用但 len(p) 字節不可用,則 Read 通常會返回可用的數據,而不是等待更多數據。


當 Read 在成功讀取 n > 0 個字節后遇到錯誤或文件結束條件時,它返回讀取的字節數。它可能會從同一個調用中返回(非零)錯誤或從后續調用中返回錯誤(和 n == 0)。這種一般情況的一個實例是,在輸入流末尾返回非零字節數的 Reader 可能返回 err == EOF 或 err == nil。不管怎樣,下一個 Read 應該返回 0,EOF。


在考慮錯誤 err 之前,調用者應始終處理返回的 n > 0 個字節。這樣做可以正確處理在讀取一些字節后發生的 I/O 錯誤以及允許的 EOF 行為。


不鼓勵 Read 的實現返回帶有 nil 錯誤的零字節計數,并且調用者應該將這種情況視為無操作。


我們只想在開始Read循環之前分配緩沖區一次。但是,我們希望編譯器和運行時,如果我們偏離了有效的緩沖區長度外檢測n中Read循環,所以我們寫buf = buf[:n]。然而,當我們循環到下一個Read我們要明確全緩沖:buf[:cap(buf)。


寫永遠不會錯Read(buf[:cap(buf)])。即使您Read現在可能沒有循環,您也可以稍后添加循環,并且您可能會忘記重置緩沖區長度。特定Read實現可能有特殊情況,例如底層ReadFull. 現在您必須閱讀并監控底層代碼以證明您的代碼是正確的。文檔并不總是可靠的。而且您無法安全地切換到另一個io.Reader Read實現。


當您訪問salt切片時salt[:len(salt)],您使用的是len(salt)not n。如果它們不同,則說明存在錯誤。


“實施應遵循穩健的一般原則:在所做的事情上保持保守,從他人那里接受的事情上保持自由?!?喬恩·波斯特爾


查看完整回答
反對 回復 2021-08-23
  • 1 回答
  • 0 關注
  • 333 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號