Skip to content

Commit

Permalink
💾 Add Boston key party CTF 2017 Crypto Resources
Browse files Browse the repository at this point in the history
  • Loading branch information
elliptic-shiho committed Feb 28, 2017
1 parent a0596f7 commit 894a107
Show file tree
Hide file tree
Showing 10 changed files with 452 additions and 4 deletions.
2 changes: 1 addition & 1 deletion boston-key-party-2017/crypto/minesweeper-350/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
>
> Connect via TCP, 54.202.194.91:65535
>
> [mineswee...](http://ctf.bostonkey.party/files/602b11e9052b95f61128d35653efb110/minesweeper.go)
> [mineswee...](minesweeper.go)
## Write-up

Expand Down
210 changes: 210 additions & 0 deletions boston-key-party-2017/crypto/minesweeper-350/minesweeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package main

import (
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"math"
"math/cmplx"
"math/rand"
"net"
)

type UserError struct {
msg string // description of error
}

func (e *UserError) Error() string { return e.msg }

const (
G_I = 0 // Identity
G_X = 1 // Pauli X-gate
G_Y = 2 // Pauli Y-gate
G_Z = 3 // Pauli Z-gate
G_H = 4 // Hadamard gate
G_R = 5 // R2 gate: rotate phase by 90 degrees
G_P = 6 // Rotate phase by an angle specified in radians
G_M = 7 // Measure in standard (Z) basis, and if 1, self-destruct
)

var S float64 = math.Sqrt(0.5)

var flag []byte

var MATRICES = [6][2][2]complex128{
{{complex(1, 0), complex(0, 0)}, {complex(0, 0), complex(1, 0)}},
{{complex(0, 0), complex(1, 0)}, {complex(1, 0), complex(0, 0)}},
{{complex(0, 0), complex(0, -1)}, {complex(0, 1), complex(0, 0)}},
{{complex(1, 0), complex(0, 0)}, {complex(0, 0), complex(-1, 0)}},
{{complex(S, 0), complex(S, 0)}, {complex(S, 0), complex(-S, 0)}},
{{complex(1, 0), complex(0, 0)}, {complex(0, 0), complex(0, 1)}},
}

func apply_gate(state [4]complex128, matrix [2][2]complex128, wire bool, controlled bool) [4]complex128 {
var result [4]complex128
// I could carefully parameterize this. Or I could be a lazy bum!
if wire && controlled {
result[0] = state[0]
result[2] = state[2]
result[1] = matrix[0][0]*state[1] + matrix[1][0]*state[3]
result[3] = matrix[0][1]*state[1] + matrix[1][1]*state[3]
} else if wire {
result[0] = matrix[0][0]*state[0] + matrix[1][0]*state[2]
result[2] = matrix[0][1]*state[0] + matrix[1][1]*state[2]
result[1] = matrix[0][0]*state[1] + matrix[1][0]*state[3]
result[3] = matrix[0][1]*state[1] + matrix[1][1]*state[3]
} else if controlled {
result[0] = state[0]
result[1] = state[1]
result[2] = matrix[0][0]*state[2] + matrix[1][0]*state[3]
result[3] = matrix[0][1]*state[2] + matrix[1][1]*state[3]
} else {
result[0] = matrix[0][0]*state[0] + matrix[1][0]*state[1]
result[1] = matrix[0][1]*state[0] + matrix[1][1]*state[1]
result[2] = matrix[0][0]*state[2] + matrix[1][0]*state[3]
result[3] = matrix[0][1]*state[2] + matrix[1][1]*state[3]
}
return result
}

func measure_wire(state [4]complex128, wire bool) [4]complex128 {
prob_zero := cmplx.Abs(state[0]) * cmplx.Abs(state[0])
if wire {
prob_zero += cmplx.Abs(state[1]) * cmplx.Abs(state[1])
} else {
prob_zero += cmplx.Abs(state[2]) * cmplx.Abs(state[2])
}
if rand.Float64() < prob_zero {
var result [4]complex128
result[0] = state[0] / complex(math.Sqrt(prob_zero), 0)
result[3] = complex(0, 0)
if wire {
result[1] = state[1] / complex(math.Sqrt(prob_zero), 0)
result[2] = complex(0, 0)
} else {
result[1] = complex(0, 0)
result[2] = state[2] / complex(math.Sqrt(prob_zero), 0)
}
return result
} else {
panic(UserError{"BOOM!"})
}
}

func measure_final(state [4]complex128) int {
var so_far float64 = 0
actual := rand.Float64()
for i := 0; i < 4; i++ {
so_far += cmplx.Abs(state[i]) * cmplx.Abs(state[i])
if so_far >= actual {
return i
}
}
panic(UserError{"Bad probability?"})
}

func handle_connection(conn net.Conn) {
defer func() {
e := recover()
if e != nil {
if uerr, ok := e.(UserError); ok {
fmt.Println(uerr.Error())
conn.Write([]byte(uerr.Error()))
}
}
conn.Close()
}()

bombs := make([]bool, 14*8)
for ix := range bombs {
bombs[ix] = (rand.Intn(2) == 1)
}
for {
command := make([]byte, 2)
io.ReadFull(conn, command)
num_gates := uint16(command[1]) + 256*uint16(command[0])
if num_gates == 0 {
break
}
state := [4]complex128{complex(1, 0), complex(0, 0), complex(0, 0), complex(0, 0)}
for i := uint16(0); i < num_gates; i++ {
gates := make([]byte, 1)
io.ReadFull(conn, gates)
gate := gates[0]
primary_wire := (gate & 0x80) != 0
var gate_id byte
var controlled bool
if (gate & 0x7F) < 0x70 {
controlled = false
if bombs[gate&0x7F] {
gate_id = G_M
} else {
gate_id = G_I
}
} else {
controlled = (gate & 0x08) != 0
gate_id = (gate & 0x07)
}

if gate_id == G_M {
// Can't control a measurement! Ignore 'controlled' flag
state = measure_wire(state, primary_wire)
} else {
var matrix [2][2]complex128
if gate_id == G_P {
// Phase gate in radians
bytes := make([]byte, 8)
io.ReadFull(conn, bytes)
bits := binary.LittleEndian.Uint64(bytes)
imag_part := math.Float64frombits(bits)
factor := cmplx.Exp(complex(0, imag_part))
matrix = [2][2]complex128{{complex(1, 0), complex(0, 0)}, {complex(0, 0), factor}}
} else {
matrix = MATRICES[gate_id]
}
state = apply_gate(state, matrix, primary_wire, controlled)
}
}
res := byte(measure_final(state))
conn.Write([]byte{res})
}
guess := make([]byte, 14)
io.ReadFull(conn, guess)
for ix, g := range guess {
for i := 0; i < 8; i++ {
var theirs bool = (g & (0x01 << uint16(7-i))) != 0
var ours bool = bombs[ix*8+i]
if theirs != ours {
panic(UserError{"WRONG"})
}
}
}
conn.Write(flag)
conn.Close()
}

func main() {
key, err := ioutil.ReadFile("flag.txt")
if err != nil {
panic(err)
}
fmt.Println(string(key))
flag = key
if len(flag) > 50 {
panic(UserError{"this doesn't happen"})
}
listener, err := net.Listen("tcp", "0.0.0.0:8001")
if err != nil {
panic(err)
}
defer listener.Close()
fmt.Println("Ready to rumble.")
for {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
go handle_connection(conn)
}
}
18 changes: 18 additions & 0 deletions boston-key-party-2017/crypto/multi-party-computation-250/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Boston Key Party CTF 2017: multi-party-computation-150

**Category:** Crypto
**Points:** 250
**Solves:**
**Description:**

> (missing description)
>
> [mpc.py](mpc.py)
## Write-up

(TODO)

## Other write-ups and resources

* none yet
130 changes: 130 additions & 0 deletions boston-key-party-2017/crypto/multi-party-computation-250/mpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from Crypto.Util import number
import random

from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import sys
import json

import traceback

def L(x, n):
return (x-1) // n


def paillier_keygen():
# Returns (pk, sk)
p = number.getStrongPrime(512)
q = number.getStrongPrime(512)
n = p*q
lam = (p-1)*(q-1)/2
while True:
g = random.randrange(n**2)
if number.GCD(g, n) != 1:
continue
mu_inv = L(pow(g, lam, n**2), n)
if number.GCD(mu_inv, n) != 1:
continue
mu = number.inverse(mu_inv, n)
break
return (n, g), (lam, mu)

def paillier_encrypt((n, g), m):
while True:
r = random.randrange(n)
if number.GCD(r, n) == 1:
break
return (pow(g, m, n**2) * pow(r, n, n**2)) % (n**2)

def paillier_decrypt((n, g), (lam, mu), c):
return (L(pow(c, lam, n**2), n) * mu) % n

def paillier_add((n, g), a, b):
return (a * b) % (n**2)

def paillier_multiply((n, g), a, k):
return pow(a, k, n**2)

def mpc_monomial(point):
return [-point, 1]

def mpc_multiply_poly(n, x, y):
result = [0]*(len(x) + len(y))
for i in range(len(x)):
for j in range(len(y)):
result[i+j] += (result[i+j] + x[i]*y[j]) % n
return result

def mpc_encrypt_poly(pk, poly):
return [paillier_encrypt(pk, term) for term in poly]

def mpc_client_genpoly((n, g), points):
result = [1]
for point in points:
result = mpc_multiply_poly(n, result, mpc_monomial(point))
return mpc_encrypt_poly(pk, result)

def mpc_evaluate_poly((n, g), poly, point):
pow_point = point
result = poly[0]
for term in poly[1:]:
result = paillier_add((n, g), result, paillier_multiply((n, g), term, pow_point))
pow_point = (pow_point * point) % n
return result

def mpc_server_side((n, g), poly, points):
for point in points:
result = mpc_evaluate_poly((n, g), poly, point)
result = paillier_multiply((n, g), result, random.randrange(n))
result = paillier_add((n, g), result, paillier_encrypt((n, g), point))
yield result

def mpc_client_parseresults(pk, sk, c_points, s_points_enc):
s_points = [paillier_decrypt(pk, sk, point) for point in s_points_enc]
return set(c_points) & set(s_points)



class MpcHandler(BaseHTTPRequestHandler):
def do_POST(self):
try:
data_str = self.rfile.read(int(self.headers.getheader('content-length')))
data = json.loads(data_str)
n = data['n']
if (n < 2**64):
raise ValueError('too small')
g = data['g']
poly = data['poly']
l = list(mpc_server_side((n, g), poly, POINTS))
random.shuffle(l)
result = json.dumps(l)
except Exception as e:
self.send_response(400)
else:
self.send_response(200)
self.end_headers()
self.wfile.write(result)


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass

if __name__=="__main__":
assert(len(sys.argv) >= 3)

with open('FLAG.txt', 'r') as f:
flag = f.read()[:-1]
print flag

POINTS = []
for i in range(len(flag)):
POINTS.append(random.randrange(2**48) * 256)
POINTS.sort()
for i in range(len(flag)):
POINTS[i] += ord(flag[i])
print POINTS

server = ThreadedHTTPServer((sys.argv[1], int(sys.argv[2])), MpcHandler)
server.serve_forever()

2 changes: 1 addition & 1 deletion boston-key-party-2017/crypto/rsa-buffet-150/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
> with. (See encrypter.py for details of the encryption format.) Decrypt any 3
> files, and recover the key from the secret share!
>
> [rsa-buffet.tar....](http://ctf.bostonkey.party/files/fdf38c07dd5986643944c0a916a618e6/rsa-buffet.tar.bz2)
> [rsa-buffet.tar.bz2](rsa-buffet.tar.bz2)
## Write-up

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
> update 7:10 UTC Saturday: the traffic in the pcap with 162.125.18.133 is not
> relevant to the challenge
>
> [accesslog....](http://ctf.bostonkey.party/files/7071a751aed6dbc599864ab66f183d24/accesslog.pcap)
> [accesslog.pcap](accesslog.pcap)
## Write-up

Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion boston-key-party-2017/crypto/sponge-200/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
>
> <http://54.202.194.91:12345>
>
> [hash.py](http://ctf.bostonkey.party/files/933896caa327762dc320053285d1b204/hash.py)
> [hash.py](hash.py)
## Write-up

Expand Down
Loading

0 comments on commit 894a107

Please sign in to comment.