// Copyright 2024 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package ecdsaimport ()// hmacDRBG is an SP 800-90A Rev. 1 HMAC_DRBG.//// It is only intended to be used to generate ECDSA nonces. Since it will be// instantiated ex-novo for each signature, its Generate function will only be// invoked once or twice (only for P-256, with probability 2⁻³²).//// Per Table 2, it has a reseed interval of 2^48 requests, and a maximum request// size of 2^19 bits (2^16 bytes, 64 KiB).type hmacDRBG struct { newHMAC func(key []byte) *hmac.HMAC hK *hmac.HMAC V []byte reseedCounter uint64}const ( reseedInterval = 1 << 48 maxRequestSize = (1 << 19) / 8)// plainPersonalizationString is used by HMAC_DRBG as-is.type plainPersonalizationString []bytefunc (plainPersonalizationString) () {}// Each entry in blockAlignedPersonalizationString is written to the HMAC at a// block boundary, as specified in draft-irtf-cfrg-det-sigs-with-noise-04,// Section 4.type blockAlignedPersonalizationString [][]bytefunc (blockAlignedPersonalizationString) () {}type personalizationString interface { isPersonalizationString()}func newDRBG[ fips140.Hash]( func() , , []byte, personalizationString) *hmacDRBG {// HMAC_DRBG_Instantiate_algorithm, per Section 10.1.2.3.fips140.RecordApproved() := &hmacDRBG{newHMAC: func( []byte) *hmac.HMAC {returnhmac.New(, ) }, } := ().Size()// K = 0x00 0x00 0x00 ... 0x00 := make([]byte, )// V = 0x01 0x01 0x01 ... 0x01 .V = bytes.Repeat([]byte{0x01}, )// HMAC_DRBG_Update, per Section 10.1.2.2. // K = HMAC (K, V || 0x00 || provided_data) := hmac.New(, ) .Write(.V) .Write([]byte{0x00}) .Write() .Write()switch s := .(type) {caseplainPersonalizationString: .Write()caseblockAlignedPersonalizationString: := len(.V) + 1 + len() + len()for , := range {pad000(, ) .Write() = len() } } = .Sum([:0])// V = HMAC (K, V) = hmac.New(, ) .Write(.V) .V = .Sum(.V[:0])// K = HMAC (K, V || 0x01 || provided_data). .Reset() .Write(.V) .Write([]byte{0x01}) .Write() .Write()switch s := .(type) {caseplainPersonalizationString: .Write()caseblockAlignedPersonalizationString: := len(.V) + 1 + len() + len()for , := range {pad000(, ) .Write() = len() } } = .Sum([:0])// V = HMAC (K, V) = hmac.New(, ) .Write(.V) .V = .Sum(.V[:0]) .hK = .reseedCounter = 1return}func pad000( *hmac.HMAC, int) { := .BlockSize()if := % ; != 0 { .Write(make([]byte, -)) }}// Generate produces at most maxRequestSize bytes of random data in out.func ( *hmacDRBG) ( []byte) {// HMAC_DRBG_Generate_algorithm, per Section 10.1.2.5.fips140.RecordApproved()iflen() > maxRequestSize {panic("ecdsa: internal error: request size exceeds maximum") }if .reseedCounter > reseedInterval {panic("ecdsa: reseed interval exceeded") } := 0for < len() {// V = HMAC_K(V) // T = T || V .hK.Reset() .hK.Write(.V) .V = .hK.Sum(.V[:0]) += copy([:], .V) }// Note that if this function shows up on ECDSA-level profiles, this can be // optimized in the common case by deferring the rest to the next Generate // call, which will never come in nearly all cases.// HMAC_DRBG_Update, per Section 10.1.2.2, without provided_data. // K = HMAC (K, V || 0x00) .hK.Reset() .hK.Write(.V) .hK.Write([]byte{0x00}) := .hK.Sum(nil)// V = HMAC (K, V) .hK = .newHMAC() .hK.Write(.V) .V = .hK.Sum(.V[:0]) .reseedCounter++}
The pages are generated with Goldsv0.7.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.