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())  	}  } | 
