forked from ctfs/write-ups-2017
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
💾 Add Boston key party CTF 2017 Crypto Resources
- Loading branch information
1 parent
a0596f7
commit 894a107
Showing
10 changed files
with
452 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
210 changes: 210 additions & 0 deletions
210
boston-key-party-2017/crypto/minesweeper-350/minesweeper.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
18
boston-key-party-2017/crypto/multi-party-computation-250/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
130
boston-key-party-2017/crypto/multi-party-computation-250/mpc.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+8.48 KB
boston-key-party-2017/crypto/sidh-rsa-aes128-gcm-sha256-600/accesslog.pcap
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.