2.1 KiB
Keyboard connection authentication
Keyboarding obviously has a ton of sensitive data, so we need to both encrypt and authenticate the connections.
All connections are encrypted using an external TLS proxy (e.g. Caddy) outside the scope of this project, but we perform application level authentication using two randomly generated UUIDv4s in a manner similar to a passphrase. @{token generation}
We hash the token using sha3-256 to avoid accidentally exposing the token to a readonly attacker.
Generating the authentication token
--- token generation
id := uuid.New() + uuid.New()
hashedID := sha3.Sum256([]byte(id))
---
Storing the authentication token
We then store the token in a file, which is set
by the environment variable KEYBOARD_AUTH_TOKEN_FILE
, but defaults to
'XDG_CONFIG_HOME/smartkeyboard/auth-token.' @{defineProvisionTokenFile}
--- store token
if err := os.WriteFile(KEYBOARD_AUTH_TOKEN_FILE, hashedID, 0666); err != nil {
log.Fatal(err)
}
---
Checking authentication
When a client connects, the websocket server checks the token they send against the stored token.
--- check token
func checkAuthToken(token string) error {
hashedToken := sha3.Sum256([]byte(token))
storedToken, err := os.ReadFile(KEYBOARD_AUTH_TOKEN_FILE)
if err != nil {
return err
}
if subtle.ConstantTimeCompare(hashedToken[:], storedToken) != 1 {
return errors.New("invalid token")
}
return nil
}
---
--- /auth/auth.go package main
@{auth imports} @{check token}
--- auth imports
import( //"github.com/google/uuid" //"encoding/base64" "golang.org/x/crypto/sha3" "os" "errors" "crypto/subtle" )
--- defineProvisionTokenFile
provisionTokenFile, keyboardAuthExists := os.Getenv("KEYBOARD_AUTH_TOKEN_FILE")
if keyboardAuthExists == false {
provisionTokenFile = filepath.Join(xdg.ConfigHome, "smartkeyboard", "auth-token")
}
---
--- provisionToken
func provisionToken() (error){
@{defineProvisionTokenFile}
@{token generation}
@{store token}
}
---