go-ricochet/authhandler.go

58 lines
1.7 KiB
Go

package goricochet
import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"io"
)
// AuthenticationHandler manages the stae required for the AuthHiddenService
// authentication scheme for ricochet.
type AuthenticationHandler struct {
clientCookie [16]byte
serverCookie [16]byte
}
// AddClientCookie adds a client cookie to the state.
func (ah *AuthenticationHandler) AddClientCookie(cookie []byte) {
copy(ah.clientCookie[:], cookie[:16])
}
// AddServerCookie adds a server cookie to the state.
func (ah *AuthenticationHandler) AddServerCookie(cookie []byte) {
copy(ah.serverCookie[:], cookie[:16])
}
// GenRandom generates a random 16byte cookie string.
func (ah *AuthenticationHandler) GenRandom() [16]byte {
var cookie [16]byte
io.ReadFull(rand.Reader, cookie[:])
return cookie
}
// GenClientCookie generates and adds a client cookie to the state.
func (ah *AuthenticationHandler) GenClientCookie() [16]byte {
ah.clientCookie = ah.GenRandom()
return ah.clientCookie
}
// GenServerCookie generates and adds a server cookie to the state.
func (ah *AuthenticationHandler) GenServerCookie() [16]byte {
ah.serverCookie = ah.GenRandom()
return ah.serverCookie
}
// GenChallenge constructs the challenge parameter for the AuthHiddenService session.
// The challenge is the a Sha256HMAC(clientHostname+serverHostname, key=clientCookie+serverCookie)
func (ah *AuthenticationHandler) GenChallenge(clientHostname string, serverHostname string) []byte {
key := make([]byte, 32)
copy(key[0:16], ah.clientCookie[:])
copy(key[16:], ah.serverCookie[:])
value := []byte(clientHostname + serverHostname)
mac := hmac.New(sha256.New, key)
mac.Write(value)
hmac := mac.Sum(nil)
return hmac
}