Advent of Code Day 3

Day 3 of Advent of Code1.

This is kind of a mess. I was really rushing to try to see if I could land on the leaderboard at least once this year.

import re

pattern = re.compile(
        """
        \#
        (?P<claim>.*?)
        \s@\s
        (?P<left>.*?)
        ,
        (?P<top>.*?)
        :\s
        (?P<x>.*?)
        [x]
        (?P<y>.*?)
        $
        """, re.VERBOSE)

matches = []
for line in open("input3.txt"):
    match = pattern.match(line)
    claim = int(match.group('claim'))
    top = int(match.group('top'))
    left = int(match.group('left'))
    x = int(match.group('x'))
    y = int(match.group('y'))
    matches.append({"top": top, "left": left, "x": x, "y": y})

c = set()
collide = set()
for match in matches:
    for i in range(match['left'],match['left']+match['x']):
        for j in range(match['top'],match['top']+match['y']):
            if (i,j) in c:
                collide.add((i,j))
            c.add((i,j))

print(len(collide))

for match in matches:
    found = True
    for i in range(match['left'],match['left']+match['x']):
        for j in range(match['top'],match['top']+match['y']):
            if (i,j) in collide:
                found = False
    
    if found:
        print(claim)

Advent of Code Day 2

Day 2 of Advent of Code1.

The following is my solution for Part 2. Part 1 was some modification of this.

import collections
 
lines = []
for line in open("input2.txt"):
    lines.append(line.strip())
 
# lines.sort() // unsure if saves time or wastes time
 
for i in range(len(lines)):
    for j in range(i,len(lines)):
        x = [ord(a) ^ ord(b) for a,b in zip(lines[i],lines[j])]
        xc = sum(i > 0 for i in x)
        if xc == 1:
            print(lines[i])
            print(lines[j])
            exit()

As I had labeled in the comment, sorting the lines didn’t appear to cause a noticeable difference in performance for the input size. I haven’t looked at the effects on larger or smaller inputs, but from what I gathered from a friend that running similar code in Clojure, sorting did have a magnitude of performance increase.

Advent of Code Day 1

I started playing around with Advent of Code1 this year.

For part 1, I used a spreadsheet to sum the numbers :P Here’s my solution for part 2:

found = False
u = set()
i = 0
while not found:
    for line in open("input1.txt"):
        i = i + int(line)
        if i in u:
            found = i
            break
        u.add(i)
        print('.', end='', flush=True)

print(f'found:{found}')

Bash on Ubuntu on Windows in Atom's PlatformIO-IDE-Terminal

For a while, I’ve been using specific IDEs for each individual language that I program in. It was feeling cluttered juggling between IntelliJ, Sublime, ZBStudio, et al.

I wanted to give Atom a try to see how it sets itself apart from the rest and to see how I could make it more useful for myself as I switch contexts between all the languages.

One of the great things on Atom is how extensible it is with the package explorer. I loved the feature of having the console in ZBStudio and Sublime. Though Sublime was difficult to configure and ZBStudio was only for Lua. The terminal on Atom’s PlatformIO-IDE-Terminal opens a Powershell window when opened. This was good and I really wanted a way to open bash at my project folder’s location.

The following details the simple steps to add bash to your Path and be able to use bash at your project folder’s location:

First, make a link to bash. I created the C:\Links directory after realizing how powerful these steps are for adding any binary to my PATH

PS C:\Links> mklink bash.exe "C:\Windows\System32\bash.exe

Second, add this folder to your PATH.

Third, open any terminal whether its Atom’s terminal, cmd, or powershell and just type bash. This will open bash at that location. This is great because you no longer have to open the Bash application and cd all the way to your project folder. I never knew until now that mklink existed on Windows and will probably use it more to keep my PATH clean by linking everything to my C:\Links directory.

Inspect 2-way authentication with Tcpdump and Wireshark

At work, I run an Nginx server that is configured for 2-way authentication. The following are notes that I took to show how to use Wireshark to inspect the tcp stream of encrypted traffic.


Convert certificates to .p12

First, we need to have both client and server certificates. With Wireshark it is preferred that we have PKCS12 format files so we need to convert our certificates to that format. The client in this case is a Tomcat server but sometimes a JMeter client which is used for testing.

To convert a JKS file to PKCS12 format:

$ keytool -importkeystore -srckeystore client.jks \
> -srcstorepass weblogic \
> -destkeystore client.p12 \
> -deststorepass weblogic \
> -srcalias client \
> -deststoretype pkcs12

To convert a PEM file to PKCS12 format:

$ openssl pkcs12 -export -out server.p12 \
> -inkey server.key \
> -in server.pem \
> -certfile server-cacert.pem 


Form the tcpdump command

In my environment, the backend server is behind an AWS Elastic Load Balancer so we need to find the IP addresses of the ELB:

$ host my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com
my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com has address 10.201.100.100
my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com has address 10.201.100.101

Use the ELB IP addresses to form the tcpdump command:

$ sudo tcpdump -i any -s0 -w output.pcap host 10.201.100.100 or 10.201.100.101

If you want to be specific about the port then a more advanced command:

$ sudo tcpdump -i any -s0 -w output.pcap \
> '(host 10.201.100.100 or 10.201.100.101) and port 443'


Sending the request

To properly capture 2-way authentication and be able to decrypt the tcp stream in Wireshark, the traffic must be encrypted with RSA. Traffic encrypted with any version of Diffie-Hellman will not work.

On the server, list the available ciphers and narrow down to the relevant ones that will work for Wireshark inspecting:

$ openssl ciphers | tr ':' '\n' | grep AES | egrep -v 'DH|PSK'
AES256-GCM-SHA384
AES256-SHA256
AES256-SHA
AES128-GCM-SHA256
AES128-SHA256
AES128-SHA

With the listed ciphers from the server, form the curl request and specify a compatible cipher:

$ curl -v --tlsv1.2 --cipher rsa_aes_128_sha --cert client.p12:weblogic \
> https://my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com:443/test

Unfortunately, if you are on a Mac, the curl request will not work. Since Mavericks, the Transport Security Layer disables the ignores the option to set the cipher suite.1 In my case, I was able to restrict the encryption to RSA by setting the Nginx server configuration:

ssl_ciphers RSA;

After setting the Nginx server to only accept RSA encryption, I could send requests from JMeter with no issue or further configuration.


Inspect with Wireshark

Finally, once the pcap file has been created which captures the traffic sent from curl or JMeter, open it in Wireshark. Open the Wireshark preferences and select SSL from the protocol list. Select “Edit…” for the RSA Key List and add both the client certificate and the server certificate that we generated earlier in this tutorial. Afterward, you should now be able to see the unencrypted traffic. If you right-click and select “Follow > SSL Stream”, then you should see the requests made in clear text including header values and body data.