Quantum Key Distribution

Attachmentscrypto - 92134 solves

Generate a key using Quantum Key Distribution (QKD) algorithm and decrypt the flag.

Time

15 minutes

Behavior

We are simulating a Quantum satellite that can exchange keys using qubits implementing BB84. You must POST the qubits and basis of measurement to /qkd/qubits and decode our satellite response, you can then derive the shared key and decrypt the flag. Send 512 qubits and basis to generate enough key bits.

The service runs BB84 protocol, there is a good explaination of the protocol on wikipedia

Solution

TL;DR

  1. Exchange shared secret using BB84 protocol
  2. Convert the bit string to char string with correct order
  3. XOR the secret and encryped key to decrypt it

Here's a example copied from wikipedia:

Action
Alice's random bit01101001
Alice's random sending basis++x+xxx+
Photon polarization Alice sends
Bob's random measuring basis+xxx+x++
Photon polarization Bob measures
PUBLIC DISCUSSION OF BASIS
Shared secret key0101

In this task, we are Alice and the server is Bob. To establish a shared secret, we have to choose some random bits first:

state = [random.randrange(2) for _ in range(512)]

Next, for the simplicity, we set all the basis to +

basis = ['+'] * 512

And calculate the qubits state based on the basis an the bits

z = [{'real': 1, 'imag': 0}, {'real': 0, 'imag': 1}]
qubits = [z[s] for s in state]

Send those qubits to the server to get Bob's basis and encrypted key

res = sess.post(
    'https://cryptoqkd.web.ctfcompetition.com/qkd/qubits',
    json={ 'basis': basis, 'qubits': qubits, }
    ).json()

Compare the basis and keep those bits with correct basis

bits = [s for s, b in zip(state, res['basis']) if b == '+'][:128]

Convert the bits to string with MSB-first and Left-first order.

shared = int(''.join(map(str, bits)), 2).to_bytes(16, 'big')

XOR the secret and encryped key to decrypt it

encrypted = bytes.fromhex(res['announcement'])
key = bytes(a ^ b for a, b in zip(encrypted, shared)).hex()
print(key)

Now decrypt the flag using the command provided in the description

echo "$KEY" > plain.key
xxd -r -p plain.key > enc.key
echo "$FLAG" | openssl enc -d -aes-256-cbc -pbkdf2 -md sha1 -base64 --pass file:enc.key