diff options
| author | siddharth <s@ricketyspace.net> | 2022-02-20 17:10:59 -0500 | 
|---|---|---|
| committer | siddharth <s@ricketyspace.net> | 2022-02-20 17:10:59 -0500 | 
| commit | d9c9edb96c2cd6e784a073894d65a843681006aa (patch) | |
| tree | 5595c3586829428fa97658f26e6af4b4d0fdeca7 | |
| parent | 857d1ba18f3a458374e462db2a7ae3cb39e3e5db (diff) | |
challenge: do challenge 35 - part ii
| -rw-r--r-- | challenge/c35.go | 340 | 
1 files changed, 339 insertions, 1 deletions
| diff --git a/challenge/c35.go b/challenge/c35.go index cb2d166..b266e47 100644 --- a/challenge/c35.go +++ b/challenge/c35.go @@ -15,10 +15,15 @@ import (  func C35(args []string) {  	if len(args) < 2 { -		fmt.Println("Usage: cryptopals -c 35 ENTITY PORT") +		fmt.Println("Usage: cryptopals -c 35 ENTITY PORT [S-PORT] [G]")  		return  	}  	entity := args[0] +	if entity == "attacker" && len(args) != 4 { +		fmt.Println("Usage: cryptopals -c 35 attacker PORT S-PORT G") +		fmt.Println("\n       G should be '1', 'p' or 'p-1'") +		return +	}  	port, err := lib.StrToNum(args[1])  	if err != nil {  		fmt.Println("Port invalid") @@ -28,6 +33,24 @@ func C35(args []string) {  		fmt.Println("Error: port number must be >= 12000")  		return  	} +	sport := 0 +	gtype := "" +	if entity == "attacker" { +		sport, err = lib.StrToNum(args[2]) +		if err != nil { +			fmt.Println("S-Port invalid") +			return +		} +		if sport < 12000 { +			fmt.Println("Error: port number must be >= 12000") +			return +		} +		gtype = lib.StripSpaceChars(args[3]) +		if gtype != "1" && gtype != "p" && gtype != "p-1" { +			fmt.Println("Error: G is invalid") +			return +		} +	}  	// Cipher functions.  	// @@ -325,6 +348,257 @@ func C35(args []string) {  			fmt.Printf("%s\n", smsg)  		}  	} +	// Attacker handling. +	// +	// Slurp DH params from client. +	attackerSlurpDHParams := func(conn net.Conn) ([]string, error) { +		// Read DH packet from client. +		packet, err := bufio.NewReader(conn).ReadString('\n') +		if err != nil { +			return []string{}, err +		} +		// Remove newline character from packet. +		packet = packet[:len(packet)-1] + +		// Try to read DH paramters from packet. +		params := lib.StrSplitAt('+', packet) +		if len(params) != 2 { +			return []string{}, lib.CPError{"DH paramters invalid"} +		} + +		// Try make a DH from params. +		_, ok := lib.NewDH(params[0], params[1]) +		if !ok { +			return []string{}, lib.CPError{"DH initialization failed"} +		} +		return params, nil +	} +	// Return DH param `g` based on gtype. +	attackerGetDHG := func(p string) (string, *big.Int, bool) { +		if gtype == "1" { +			return "1", new(big.Int).SetInt64(1), true +		} + +		// Convert string `p` to big.Int. +		pi, ok := new(big.Int).SetString(p, 16) +		if !ok { +			return "", nil, false +		} + +		if gtype == "p" { +			return p, pi, true +		} + +		if gtype != "p-1" { +			return "", nil, false +		} + +		// gtype is "p-1"; make it. +		pi.Sub(pi, new(big.Int).SetInt64(1)) +		return fmt.Sprintf("%x", pi), pi, true +	} +	// Try to make a connection with the server using DH and +	// return serve'rs DH public key. +	attackerSecureConnToServer := func(p, g string) (net.Conn, *big.Int, error) { +		// Try to connect to server. +		addr := fmt.Sprintf(":%d", sport) +		conn, err := net.Dial("tcp", addr) +		if err != nil { +			return conn, nil, err +		} + +		// Initialize DH. +		dh, ok := lib.NewDH(p, g) +		if !ok { +			return conn, nil, lib.CPError{"DH initialization failed"} +		} + +		// Make DH packet: p+g +		packet := fmt.Sprintf("%v+%v", p, g) + +		// Sent DH packet to server. +		fmt.Fprintf(conn, "%s\n", packet) + +		// Wait and try to get ACK from server. +		spacket, err := bufio.NewReader(conn).ReadString('\n') +		if err != nil { +			return conn, nil, err +		} +		// Remove newline character. +		spacket = spacket[:len(spacket)-1] +		if spacket != "ACK" { +			return conn, nil, lib.CPError{"ACK failed"} +		} + +		// Send DH public key to server. +		fmt.Fprintf(conn, "%v\n", dh.Pub()) + +		// Get server's DH public key. +		spacket, err = bufio.NewReader(conn).ReadString('\n') +		if err != nil { +			return conn, nil, err +		} +		// Remove newline character. +		spacket = spacket[:len(spacket)-1] + +		// Parse server's DH public key. +		sPub, ok := new(big.Int).SetString(lib.StripSpaceChars(spacket), 10) +		if !ok { +			return conn, nil, lib.CPError{"Server's DH key invalid"} +		} + +		// Return server connection and server's DH public key. +		return conn, dh.SharedSecret(sPub), nil +	} +	// Handle connection from a client. +	attackerHandleConn := func(conn net.Conn) { +		defer conn.Close() + +		// Read DH params from client. +		dhParams, err := attackerSlurpDHParams(conn) +		if err != nil { +			fmt.Printf("Error: %v\n", err) +			return +		} + +		// DH params for the server. +		p := dhParams[0] +		g, gi, ok := attackerGetDHG(p) +		if !ok { +			fmt.Println("Error: Unable to get DH param 'g'") +			return +		} +		sconn, skey, err := attackerSecureConnToServer(p, g) +		if err != nil { +			fmt.Printf("Error: %v\n", err) +			return +		} +		defer sconn.Close() + +		// Send ACK to client. +		fmt.Fprintf(conn, "ACK\n") + +		// Wait and get client's DH public key +		packet, err := bufio.NewReader(conn).ReadString('\n') +		if err != nil { +			fmt.Println("Error: Unable to read client's DH public key") +			return +		} +		// Remove newline character. +		packet = packet[:len(packet)-1] + +		// Parse client's DH public key. +		_, ok = new(big.Int).SetString(lib.StripSpaceChars(packet), 10) +		if !ok { +			fmt.Println("Error: client DH public key invalid") +			return +		} + +		// Send server's session key as public key to client. +		fmt.Fprintf(conn, "%v\n", skey) + +		// Client session key. +		ckey := new(big.Int).Set(skey) +		ckeyAlt := new(big.Int) +		ckeyConfirmed := true +		if gtype == "p-1" { +			// ckey can be 1 or p-1. Set ckeyAlt to p-1 if +			// ckey is 1; 1 otherwise. +			ckeyConfirmed = false +			if ckey.Cmp(new(big.Int).SetInt64(1)) == 0 { +				ckeyAlt.Set(gi) +			} else { +				ckeyAlt.Set(new(big.Int).SetInt64(1)) +			} +		} + +		// Enter mitm loop +		for { +			// Read from client. +			packet, err := bufio.NewReader(conn).ReadString('\n') +			if err != nil { +				fmt.Printf("Closed connection to [%v]\n", +					conn.RemoteAddr()) +				return +			} +			// Remove newline character. +			packet = packet[:len(packet)-1] + +			// Decipher packet. +			if !ckeyConfirmed { +				_, err = decipher(ckey, packet) +				if err != nil { +					ckey = ckeyAlt +					ckeyConfirmed = true +				} +			} +			msg, err := decipher(ckey, packet) +			if err != nil { +				fmt.Printf("Message decryption failed for [%v]: %v\n", +					conn.RemoteAddr(), err) +				return +			} +			fmt.Printf("Received from client [%v]: '%v'\n", +				conn.RemoteAddr(), msg) + +			// Encrypt and forward message to server. +			spacket, err := encipher(skey, msg) +			if err != nil { +				fmt.Printf("Message encryption failed for [%v]: %v\n", +					sconn.RemoteAddr(), err) +				return +			} +			// Send message to server. +			fmt.Fprintf(sconn, "%s\n", spacket) + +			// Read encrypted message from server. +			spacket, err = bufio.NewReader(sconn).ReadString('\n') +			if err != nil { +				fmt.Printf("Closed connection to [%v]\n", +					sconn.RemoteAddr()) +				return +			} +			// Remove newline character. +			spacket = spacket[:len(spacket)-1] + +			// Decipher packet. +			msg, err = decipher(skey, spacket) +			if err != nil { +				fmt.Printf("Message decryption failed for [%v]: %v\n", +					sconn.RemoteAddr(), err) +				return +			} +			fmt.Printf("Received from server [%v]: '%v'\n", +				sconn.RemoteAddr(), msg) + +			// Encrypt and echo back message. +			cpacket, err := encipher(ckey, msg) +			if err != nil { +				fmt.Printf("Message encryption failed for [%v]: %v\n", +					conn.RemoteAddr(), err) +				return +			} +			// Send message to client. +			fmt.Fprintf(conn, "%s\n", cpacket) +		} +	} +	// Start (mitm) attacker server. +	attackerSpawn := func() { +		p := fmt.Sprintf(":%d", port) +		ln, err := net.Listen("tcp", p) +		if err != nil { +			fmt.Printf("Attacker listen error: %v\n", err) +			return +		} +		for { +			fmt.Println("Waiting for connection...") +			conn, err := ln.Accept() +			if err != nil { +				fmt.Printf("Attacker accept error: %v", err) +			} +			go attackerHandleConn(conn) +		} +	}  	// Take action based on entity.  	switch { @@ -332,6 +606,8 @@ func C35(args []string) {  		serverSpawn()  	case entity == "client":  		clientSpawn() +	case entity == "attacker": +		attackerSpawn()  	default:  		fmt.Println("Error: Uknown entity")  	} @@ -356,3 +632,65 @@ func C35(args []string) {  // -> Kara Swisher's Sway.  // > ^C  // +// Part II: +// +// https://ricketyspace.net/cryptopals/c35.webm +// +// $ ./cryptopals -c 35 server 12000 +// Waiting for connection... +// Waiting for connection... +// Made secure connection with 127.0.0.1:27477 +// Received from [127.0.0.1:27477]: 'If the red slayer think he slays,' +// Closed connection to [127.0.0.1:27477] +// Waiting for connection... +// Made secure connection with 127.0.0.1:46947 +// Received from [127.0.0.1:46947]: 'Or if the slain think he is slain,' +// Closed connection to [127.0.0.1:46947] +// Waiting for connection... +// Made secure connection with 127.0.0.1:42735 +// Received from [127.0.0.1:42735]: 'They know not well the subtle ways' +// Received from [127.0.0.1:42735]: 'I keep, and pass, and turn again.' +// Closed connection to [127.0.0.1:42735] +// ^C +// +// $ ./cryptopals -c 35 attacker 12001 12000 1 +// Waiting for connection... +// Waiting for connection... +// Received from client [127.0.0.1:12597]: 'If the red slayer think he slays,' +// Received from server [127.0.0.1:12000]: '-> If the red slayer think he slays,' +// Closed connection to [127.0.0.1:12597] +// ^C +// ada$ ./cryptopals -c 35 attacker 12001 12000 p +// Waiting for connection... +// Waiting for connection... +// Received from client [127.0.0.1:47227]: 'Or if the slain think he is slain,' +// Received from server [127.0.0.1:12000]: '-> Or if the slain think he is slain,' +// Closed connection to [127.0.0.1:47227] +// ^C +// ada$ ./cryptopals -c 35 attacker 12001 12000 p-1 +// Waiting for connection... +// Waiting for connection... +// Received from client [127.0.0.1:9193]: 'They know not well the subtle ways' +// Received from server [127.0.0.1:12000]: '-> They know not well the subtle ways' +// Received from client [127.0.0.1:9193]: 'I keep, and pass, and turn again.' +// Received from server [127.0.0.1:12000]: '-> I keep, and pass, and turn again.' +// Closed connection to [127.0.0.1:9193] +// ^C +// +// $ ./cryptopals -c 35 client 12001 +// Made secure connection with 127.0.0.1:12001 +// > If the red slayer think he slays, +// -> If the red slayer think he slays, +// > ^C +// ada$ ./cryptopals -c 35 client 12001 +// Made secure connection with 127.0.0.1:12001 +// > Or if the slain think he is slain, +// -> Or if the slain think he is slain, +// > ^C +// ada$ ./cryptopals -c 35 client 12001 +// Made secure connection with 127.0.0.1:12001 +// > They know not well the subtle ways +// -> They know not well the subtle ways +// > I keep, and pass, and turn again. +// -> I keep, and pass, and turn again. +// > ^C | 
