首頁 > 後端開發 > Golang > 使用 Go 透過自訂 io.Reader 確定性產生 RSA 私鑰

使用 Go 透過自訂 io.Reader 確定性產生 RSA 私鑰

WBOY
發布: 2024-02-09 14:12:10
轉載
405 人瀏覽過

使用 Go 通过自定义 io.Reader 确定性生成 RSA 私钥

php小編草將為大家介紹如何使用Go語言透過自訂io.Reader介面來決定性產生RSA私鑰。 RSA是一種非對稱加密演算法,常用於資料加密和數位簽章。在產生RSA私鑰時,通常需要從隨機來源取得隨機數,但有時我們需要根據特定的規則產生確定性的私鑰。本文將詳細說明如何實作自訂的io.Reader接口,並使用此介面產生確定性的RSA私鑰。透過閱讀本文,您將掌握這項有用的技巧,為您的加密應用程式提供更多靈活性和可控性。

問題內容

出於可能最好不回答的原因,我需要產生無限的 rsa 公鑰/私鑰。請注意,這沒有用於任何高度安全的事情,所以請不要告訴我不要這樣做,是的,我知道它並不理想。我所說的「無限」是指我需要其中未知數量(數十億到數萬億),並且在使用之前創建它們是不可能的。

由於這會消耗無限的空間並需要無限的時間來生成,因此我需要在運行時執行此操作。

但是,對於給定的輸入,我還需要具有相同的金鑰對。這意味著我需要根據輸入確定性地重新建立 rsa 金鑰。

我使用 go,通常您使用以下命令建立金鑰,

k, err := rsa.generatekey(rand.reader, 2048)
登入後複製

當然,問題是 rand.reader 是由 crypto/rand 提供的,因此無法為其提供種子。

我認為可以提供我自己的閱讀器實現來實現我的目標。我查看了generatekey 的源代碼,注意到它正在尋找素數,因此我實現了自己的閱讀器,這樣我就可以控制返回的“隨機”素數,從而允許我在需要時生成相同的密鑰,

type reader struct {
    data   []byte
    sum    int
    primes []int
}

func newreader(toread string) *reader {
    primes := sieveoferatosthenes(10_000_000)
    return &reader{[]byte(toread), 0, primes}
}

func (r *reader) read(p []byte) (n int, err error) {
    r.sum = r.sum + 1

    if r.sum >= 100_000 {
        return r.primes[rand.intn(len(r.primes))], io.eof
    }

    return r.primes[rand.intn(len(r.primes))], nil
}

func sieveoferatosthenes(n int) (primes []int) {
    b := make([]bool, n)
    for i := 2; i < n; i++ {
        if b[i] == true {
            continue
        }
        primes = append(primes, i)
        for k := i * i; k < n; k += i {
            b[k] = true
        }
    }
    return
}
登入後複製

然後我可以像這樣呼叫產生金鑰

k, err := rsa.GenerateKey(NewReader(""), 2048)
登入後複製

它可以編譯,但由於零指標而在運行時崩潰。我對 go 相當滿意,但 rsa 的實現超出了我的理解。尋找更好的方法來實現這一目標,或尋找我需要做的事情來讓我的讀者工作。

請注意,我在這裡唯一的硬性要求是能夠為給定的輸入產生相同的金鑰,並使用 rsa.generatekey 或相容替換。輸入實際上可以是任何東西,只要我得到與輸出相同的密鑰即可。

這是一個go playground 鏈接,展示了我目前所在的位置https://go.dev/play/p/jd1naopr5ad

解決方法

##read 方法未執行預期操作。它不會用隨機位元組填滿輸入 p 位元組切片。如果您查看 crypto/rand.read 方法的 unix 實現,它將輸入位元組切片傳遞給另一個讀取器。所以基本上你需要用隨機數字填滿位元組片。例如:

這是遊樂場的

連結

更新

正如erwin 在回答中提到的,有一個名為

maybereadrand 的函數,它有50% 的機會從rand 讀取器讀取1 個位元組,從而使該函數具有不確定性。但是您可以透過在 read 方法中新增 if 語句來解決:如果輸入切片的長度為 1,請忽略所有內容並返回。否則,向輸入切片提供質數:

func (r *Reader) Read(p []byte) (n int, err error) {
    i := 0
    b := p

    if len(p) == 1 {
        println("maybeReadRand")
        return 1, nil
    }

    for i < len(b) {
        if len(b) < 4 {
            b[0] = 7
            b = b[1:]
        } else {
            binary.LittleEndian.PutUint32(b, uint32(r.primes[r.i]))
            r.i++
            b = b[4:]
        }
    }

    return len(p), nil
}
登入後複製
在此

片段中,我建立了 2 個金鑰,而且它們都是相等的。

以上是使用 Go 透過自訂 io.Reader 確定性產生 RSA 私鑰的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板