mirror of https://github.com/portainer/portainer
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
|
package crypto
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"errors"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
type Nonce struct {
|
||
|
val []byte
|
||
|
}
|
||
|
|
||
|
func NewNonce(size int) *Nonce {
|
||
|
return &Nonce{val: make([]byte, size)}
|
||
|
}
|
||
|
|
||
|
// NewRandomNonce generates a new initial nonce with the lower byte set to a random value
|
||
|
// This ensures there are plenty of nonce values availble before rolling over
|
||
|
// Based on ideas from the Secure Programming Cookbook for C and C++ by John Viega, Matt Messier
|
||
|
// https://www.oreilly.com/library/view/secure-programming-cookbook/0596003943/ch04s09.html
|
||
|
func NewRandomNonce(size int) (*Nonce, error) {
|
||
|
randomBytes := 1
|
||
|
if size <= randomBytes {
|
||
|
return nil, errors.New("nonce size must be greater than the number of random bytes")
|
||
|
}
|
||
|
|
||
|
randomPart := make([]byte, randomBytes)
|
||
|
if _, err := rand.Read(randomPart); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
zeroPart := make([]byte, size-randomBytes)
|
||
|
nonceVal := append(randomPart, zeroPart...)
|
||
|
return &Nonce{val: nonceVal}, nil
|
||
|
}
|
||
|
|
||
|
func (n *Nonce) Read(stream io.Reader) error {
|
||
|
_, err := io.ReadFull(stream, n.val)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (n *Nonce) Value() []byte {
|
||
|
return n.val
|
||
|
}
|
||
|
|
||
|
func (n *Nonce) Increment() error {
|
||
|
// Start incrementing from the least significant byte
|
||
|
for i := len(n.val) - 1; i >= 0; i-- {
|
||
|
// Increment the current byte
|
||
|
n.val[i]++
|
||
|
|
||
|
// Check for overflow
|
||
|
if n.val[i] != 0 {
|
||
|
// No overflow, nonce is successfully incremented
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we reach here, it means the nonce has overflowed
|
||
|
return errors.New("nonce overflow")
|
||
|
}
|