package ecdsa
import (
"bytes"
"crypto/internal/fips140"
"crypto/internal/fips140/hmac"
"hash"
)
type hmacDRBG struct {
newHMAC func (key []byte ) *hmac .HMAC
hK *hmac .HMAC
V []byte
reseedCounter uint64
}
const (
reseedInterval = 1 << 48
maxRequestSize = (1 << 19 ) / 8
)
type plainPersonalizationString []byte
func (plainPersonalizationString ) isPersonalizationString () {}
type blockAlignedPersonalizationString [][]byte
func (blockAlignedPersonalizationString ) isPersonalizationString () {}
type personalizationString interface {
isPersonalizationString ()
}
func newDRBG [H hash .Hash ](hash func () H , entropy , nonce []byte , s personalizationString ) *hmacDRBG {
fips140 .RecordApproved ()
d := &hmacDRBG {
newHMAC : func (key []byte ) *hmac .HMAC {
return hmac .New (hash , key )
},
}
size := hash ().Size ()
K := make ([]byte , size )
d .V = bytes .Repeat ([]byte {0x01 }, size )
h := hmac .New (hash , K )
h .Write (d .V )
h .Write ([]byte {0x00 })
h .Write (entropy )
h .Write (nonce )
switch s := s .(type ) {
case plainPersonalizationString :
h .Write (s )
case blockAlignedPersonalizationString :
l := len (d .V ) + 1 + len (entropy ) + len (nonce )
for _ , b := range s {
pad000 (h , l )
h .Write (b )
l = len (b )
}
}
K = h .Sum (K [:0 ])
h = hmac .New (hash , K )
h .Write (d .V )
d .V = h .Sum (d .V [:0 ])
h .Reset ()
h .Write (d .V )
h .Write ([]byte {0x01 })
h .Write (entropy )
h .Write (nonce )
switch s := s .(type ) {
case plainPersonalizationString :
h .Write (s )
case blockAlignedPersonalizationString :
l := len (d .V ) + 1 + len (entropy ) + len (nonce )
for _ , b := range s {
pad000 (h , l )
h .Write (b )
l = len (b )
}
}
K = h .Sum (K [:0 ])
h = hmac .New (hash , K )
h .Write (d .V )
d .V = h .Sum (d .V [:0 ])
d .hK = h
d .reseedCounter = 1
return d
}
func TestingOnlyNewDRBG [H hash .Hash ](hash func () H , entropy , nonce []byte , s []byte ) *hmacDRBG {
return newDRBG (hash , entropy , nonce , plainPersonalizationString (s ))
}
func pad000 (h *hmac .HMAC , writtenSoFar int ) {
blockSize := h .BlockSize ()
if rem := writtenSoFar % blockSize ; rem != 0 {
h .Write (make ([]byte , blockSize -rem ))
}
}
func (d *hmacDRBG ) Generate (out []byte ) {
fips140 .RecordApproved ()
if len (out ) > maxRequestSize {
panic ("ecdsa: internal error: request size exceeds maximum" )
}
if d .reseedCounter > reseedInterval {
panic ("ecdsa: reseed interval exceeded" )
}
tlen := 0
for tlen < len (out ) {
d .hK .Reset ()
d .hK .Write (d .V )
d .V = d .hK .Sum (d .V [:0 ])
tlen += copy (out [tlen :], d .V )
}
d .hK .Reset ()
d .hK .Write (d .V )
d .hK .Write ([]byte {0x00 })
K := d .hK .Sum (nil )
d .hK = d .newHMAC (K )
d .hK .Write (d .V )
d .V = d .hK .Sum (d .V [:0 ])
d .reseedCounter ++
}
The pages are generated with Golds v0.8.4 . (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 .