What 3 Words - 60 points
Writeup by poortho
Problem Statement: That’s a lot of data… but at least it’s signed! I’ll bet that at least one signature doesn’t match up, though. One of ‘em has a bit of cuil. It’ll be like finding a needle in a haystack…
Hint:
Yes, I know that the RSA key format doesn’t really matter in this scenario (considering there isn’t much of a format).
Writeup
We are given a massive json file, which we have to get the flag from. It seems to contain a huge array of data and signatures. At the bottom, it includes a RSA public key.
This problem is fairly straightforward - we have to create a script that verifies which data is properly signed, which will give us the flag.
First, however, we have to format the public key in a way such that python will recognize it.
To do this, we can use this online tool to convert the key to PEM format, which gives us:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEDtIRT57TJAfmub2RsIM32jdo
8ijsds/u1fpY6hwtkC01/LFJkNTXqSwvpaO5tp86o0SlzBHdF0WxPtsKqdc8F7kQ
uHm7hUTLX0zPGRdGCsy9q/PIGlVGAFTBSVXl+grmGGZuS1CHI13L/oulBGENQOxO
8r6D1RyPjt6z0BAndQIDAQAB
-----END PUBLIC KEY-----
Now, we can write a script to read the json and check every piece of data.
This is my code:
import json
with open('haystack.json') as data_file:
data = json.load(data_file)
data = data["haystack"]
def verify_sign(public_key_loc, signature, data):
'''
Verifies with a public key from whom the data came that it was indeed
signed by their private key
param: public_key_loc Path to public key
param: signature String signature to be verified
return: Boolean. True if the signature is valid; False otherwise.
'''
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64decode
pub_key = '''-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7/t8AXWyOuk9IULfWzA6HDPU5
1IKfAUCO1nxDlg8e2EiZX94cvaChFdl3UfpPNS/nxbJQwVlHaGHL070ETVJASzap
IgoS5HCchNkNyQPUJqGrviV8bs7+01Yq649TKD8xGdQ7nD39y+tfVnkfTmTSwiwT
lJiw4PEJ1RCw+PbwMQIDAQAB
-----END PUBLIC KEY-----'''
rsakey = RSA.importKey(pub_key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
# Assumes the data is base64 encoded to begin with
digest.update(b64decode(data))
if signer.verify(digest, b64decode(signature)):
return True
return False
for x in range(len(data)):
if not verify_sign("",data[x]['signature'],data[x]['data']):
print data[x]['data'].decode('base64')
Run it, and we get the flag!
Flag
sometimes_needles_in_a_haystack_can_prick_you