forked from quic-go/quic-go
add a method to generate a client nonce (NONC)
This commit is contained in:
@@ -2,8 +2,11 @@ package handshake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
@@ -23,6 +26,10 @@ type cryptoSetupClient struct {
|
||||
var _ crypto.AEAD = &cryptoSetupClient{}
|
||||
var _ CryptoSetup = &cryptoSetupClient{}
|
||||
|
||||
var (
|
||||
errNoObitForClientNonce = errors.New("No OBIT for client nonce available")
|
||||
)
|
||||
|
||||
// NewCryptoSetupClient creates a new CryptoSetup instance for a client
|
||||
func NewCryptoSetupClient(
|
||||
connID protocol.ConnectionID,
|
||||
@@ -114,3 +121,21 @@ func (h *cryptoSetupClient) sendInchoateCHLO() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) generateClientNonce() ([]byte, error) {
|
||||
nonce := make([]byte, 32)
|
||||
binary.BigEndian.PutUint32(nonce, uint32(time.Now().Unix()))
|
||||
|
||||
if len(h.serverConfig.obit) != 8 {
|
||||
return nil, errNoObitForClientNonce
|
||||
}
|
||||
|
||||
copy(nonce[4:12], h.serverConfig.obit)
|
||||
|
||||
_, err := rand.Read(nonce[12:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nonce, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package handshake
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
@@ -10,8 +13,10 @@ var _ = Describe("Crypto setup", func() {
|
||||
var cs cryptoSetupClient
|
||||
|
||||
BeforeEach(func() {
|
||||
scfg := serverConfigClient{}
|
||||
cs = cryptoSetupClient{
|
||||
cryptoStream: &mockStream{},
|
||||
serverConfig: &scfg,
|
||||
version: protocol.Version36,
|
||||
}
|
||||
})
|
||||
@@ -30,4 +35,34 @@ var _ = Describe("Crypto setup", func() {
|
||||
Expect(cs.cryptoStream.(*mockStream).dataWritten.Len()).To(BeNumerically(">", protocol.ClientHelloMinimumSize))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Client Nonce generation", func() {
|
||||
BeforeEach(func() {
|
||||
cs.serverConfig.obit = []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}
|
||||
})
|
||||
|
||||
It("generates a client nonce", func() {
|
||||
now := time.Now()
|
||||
nonce, err := cs.generateClientNonce()
|
||||
Expect(nonce).To(HaveLen(32))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(time.Unix(int64(binary.BigEndian.Uint32(nonce[0:4])), 0)).To(BeTemporally("~", now, 1*time.Second))
|
||||
Expect(nonce[4:12]).To(Equal(cs.serverConfig.obit))
|
||||
})
|
||||
|
||||
It("uses random values for the last 20 bytes", func() {
|
||||
nonce1, err := cs.generateClientNonce()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
nonce2, err := cs.generateClientNonce()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(nonce1[4:12]).To(Equal(nonce2[4:12]))
|
||||
Expect(nonce1[12:]).ToNot(Equal(nonce2[12:]))
|
||||
})
|
||||
|
||||
It("errors if no OBIT value is available", func() {
|
||||
cs.serverConfig.obit = []byte{}
|
||||
_, err := cs.generateClientNonce()
|
||||
Expect(err).To(MatchError(errNoObitForClientNonce))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user