diff --git a/Dependencies.md b/Dependencies.md index c0b4167..f9f32a9 100644 --- a/Dependencies.md +++ b/Dependencies.md @@ -33,14 +33,14 @@ We use sha3 to hash authentication tokens. It is not in the crypto standard libr --- -# keybd_event +# sendkeys -In order to avoid coding key press simulation for every major platform, we use [keybd_event](https://github.com/micmonay/keybd_event). This is a cross-platform library that uses the OS's native key press simulation. +In order to avoid coding key press simulation for every major platform, we use [sendkeys](https://github.com/yunginnanet/sendkeys). This is a cross-platform library that uses the OS's native key press simulation using [keybd_event](https://github.com/micmonay/keybd_event) ---- keybd_event import string +--- sendkeys import string - "github.com/micmonay/keybd_event" + "github.com/EgosOwn/sendkeys" --- diff --git a/ReadMe.md b/ReadMe.md index dfbad5e..7f0cf04 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -50,6 +50,7 @@ First, we call --- entrypoint func main(){ + auth.ProvisionToken() server.StartServer() } @@ -61,6 +62,7 @@ First, we call import( "keyboard.voidnet.tech/server" + "keyboard.voidnet.tech/auth" ) diff --git a/Server.md b/Server.md index 13c3673..6b15d6d 100644 --- a/Server.md +++ b/Server.md @@ -36,7 +36,7 @@ if unixSocketPathExists { --- start websocket server func clientConnected(w http.ResponseWriter, r *http.Request) { - kb, err := keybd_event.NewKeyBonding() + keyboard, err := sendkeys.NewKBWrapWithOptions(sendkeys.Noisy) if err != nil { panic(err) } @@ -47,7 +47,22 @@ func clientConnected(w http.ResponseWriter, r *http.Request) { } defer c.Close() + // get auth token + _, message, err := c.ReadMessage() + if err != nil { + log.Println("read:", err) + return + } + + if auth.CheckAuthToken(string(message)) != nil { + log.Println("invalid token") + return + } + c.WriteMessage(websocket.TextMessage, []byte("authenticated")) + + for { + time.Sleep(25 * time.Millisecond) _, message, err := c.ReadMessage() if err != nil { log.Println("read:", err) @@ -55,16 +70,11 @@ func clientConnected(w http.ResponseWriter, r *http.Request) { } log.Printf("recv: %s", message) message_string := string(message) - for _, char := range message_string { - // make sure that the char is a number - number, err := strconv.Atoi(string(char)) - if err == nil { - kb.SetKeys(number) - } + err = keyboard.Type(message_string) + if err != nil { + log.Println("type:", err) + break } - // sendkeys - //kb.SetKeys(30, 32, 33) - go kb.Launching() } } @@ -80,18 +90,20 @@ func StartServer() { --- -``` + --- /server/server.go package server import( "net" + "time" "os" "net/http" "log" + "keyboard.voidnet.tech/auth" @{gorilla/websocket import string} - @{keybd_event import string} + @{sendkeys import string} ) var listener net.Listener @@ -100,4 +112,5 @@ var upgrader = websocket.Upgrader{} // use default options @{start websocket server} ---- \ No newline at end of file +--- +``` \ No newline at end of file diff --git a/security/Authentication.md b/security/Authentication.md index 9874a6f..5fe795e 100644 --- a/security/Authentication.md +++ b/security/Authentication.md @@ -14,6 +14,8 @@ KDF. --- token generation authToken = uuid.New().String() + uuid.New().String() hashedID := sha3.Sum256([]byte(authToken)) + +fmt.Println("This is your authentication token, it will only be shown once: " + authToken) --- ``` @@ -43,9 +45,12 @@ if authTokenFileIsSet == false { When a client connects, the [websocket server](Server.md) checks the token they send against the stored token. +We use a constant time comparison to avoid timing attacks. + + ``` go ---- check token -func checkAuthToken(token string) error { +--- check token function +func CheckAuthToken(token string) error { @{define authentication token file} // compare sha3_256 hash to hash in file hashedToken := sha3.Sum256([]byte(token)) @@ -60,12 +65,42 @@ func checkAuthToken(token string) error { } --- +--- provision token function +func ProvisionToken() (error){ + @{define authentication token file} + + if _, err := os.Stat(authTokenFile); err == nil { + return nil + } + + @{token generation} + + // create directories if they don't exist + os.MkdirAll(filepath.Dir(authTokenFile), 0700) + fo, err := os.Create(authTokenFile) + defer fo.Close() + if err != nil { + panic(err) + } + fo.Write(hashedID[:]) + return nil +} +--- + +## Putting it all together + +The following is the structure of the authentication package. + +Both CheckAuthToken and ProvisionToken are exported. +The former is used by the server on client connect and the latter is called on startup. + --- /auth/auth.go package auth import( "os" "path/filepath" + "fmt" "errors" "crypto/subtle" @{sha3 import string} @@ -75,25 +110,9 @@ import( var authToken = "" -func provisionToken() (error){ - @{define authentication token file} +@{provision token function} - if _, err := os.Stat(authTokenFile); err == nil { - return nil - } - - @{token generation} - - fo, err := os.Create(authTokenFile) - if err != nil { - panic(err) - } - fo.Write(hashedID[:]) - fo.Close() - return nil -} - -@{check token} +@{check token function} ---