diff options
-rw-r--r-- | challenge/c36.go | 202 | ||||
-rw-r--r-- | cryptopals.go | 2 |
2 files changed, 204 insertions, 0 deletions
diff --git a/challenge/c36.go b/challenge/c36.go new file mode 100644 index 0000000..dc4456b --- /dev/null +++ b/challenge/c36.go @@ -0,0 +1,202 @@ +// Copyright © 2022 siddharth <s@ricketyspace.net> +// SPDX-License-Identifier: ISC + +package challenge + +import ( + "bufio" + "fmt" + "net" + "os" + + "ricketyspace.net/cryptopals/lib" +) + +// Usage: +// +func C36(args []string) { + if len(args) < 2 { + fmt.Println("Usage: cryptopals -c 36 [ client | server ] PORT") + return + } + entity := args[0] + port, err := lib.StrToNum(args[1]) + if err != nil { + fmt.Println("port invalid") + return + } + if port < 12000 { + fmt.Println("port number must be >= 12000") + return + } + + // Register user on the server. + serverRegisterUser := func(server *lib.SRPServer, info []string) error { + if len(info) != 5 { + return fmt.Errorf("regiser user: info valid") + } + n := info[0] + g := info[1] + k := info[2] + ident := info[3] + pass := info[4] + user, err := lib.NewSRPUser(n, g, k, ident, pass) + if err != nil { + return fmt.Errorf("register user: %v", err) + } + if err = server.RegisterUser(user); err != nil { + return fmt.Errorf("register user: %v", err) + } + return nil + } + // Handle connection from a client. + serverHandleConn := func(server *lib.SRPServer, conn net.Conn) { + defer conn.Close() + fmt.Printf("Got connection from %v\n", conn.RemoteAddr()) + + // Read packet from client. + packet, err := bufio.NewReader(conn).ReadString('\n') + if err != nil { + fmt.Printf("Unable to read from client %v\n", + conn.RemoteAddr()) + return + } + + // Remove newline character from packet. + packet = packet[:len(packet)-1] + + parts := lib.StrSplitAt('+', packet) + if len(parts) < 2 { + fmt.Fprintf(conn, "invalid request\n") + return + } + + switch { + case parts[0] == "register": + err = serverRegisterUser(server, parts[1:]) + if err != nil { + fmt.Fprintf(conn, "%v\n", err) + return + } else { + fmt.Fprintf(conn, "OK\n") + } + return + default: + fmt.Fprintf(conn, "invalid action") + return + } + + } + // Start SRP server. + serverSpawn := func() { + server := new(lib.SRPServer) + + p := fmt.Sprintf(":%d", port) + ln, err := net.Listen("tcp", p) + if err != nil { + fmt.Printf("server listen error: %v\n", err) + return + } + for { + fmt.Println("Waiting for connection...") + conn, err := ln.Accept() + if err != nil { + fmt.Printf("server accept error: %v\n", err) + } + go serverHandleConn(server, conn) + } + } + // Register user with server. + clientRegisterUser := func(client *lib.SRPClient, ident string) error { + n := lib.StripSpaceChars( + `ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024 + e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd + 3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec + 6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f + 24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361 + c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552 + bb9ed529077096966d670c354e4abc9804f1746c08ca237327fff + fffffffffffff`) + g := "2" + k := "3" + + // Prompt for password. + fmt.Printf("password> ") + pass, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + return fmt.Errorf("unable to read password: %v", err) + } + + // Create session for user. + client.Session, err = lib.NewSRPClientSession(n, g, k, ident) + if err != nil { + return fmt.Errorf("unable to create session: %v", err) + } + + // Make SRP registration packet. + packet := fmt.Sprintf("%s+%s+%s+%s+%s+%s", "register", + n, g, k, ident, pass) + + // Try to connect to server. + conn, err := net.Dial("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return fmt.Errorf("unable connect to server: %v", err) + } + defer conn.Close() + + // Send packet to server. + _, err = fmt.Fprintf(conn, "%s", packet) + if err != nil { + return fmt.Errorf("unable communicate with server: %v", err) + } + + // Wait and try to get registration ACK from server. + spacket, err := bufio.NewReader(conn).ReadString('\n') + if err != nil { + return fmt.Errorf("server did not respond: %v", err) + } + // Remove newline character. + spacket = spacket[:len(spacket)-1] + if spacket != "OK" { + return fmt.Errorf("server registration failed: %s", spacket) + } + return nil + } + // Start SRP client. + clientSpawn := func() { + client := new(lib.SRPClient) + // Enter repl. + for { + // Read message from stdin. + fmt.Printf("> ") + msg, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + fmt.Printf("read error: %v\n", err) + return + } + // Remove newline character. + msg = msg[:len(msg)-1] + + msg_parts := lib.StrSplitAt(' ', msg) + switch { + case msg_parts[0] == "register" && len(msg_parts) == 2: + err := clientRegisterUser(client, msg_parts[1]) + if err != nil { + fmt.Printf("Registration failed: %v\n", err) + } else { + fmt.Printf("Registered!\n") + } + } + } + } + + // Take action based on entity. + switch { + case entity == "server": + serverSpawn() + case entity == "client": + clientSpawn() + default: + fmt.Println("uknown entity") + } +} diff --git a/cryptopals.go b/cryptopals.go index b9bef80..1c99f22 100644 --- a/cryptopals.go +++ b/cryptopals.go @@ -90,5 +90,7 @@ func main() { challenge.C34(flag.Args()) case 35: challenge.C35(flag.Args()) + case 36: + challenge.C36(flag.Args()) } } |