package handshake
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"fmt"
"io"
"golang.org/x/crypto/hkdf"
)
type TokenProtectorKey [32 ]byte
const tokenNonceSize = 32
type tokenProtector struct {
key TokenProtectorKey
}
func newTokenProtector(key TokenProtectorKey ) *tokenProtector {
return &tokenProtector {key : key }
}
func (s *tokenProtector ) NewToken (data []byte ) ([]byte , error ) {
var nonce [tokenNonceSize ]byte
if _ , err := rand .Read (nonce [:]); err != nil {
return nil , err
}
aead , aeadNonce , err := s .createAEAD (nonce [:])
if err != nil {
return nil , err
}
return append (nonce [:], aead .Seal (nil , aeadNonce , data , nil )...), nil
}
func (s *tokenProtector ) DecodeToken (p []byte ) ([]byte , error ) {
if len (p ) < tokenNonceSize {
return nil , fmt .Errorf ("token too short: %d" , len (p ))
}
nonce := p [:tokenNonceSize ]
aead , aeadNonce , err := s .createAEAD (nonce )
if err != nil {
return nil , err
}
return aead .Open (nil , aeadNonce , p [tokenNonceSize :], nil )
}
func (s *tokenProtector ) createAEAD (nonce []byte ) (cipher .AEAD , []byte , error ) {
h := hkdf .New (sha256 .New , s .key [:], nonce , []byte ("quic-go token source" ))
key := make ([]byte , 32 )
if _ , err := io .ReadFull (h , key ); err != nil {
return nil , nil , err
}
aeadNonce := make ([]byte , 12 )
if _ , err := io .ReadFull (h , aeadNonce ); err != nil {
return nil , nil , err
}
c , err := aes .NewCipher (key )
if err != nil {
return nil , nil , err
}
aead , err := cipher .NewGCM (c )
if err != nil {
return nil , nil , err
}
return aead , aeadNonce , nil
}
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 .