Qwantik

Category: Crypto
Author: Amosys

This challenge is about the hybridization in a key encapsulation mechanism (KEM).

First look

We have access to TCP server that provides 5 services:

[DEBUG]: Warning, XOR combiner is unsafe. Consider using a safer key encapsulation mechanism combiners.

Please choose an action:
 1- Encapsulation with RSA
 2- Encapsulation with Kyber
 3- Decapsulation Oracle
 4- Test a session key
 5- Read the latest communication

Command:

We also have a link to a blogpost about hybridization. This blogpost explains how to combine two KEM to create a new one, which can be broken only if both sub-KEM are broken.

This is useful when one of the KEM is using well-tested classical cryptography (but vulnerable to quantum computers) and the other one is using post-quantum cryptography (which might have a vulnerability).

Using the service, we can get the “latest communication”:

Command:
5
(Beginning of communication between A and B)
(A --> B: pk_rsa + pk_kyber)
c0342260668b7386fbecba834da3a81c5baec8dbfd6d77ffb43f70d73b01a8f4c556facb805bbcaa346ad6867f13dda1e4f2cd925360b8b8f9b9e9ebda32c14462ad865930554e84cb42e440c9ad8b463fadbcd5b510b0751bcb26427af6dbad30a14dd288060e732b0349011cd14121ac611b682547286309748f270474ea9d0100015b039bb99bce96e8b5b0d2ca18f518f6a7add9b81b7e791a632bce28e35734fb9902e416a4955fb0a0c61b5070995739d4100d94538e1578975c2110fbf497cfe95f4634adfe0006cb9cbe48157ef3fb0f8bd53d70d8a29a152ca4882904151ac1c0b429d274a8642db8192237f6854f6b548d299cde17caae403c6deb77611934cc665e1852bf5e483fb3505131084e8fcc55252a900b836d562675f11434c7daa2882035e15a149d967b16cb1a14e8ac438a475914693ae7c023634e542392abcaa0f25398bad7b9358123bbe61d77fa19e8696aefa4958b7a5f83d994a5f69611c0234a132881c00fc61795523771c1e7c23e61cedf32a6a15a3551a69e1c731ffb5a12c23b8a76102190b80a2700518bc788ccb2c54fa5cd276516893656baf1c5296906af39ab90270d1f98bac393178433ae186b645ed74dd9492d6a201977c6c81794a755c1b65383630a807b8b3348b0b41271844b5a6b708157b90a323bcc240f00b66d40c2355eb8c0b64bb0817187c4f61b710290e6fc24e9f89946a92104801eb2b7c724bc42f006a1eb7919b7f2a7b0cc05ce338dbd070560935e0d604f03e56eb5f4b88b5197b9f4139f1c7aa9b66e3d7bba146b19ec17af387c7c1a0532106a696c92a12cd63ab651045ba318e2f5245bd55773b000c163686e54a08d03aa4a7c312217c0fd320eb061567456a7c5daad6f597b69802cda0112789a2f93f81da8d7c9e367503f4c6679616dad5aa9a653ca218ac4c3c5a528989530123ab467c9c9485fd92b15f9e1a869f33bd657a84ec8bcd7a43ccffb00e602c73d501f92dbb1df4503e91009c71344ab645697fa6be34bb103502a58a26aaedaadf5423fc15209843261c2a71717f0136ff3430de00f943a73f1371fc779b5aae4bf2ec34369cb27967293d915b4ccbc3880972584b55597325795f8c8689b48dddb71ac1b19733348d0f0a56d3b12ee7b114a34396edc26a0971ac8d02eba61766006ce650941a2e65086c791024a1ccddc602f78075f5a144f0a6a0aa97a66b8738105a241a22317fa87de8c7ea95369eb06a7cd3855fc684516a57e66683abec68349640c857763d8578c1d7d872619aa52b2b2b1cf16ae5360c8b0

(B --> A: c_rsa + c_kyber)
69129b465ad0da4613e8dac68a73e4ccdad6c7877500d3950438e3efb6b06337a5126b4806c196e20004269f4734731c014c7d492fe4262c5507ad1771225468dfed1933234e6fe8371d7bd098de2ab4e6f8dcd9a0bcdea27ca8c90bf06f61a2da3aec18f0be5ab95b918aa73bdb200f31a15f2be2350325e8595bd78415940a99d801de4cd81075b56fea09bfc896cb8d43a9a9961f856f3462a73d90246b126bfcfd7e4c7a0a4e91f7d5829b93bb4d2125b021a02dc3f426fa288226a1f0193bed5bae7d0ba98a5a451abd932240596b684d1f8af2d1569971dde8c61eb0b7a45170e3885029603f40280ee2c991718154ce96438e27ba94cd27b378160467c26162f675173ce89586d7d949824f8bd9c8e8f0b4ec11f843c8c0130addac95443cb3b220bdbd3b103fd2d72681aa8545987bbbd461a02c765d5d09232c134573f0d1558570554aefebe7001410635431f1b4a4ed3ca97ec188dcb4b40ee9ae82057dd1aa06a06477429ac121c8f542847192da789fa10dce3ec071bc600e100b75265816c2a723ef5d8d5a46fe3692f1d756de1eeb3825a4635af5bf59122a22549f162f44ac1bec76ea1b8de5a3e35902c9c4efa200b67ba35d2806cfde4082ad208d6270794829ce0d0e732233cc71cd86011177c85b4644df617f7d5524169e82684602cf53425f271c70b603f60fca8a46953f7c224fbbb43678430151c4b56ce27ce311feb357562dcb7b879c491d211d2f125d8e32be41ad3deb4b3d6f6a19653e0f9da2466c1773543f8ced9cdee5f636c8b07cfba7b676f61af6d9f03bab48bd9b7ccbffb3b20d88e3562604a7ff342919a327e2200a9826007aa0476a459094a82c6afda7284b2ed8b97ed0664b28031d2e2d3563d253044d937c9939fb882c3d3e35020579afcd2b0558bbd173ccfaba35e392496f18c32673c0bae859999cb265452b5ba8ae7394cde36b93b3685dfecb78cf734a156b2a3a464d357b93452326533a48029b20601470fc6edf2542c0214a036bec42214f6302a379c653eaed3e209a3afc9dbfd3988e9f7f7e71cbf73f347bf2a430eb337f320c4ca5303471b897bd2d2aec32e07d99b00415752a1bc4e70edb38e02a192c657e8a5818473e155ba76d8164870c3f6d85cba2e3ab0aa7dff4ecd0039b6a90540bcea0e0f6718245ec1b75b553746c92b25a10152c82c844cc6c09812200cbce8a7ab0c8887318075c1bc1d025e1e194814b195113c604a4da2f1500c0cb02b1

Which gives us a public key and a ciphertext. We can guess that our goal is to decipher the ciphertext using the other service.

Key Encapsulation Mechanism

We first have to understand how this hybrid KEM works. A KEM is a cryptographic protocol that allows two parties to agree on a shared secret key. It is composed of two algorithms:

  • $(k, c) = \text{Encaps}(pk)$: The encapsulation algorithm takes a public key $pk$ and returns a shared secret key $k$, and the encrypted secret key $c$.
  • $k = \text{Decaps}(c, sk)$: The decapsulation algorithm takes a ciphertext $c$ and a secret key $sk$ and returns the shared secret key $k$.

The blogpost describes how the hybrid KEM works:

KeyGen()
(pk1, sk1) = KeyGen1()
(pk2, sk2) = KeyGen2()
pk = (pk1, pk2) # Concatenation
sk = (sk1, sk2) # Concatenation
return pk, sk

We see that the public key is simply the combination of the two public keys of the sub-KEMs. The same goes for the secret key.

Encaps(pk)
pk1, pk2 = pk    # Split the public key
k1, c1 = Encaps1(pk1)
k2, c2 = Encaps2(pk2)
c = c1 || c2     # Concatenation
k = W(k1, k2, c) # Combination function
return k, c

Here, $W$ is a combiner function that takes the two shared secret keys $k1$ and $k2$, and the ciphertext $c$ and returns the shared secret key $k$. The blogpost and the warning message of the service hint that the XOR combiner is used and that it is unsafe.

Decaps(c, sk)
c1, c2 = c    # Split the ciphertext
k1 = Decaps1(c1, sk1)
k2 = Decaps2(c2, sk2)
k = W(k1, k2, c)
return k

We now understand that we have the folowing services:

- 1 - Encapsulation with RSA:   Encaps1(pk_rsa)
- 2 - Encapsulation with Kyber: Encaps2(pk_kyber)
- 3 - Decapsulation Oracle:     Decaps(c)
- 4 - Test a session key:       Test if we have the correct k
- 5 - Read the latest communication: Get pk and c

Of course the service forbids us to use the Descaps() oracle on the ciphertext directly.

Solution

We can use the following strategy:

    1. Split the ciphertext $c$ into $c_{rsa}$ and $c_{kyber}$ and the public key $pk$ into $pk_{rsa}$ and $pk_{kyber}$: $$pk = pk_{rsa} || pk_{kyber}$$ $$c = c_{rsa} || c_{kyber}$$
    1. Use the RSA and Kyber encapsulation services to get new key encapsulations: $$k1_{rsa}, c1_{rsa} = \text{Encaps1}(pk_{rsa})$$ $$k1_{kyber}, c1_{kyber} = \text{Encaps2}(pk_{kyber})$$
    1. Combine them with the original ciphertext, and combine them together: $$c2 = c1_{rsa} || c_{kyber}$$ $$c3 = c_{rsa} || c1_{kyber}$$ $$c4 = c1_{rsa} || c1_{kyber}$$
    1. Use the Decapsulation Oracle on $c2$ and $c3$ to get the shared secret keys $k2$ and $k3$ $$k2 = \text{Decaps}(c2)$$ $$k3 = \text{Decaps}(c3)$$ $$k4 = \text{Decaps}(c4)$$
    1. XOR $k2$ and $k3$ to get the shared secret key $k$ (and xor with $k4$ to “remove” the added components in $k2$ and $k3$): $$k = k2 \oplus k3 \oplus k4$$
import socket, time

# challenges.challenge-ecw.eu 34588

host = "challenges.challenge-ecw.eu"
port = 4242


"""
Please choose an action:
 1- Encapsulation with RSA
 2- Encapsulation with Kyber
 3- Decapsulation Oracle
 4- Test a session key
 5- Read the latest communication
"""

def get_communication(s):
    """
    Returns (A --> B: pk_rsa + pk_kyber) and (B --> A: c_rsa + c_kyber)
    """
    s.send(b"5\n")
    time.sleep(1)
    data = s.recv(20000).decode().split("\n")

    return data[2], data[5]

def enc_rsa(s, pk):
    """
    returns ct, key
    """
    s.send(b"1\n")
    s.send(pk.encode() + b"\n")
    time.sleep(1)
    data = s.recv(20000).decode()
    lines = data.split("\n")
    return lines[3], lines[6]

def enc_kyber(s, pk):
    """
    returns ct, key
    """
    s.send(b"2\n")
    s.send(pk.encode() + b"\n")
    time.sleep(1)
    data = s.recv(20000).decode()
    lines = data.split("\n")
    return lines[3], lines[6]

def dec_oracle(s, ct):
    s.send(b"3\n")
    s.send(ct.encode() + b"\n")
    time.sleep(1)
    data = s.recv(20000).decode()
    res = data.split("\n")[3]
    if res == 'Please choose an action:':
        return data
    return res

def test_key(s, key):
    s.send(b"4\n")
    s.send(key.encode() + b"\n")
    time.sleep(1)
    data = s.recv(20000).decode()
    return data

def xork(key1, key2):
    return bytes([a ^ b for a, b in zip(bytes.fromhex(key1), bytes.fromhex(key2))]).hex()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
data = s.recv(1024).decode()

pk, ct = get_communication(s)
print("pk:      ", pk , len(pk))
print("ct:      ", ct, len(ct))
rsa_ct = ct[:256]
kyber_ct = ct[256:]
print("rsa_ct:  ", rsa_ct)
print("kyber_ct:", kyber_ct)
rsa_pk = pk[:len(pk)//2]
kyber_pk = pk[len(pk)//2:]
print("rsa_pk:  ", rsa_pk)
print("kyber_pk:", kyber_pk)
print()

rsa_ct1, rsa_k1 = enc_rsa(s, pk)
print("rsa_ct1: ", rsa_ct1)
print("len(rsa_ct1): ", len(rsa_ct1))
print("rsa_k1:  ", rsa_k1)
kyber_ct2, kyber_k2 = enc_kyber(s, pk)
print("kyber_ct2:", kyber_ct2)
print("len(kyber_ct2): ", len(kyber_ct2))
print("kyber_k2: ", kyber_k2)
print()

ct1 = rsa_ct1 + kyber_ct
print("ct1:     ", ct1)
k1 = dec_oracle(s, ct1)
print("k1:      ", k1)
ct2 = rsa_ct + kyber_ct2
print("ct2:     ", ct2)
k2 = dec_oracle(s, ct2)
print("k2:      ", k2)
ct3 = rsa_ct1 + kyber_ct2
print("ct3:     ", ct3)
k3 = dec_oracle(s, ct3)
print()

rsa_k = xork(rsa_k1, k1)
kyber_k = xork(kyber_k2, k2)
print("rsa_k:   ", rsa_k)
print("kyber_k: ", kyber_k)
k = xork(xork(k1, k2), k3)
print("k:       ", k)

data = test_key(s, k)
s.close()

print(data)

Output:

pk:       e976d7efe8fd3ce1c688d8053f8433c136efc7287db31a7b159fa3d17e4b2ceeada589aaa65edb7193ea9ece7281c63ab44a8168fb458685289ccdb260a5734a39c877b90871c77600dd2d3076619dec4830679a5c268ce4f96b310bbeb0b4fa88eda28e66bce07f4474ddcacc2c221a2cccef8f0e60ce6ebfac359efb93736f010001d8998507a14337022cad2bcbcaa77adaa6529006cf2dd355a6283e07c4b0c1e10ebdf43a941c8c7c9aac7d69015a15c267c61f00965939c09902cc9fc18a6a50319318fbae8a2a00ce2a9b8afccb2d77564cc32766d70fc129a957945f78bcaa7bf34188ca3d7d3022597cac3e4c371a1a387854ad65261e556260c3a6100d2b89e0b029e7d9334187a1f7bc1bfcab2f0d988b2b0538428a65312b73ec421917320215790ed42aa3131627ce49a5759b0fbff95abdec1828839655e5618c1023f9f44275ca6cdb5bc73d7ca429f203693ba0c325a4f5933694bc796239b7b4a72650363d80c39d8714947fe204388147c6b7bac11b70d968382f399ac545aad783a1e2f767670ca1a653bf553b9212920dcf91bde862951927754cd504be839561a29b6e1679a0911f4b2a62a6aa27e90a2919c241d4e0ca2a143c0c887fe518b47d845e2d8c389064025175490964514bf109fc9a2e4979837a8b76240bc592ab09886b5e9dacb4c0a07dcd49ae61986b28103d7230b629c4a331826905777a6d7933b5b21152da7396f82bc269c39f1502e6d414c366bb3d208023b04b3997cb80d19574a594d1b3c3e78409e33657b1e76bce170d9ec46ac2b29abdfbb197c0a221d8cac40c35c70012606a3bb9ca90e37b0a9c206bf1ec52e120122b196c98e06e34223b0519759ca72a8fd3987c1a1a7e80cc3c7926fa6b380c372d12b3c9656b4454c96d5b657b1dca50c46356bcac6d8a687c30a69d394b079c19b14d066eb47b80a37b320e34318fa666976b015463120c447b51cc16fb97ba53421503c021d7d51f7668afacf054886945abb7baf1c569f43a1dd82a556686a353c995404aca138b356af7b5dccba597b14a6dda699a2931f5579d18673da7acbf0d90291ed26330b348b0952413ac205097a910a39fee19c39941b5cb889551755197f877cb7b33d5e63a0cd5260e860c6141132d7b50825211f1b9950f7cbdf01bc2f964b39c376ad547a822a8619d37479f263199a516beba974cc34253d2c6667b2a08345e3e88cf0229c7ce719d96cb0a2ce69d5ba55015c20f589ca4b324afc6a5dc16ef72bd709e0a7fd4b5dbf5ef41760b3b67be0e0ce3804db7ef7b4c6c 1862
ct:       abff2aa42a34e246c912b1ec74a10099974c7220c9e46982bcdb36840a71210d8fe52c9e7e2a4fad8febcecedffae052cffab5a219193255264ced7cd085fb78a5630be816d9bebac5f6ee3a908118217f9e0018169e17ae4a992cd6c9400e3c39a6be0330bb9e9085e6f6a88fc74a271bc69072b2ba6902fcc1cd8b87b474e1c81cb27253d779f53a0db5f3e28cb95c2c8a6315c127bd35ad0b131d7b30dda702ad610e24d3609dc80ca95691ac7a0477aed4a9b059483753b687512da1148650f4ebce22ab0a8971d2a2c793b80475cd998a2d7e3e93c8607ee0a3d9d43b307fa15d214e12e655eeeeff5b71b91bd8804dff1e8630f09167dfff6e3bfa9ce05287fab4f9df41161b5ac4155732cd1d232f1dd4d20ebe868c28c768f6ee208bb81cbafc7b3cf0f65caf486bd034bb5ed6e64f4688ba9aedd31a3f66aaa596cc0c1458acddef8350b8ed0cfb1df6d03fc5e9c27959a89be7dc08dd9e3ab9396ae45dcb0d8b08baf15b39ad015a3174e3cdd59f0298413ec07420d9d19c1e589c57147909b7a15a82db19f2b478679ec9c89a65305e5def3afaf2a93c6b61880a912c7fd44c51f4c7421b82d19016c3a42c090ec73563bbbec5cd037cc113fb1cc51ff6cbd949246706a3717adb472f22ea3d75fd488acc507816b409838f34944d19d8af3a9e36c3a61f6139ef3e8d703cbddb85738ca0dec93b32f649e697d44162d182a5728841367d4e459d744e1e810d7584b71b8e615b16e8b88fc7869626d9b68a8c7742f7d53508407a906477ec2138bc73f4d54b53be6c551ce824944dc1f721aaefa6317821d4cf297a67fe71260dbccd64806b7f3fcc2aa60c7781e2fd2edd8158b5cd037d4ae0dbd3bd7c222fd3ea7d16f5c4d383f6f2974824c8ef1eeacf83fee592ead75848219ba10dc88438b2841d51a03a7d8635dbf49aa7b96ac4e81cf6af968245434bc0d3ccbf23f58284ae8d144d187dfee3449c1df472d446142b1659c585ba66dde6ad9fe5e9e237e54670fe298b938999ff7e9f17e98ff71c99c5387cd9a20ced1aebf12493a1eeb0a0e3f3751f1083bc35b4a44c358953643e6fedcc3210c524a6c5a9f02ff676cc979f45558e17319a2d6b2d4fac9f399e46ed094b535d0679c216ba0dbcc2e9bda5fc3f4ef895ff53ad87902127a4d818f1f5434637ff55fcfa0c37ef7797185fa53eefc3ba3792b0e6981c3760d0d7eeae6bdfd850435aaac1110606156cc7063ef20d3491197dccd4b4fb2e 1792
rsa_ct:   abff2aa42a34e246c912b1ec74a10099974c7220c9e46982bcdb36840a71210d8fe52c9e7e2a4fad8febcecedffae052cffab5a219193255264ced7cd085fb78a5630be816d9bebac5f6ee3a908118217f9e0018169e17ae4a992cd6c9400e3c39a6be0330bb9e9085e6f6a88fc74a271bc69072b2ba6902fcc1cd8b87b474e1
kyber_ct: c81cb27253d779f53a0db5f3e28cb95c2c8a6315c127bd35ad0b131d7b30dda702ad610e24d3609dc80ca95691ac7a0477aed4a9b059483753b687512da1148650f4ebce22ab0a8971d2a2c793b80475cd998a2d7e3e93c8607ee0a3d9d43b307fa15d214e12e655eeeeff5b71b91bd8804dff1e8630f09167dfff6e3bfa9ce05287fab4f9df41161b5ac4155732cd1d232f1dd4d20ebe868c28c768f6ee208bb81cbafc7b3cf0f65caf486bd034bb5ed6e64f4688ba9aedd31a3f66aaa596cc0c1458acddef8350b8ed0cfb1df6d03fc5e9c27959a89be7dc08dd9e3ab9396ae45dcb0d8b08baf15b39ad015a3174e3cdd59f0298413ec07420d9d19c1e589c57147909b7a15a82db19f2b478679ec9c89a65305e5def3afaf2a93c6b61880a912c7fd44c51f4c7421b82d19016c3a42c090ec73563bbbec5cd037cc113fb1cc51ff6cbd949246706a3717adb472f22ea3d75fd488acc507816b409838f34944d19d8af3a9e36c3a61f6139ef3e8d703cbddb85738ca0dec93b32f649e697d44162d182a5728841367d4e459d744e1e810d7584b71b8e615b16e8b88fc7869626d9b68a8c7742f7d53508407a906477ec2138bc73f4d54b53be6c551ce824944dc1f721aaefa6317821d4cf297a67fe71260dbccd64806b7f3fcc2aa60c7781e2fd2edd8158b5cd037d4ae0dbd3bd7c222fd3ea7d16f5c4d383f6f2974824c8ef1eeacf83fee592ead75848219ba10dc88438b2841d51a03a7d8635dbf49aa7b96ac4e81cf6af968245434bc0d3ccbf23f58284ae8d144d187dfee3449c1df472d446142b1659c585ba66dde6ad9fe5e9e237e54670fe298b938999ff7e9f17e98ff71c99c5387cd9a20ced1aebf12493a1eeb0a0e3f3751f1083bc35b4a44c358953643e6fedcc3210c524a6c5a9f02ff676cc979f45558e17319a2d6b2d4fac9f399e46ed094b535d0679c216ba0dbcc2e9bda5fc3f4ef895ff53ad87902127a4d818f1f5434637ff55fcfa0c37ef7797185fa53eefc3ba3792b0e6981c3760d0d7eeae6bdfd850435aaac1110606156cc7063ef20d3491197dccd4b4fb2e
rsa_pk:   e976d7efe8fd3ce1c688d8053f8433c136efc7287db31a7b159fa3d17e4b2ceeada589aaa65edb7193ea9ece7281c63ab44a8168fb458685289ccdb260a5734a39c877b90871c77600dd2d3076619dec4830679a5c268ce4f96b310bbeb0b4fa88eda28e66bce07f4474ddcacc2c221a2cccef8f0e60ce6ebfac359efb93736f010001d8998507a14337022cad2bcbcaa77adaa6529006cf2dd355a6283e07c4b0c1e10ebdf43a941c8c7c9aac7d69015a15c267c61f00965939c09902cc9fc18a6a50319318fbae8a2a00ce2a9b8afccb2d77564cc32766d70fc129a957945f78bcaa7bf34188ca3d7d3022597cac3e4c371a1a387854ad65261e556260c3a6100d2b89e0b029e7d9334187a1f7bc1bfcab2f0d988b2b0538428a65312b73ec421917320215790ed42aa3131627ce49a5759b0fbff95abdec1828839655e5618c1023f9f44275ca6cdb5bc73d7ca429f203693ba0c325a4f5933694bc796239b7b4a72650363d80c39d8714947fe204388147c6b7bac11b70d968382f399ac545aad783a1e2f767670ca1a653bf553b9212920dcf91bde862951927754cd504be839561a29b6e1679a0911f4b2a62a6aa27e90a2919c241d4e0ca2a143c0c887fe518b47d845e2d8c38906402517549096
kyber_pk: 4514bf109fc9a2e4979837a8b76240bc592ab09886b5e9dacb4c0a07dcd49ae61986b28103d7230b629c4a331826905777a6d7933b5b21152da7396f82bc269c39f1502e6d414c366bb3d208023b04b3997cb80d19574a594d1b3c3e78409e33657b1e76bce170d9ec46ac2b29abdfbb197c0a221d8cac40c35c70012606a3bb9ca90e37b0a9c206bf1ec52e120122b196c98e06e34223b0519759ca72a8fd3987c1a1a7e80cc3c7926fa6b380c372d12b3c9656b4454c96d5b657b1dca50c46356bcac6d8a687c30a69d394b079c19b14d066eb47b80a37b320e34318fa666976b015463120c447b51cc16fb97ba53421503c021d7d51f7668afacf054886945abb7baf1c569f43a1dd82a556686a353c995404aca138b356af7b5dccba597b14a6dda699a2931f5579d18673da7acbf0d90291ed26330b348b0952413ac205097a910a39fee19c39941b5cb889551755197f877cb7b33d5e63a0cd5260e860c6141132d7b50825211f1b9950f7cbdf01bc2f964b39c376ad547a822a8619d37479f263199a516beba974cc34253d2c6667b2a08345e3e88cf0229c7ce719d96cb0a2ce69d5ba55015c20f589ca4b324afc6a5dc16ef72bd709e0a7fd4b5dbf5ef41760b3b67be0e0ce3804db7ef7b4c6c

rsa_ct1:  a8b3e5fa8c69e2bc89e24bea887401b8a70697b10a46f68b79674bb3761f367eee491c5c261b1562ddada7f97db9e82849146422c56f62904c99dd797182da38c699e3401b2b536c646afa5cc0d144bd1994d4f825fc670be556938dc47f7ea807736e723b75eda1a48e8f7b4f2312c545b884d1172dc6f692dce337977da56c
len(rsa_ct1):  256
rsa_k1:   443d3ed1f6ff820125d94d3787f23f5825c589d650a2405f81a468a3a153a7f4
kyber_ct2: 0b8a9df2eba9e9f6eed77627fb03227de3f8f1652ddcf6169cbbec2c5f30dcb571a807149d7404f898cef0e5d1767c3b3eeb3148bf6320f9a1731c1e2228e55dad275c1b0b2f930a76b53c68afaf963edaffae8b3f036d7f2e4f610f20d1c754ff89d4c094a30f756fc167958313b551fbad55546a306dfd0553e519caea6958f7a72876e0f79073bee3a12b111b98483d3c1e1ce15df2d4c293fb0717ab7adbf138a3ef549ccdefe5be070140369adcc15711167015fbc2c91738968e24468a6e5e63ba8933930401409bf8e0c3a624d4e398a3c7e5105d9829650dd7feb9e36cf9952c683600e3e3fa0b59999e5f5fae9d2c5fb164142f904e872f87b4fcd08bef05413edf5a15d9cd62555629a5094fe5d33702b40753e31173ecf5604a55f96bc01133c4a06be3ca7f1c3403b111b5b3752fd657e2685a6106e63c397cd258ad10df25f833e1f37fd9397c6252df9008287240d69e4c5f7ebe9308495ff5f86a0d7dad00b47a5268c3d6a93f437b4d6bc32a8ed817a54c7d01e60892e769a4d4807780d2b495aaf748c430a7915740b090eaba010b084cefa2017780e539071d3657d1945d1d9811060d890d930109fbfe5b4045846e00342ed10cea90861bc7cfccaea005895bed484ea3a6236cb549692abc15976c1c8bf154522cd71dce257b2e667de63182927e5f5964f52ce305f8e20de0077244119fb1d50ccdd31160fbfbf8f1e926a3693fc64058a238dee8c89a9e40b8559f0877a025957e63cf8df574fa6f3e412ac502eb808e3e5a2cb2ebb4b9d69d07a38425aee0f815dc3fb02ea427dcec4298b59372b9979a64b337cc645cd51862a22d236baa86a8eeb5a02481d45cff6dee6b6cadd76eaf616fda1f620a6b0f124a9537fa1808e85c78d8be5acad1be1602be1105aa858eea65df437e312f0c8cb0107ff2f2b05f1980fdec3a421c89be753c502752a5f4ebee4836c9d52e34c91e750a7f9a395bc116c640c29473379fb5da73447492f2314269751588d2a61acdc5f8eb8428b3434074a30712eec2e76d8c373da242cda6536404bf497f0c09704efb709242e9c7
len(kyber_ct2):  1536
kyber_k2:  64dac59f4771e351aa26387ba6776125800d69dbedb099b5ab828025e3882be9

ct1:      a8b3e5fa8c69e2bc89e24bea887401b8a70697b10a46f68b79674bb3761f367eee491c5c261b1562ddada7f97db9e82849146422c56f62904c99dd797182da38c699e3401b2b536c646afa5cc0d144bd1994d4f825fc670be556938dc47f7ea807736e723b75eda1a48e8f7b4f2312c545b884d1172dc6f692dce337977da56cc81cb27253d779f53a0db5f3e28cb95c2c8a6315c127bd35ad0b131d7b30dda702ad610e24d3609dc80ca95691ac7a0477aed4a9b059483753b687512da1148650f4ebce22ab0a8971d2a2c793b80475cd998a2d7e3e93c8607ee0a3d9d43b307fa15d214e12e655eeeeff5b71b91bd8804dff1e8630f09167dfff6e3bfa9ce05287fab4f9df41161b5ac4155732cd1d232f1dd4d20ebe868c28c768f6ee208bb81cbafc7b3cf0f65caf486bd034bb5ed6e64f4688ba9aedd31a3f66aaa596cc0c1458acddef8350b8ed0cfb1df6d03fc5e9c27959a89be7dc08dd9e3ab9396ae45dcb0d8b08baf15b39ad015a3174e3cdd59f0298413ec07420d9d19c1e589c57147909b7a15a82db19f2b478679ec9c89a65305e5def3afaf2a93c6b61880a912c7fd44c51f4c7421b82d19016c3a42c090ec73563bbbec5cd037cc113fb1cc51ff6cbd949246706a3717adb472f22ea3d75fd488acc507816b409838f34944d19d8af3a9e36c3a61f6139ef3e8d703cbddb85738ca0dec93b32f649e697d44162d182a5728841367d4e459d744e1e810d7584b71b8e615b16e8b88fc7869626d9b68a8c7742f7d53508407a906477ec2138bc73f4d54b53be6c551ce824944dc1f721aaefa6317821d4cf297a67fe71260dbccd64806b7f3fcc2aa60c7781e2fd2edd8158b5cd037d4ae0dbd3bd7c222fd3ea7d16f5c4d383f6f2974824c8ef1eeacf83fee592ead75848219ba10dc88438b2841d51a03a7d8635dbf49aa7b96ac4e81cf6af968245434bc0d3ccbf23f58284ae8d144d187dfee3449c1df472d446142b1659c585ba66dde6ad9fe5e9e237e54670fe298b938999ff7e9f17e98ff71c99c5387cd9a20ced1aebf12493a1eeb0a0e3f3751f1083bc35b4a44c358953643e6fedcc3210c524a6c5a9f02ff676cc979f45558e17319a2d6b2d4fac9f399e46ed094b535d0679c216ba0dbcc2e9bda5fc3f4ef895ff53ad87902127a4d818f1f5434637ff55fcfa0c37ef7797185fa53eefc3ba3792b0e6981c3760d0d7eeae6bdfd850435aaac1110606156cc7063ef20d3491197dccd4b4fb2e
k1:       92aa811f71cad540aa6288b7a9fd25f86a0f026f59de5495db3e9095fe23eb61
ct2:      abff2aa42a34e246c912b1ec74a10099974c7220c9e46982bcdb36840a71210d8fe52c9e7e2a4fad8febcecedffae052cffab5a219193255264ced7cd085fb78a5630be816d9bebac5f6ee3a908118217f9e0018169e17ae4a992cd6c9400e3c39a6be0330bb9e9085e6f6a88fc74a271bc69072b2ba6902fcc1cd8b87b474e10b8a9df2eba9e9f6eed77627fb03227de3f8f1652ddcf6169cbbec2c5f30dcb571a807149d7404f898cef0e5d1767c3b3eeb3148bf6320f9a1731c1e2228e55dad275c1b0b2f930a76b53c68afaf963edaffae8b3f036d7f2e4f610f20d1c754ff89d4c094a30f756fc167958313b551fbad55546a306dfd0553e519caea6958f7a72876e0f79073bee3a12b111b98483d3c1e1ce15df2d4c293fb0717ab7adbf138a3ef549ccdefe5be070140369adcc15711167015fbc2c91738968e24468a6e5e63ba8933930401409bf8e0c3a624d4e398a3c7e5105d9829650dd7feb9e36cf9952c683600e3e3fa0b59999e5f5fae9d2c5fb164142f904e872f87b4fcd08bef05413edf5a15d9cd62555629a5094fe5d33702b40753e31173ecf5604a55f96bc01133c4a06be3ca7f1c3403b111b5b3752fd657e2685a6106e63c397cd258ad10df25f833e1f37fd9397c6252df9008287240d69e4c5f7ebe9308495ff5f86a0d7dad00b47a5268c3d6a93f437b4d6bc32a8ed817a54c7d01e60892e769a4d4807780d2b495aaf748c430a7915740b090eaba010b084cefa2017780e539071d3657d1945d1d9811060d890d930109fbfe5b4045846e00342ed10cea90861bc7cfccaea005895bed484ea3a6236cb549692abc15976c1c8bf154522cd71dce257b2e667de63182927e5f5964f52ce305f8e20de0077244119fb1d50ccdd31160fbfbf8f1e926a3693fc64058a238dee8c89a9e40b8559f0877a025957e63cf8df574fa6f3e412ac502eb808e3e5a2cb2ebb4b9d69d07a38425aee0f815dc3fb02ea427dcec4298b59372b9979a64b337cc645cd51862a22d236baa86a8eeb5a02481d45cff6dee6b6cadd76eaf616fda1f620a6b0f124a9537fa1808e85c78d8be5acad1be1602be1105aa858eea65df437e312f0c8cb0107ff2f2b05f1980fdec3a421c89be753c502752a5f4ebee4836c9d52e34c91e750a7f9a395bc116c640c29473379fb5da73447492f2314269751588d2a61acdc5f8eb8428b3434074a30712eec2e76d8c373da242cda6536404bf497f0c09704efb709242e9c7
k2:       92d8707b187b9c5a6ca3feb5fe540875bd9201d8edaf4150f967a12db5217c1a
ct3:      a8b3e5fa8c69e2bc89e24bea887401b8a70697b10a46f68b79674bb3761f367eee491c5c261b1562ddada7f97db9e82849146422c56f62904c99dd797182da38c699e3401b2b536c646afa5cc0d144bd1994d4f825fc670be556938dc47f7ea807736e723b75eda1a48e8f7b4f2312c545b884d1172dc6f692dce337977da56c0b8a9df2eba9e9f6eed77627fb03227de3f8f1652ddcf6169cbbec2c5f30dcb571a807149d7404f898cef0e5d1767c3b3eeb3148bf6320f9a1731c1e2228e55dad275c1b0b2f930a76b53c68afaf963edaffae8b3f036d7f2e4f610f20d1c754ff89d4c094a30f756fc167958313b551fbad55546a306dfd0553e519caea6958f7a72876e0f79073bee3a12b111b98483d3c1e1ce15df2d4c293fb0717ab7adbf138a3ef549ccdefe5be070140369adcc15711167015fbc2c91738968e24468a6e5e63ba8933930401409bf8e0c3a624d4e398a3c7e5105d9829650dd7feb9e36cf9952c683600e3e3fa0b59999e5f5fae9d2c5fb164142f904e872f87b4fcd08bef05413edf5a15d9cd62555629a5094fe5d33702b40753e31173ecf5604a55f96bc01133c4a06be3ca7f1c3403b111b5b3752fd657e2685a6106e63c397cd258ad10df25f833e1f37fd9397c6252df9008287240d69e4c5f7ebe9308495ff5f86a0d7dad00b47a5268c3d6a93f437b4d6bc32a8ed817a54c7d01e60892e769a4d4807780d2b495aaf748c430a7915740b090eaba010b084cefa2017780e539071d3657d1945d1d9811060d890d930109fbfe5b4045846e00342ed10cea90861bc7cfccaea005895bed484ea3a6236cb549692abc15976c1c8bf154522cd71dce257b2e667de63182927e5f5964f52ce305f8e20de0077244119fb1d50ccdd31160fbfbf8f1e926a3693fc64058a238dee8c89a9e40b8559f0877a025957e63cf8df574fa6f3e412ac502eb808e3e5a2cb2ebb4b9d69d07a38425aee0f815dc3fb02ea427dcec4298b59372b9979a64b337cc645cd51862a22d236baa86a8eeb5a02481d45cff6dee6b6cadd76eaf616fda1f620a6b0f124a9537fa1808e85c78d8be5acad1be1602be1105aa858eea65df437e312f0c8cb0107ff2f2b05f1980fdec3a421c89be753c502752a5f4ebee4836c9d52e34c91e750a7f9a395bc116c640c29473379fb5da73447492f2314269751588d2a61acdc5f8eb8428b3434074a30712eec2e76d8c373da242cda6536404bf497f0c09704efb709242e9c7

rsa_k:    d697bfce873557418fbbc5802e0f1aa04fca8bb9097c14ca5a9af8365f704c95
kyber_k:  f602b5e45f0a7f0bc685c6ce582369503d9f6803001fd8e552e5210856a957f3
k:        48f66b0d56655a47bcdf45bc7fef78470fba0ee0a6cbd9441c55e99a835c5ca0

Well done! The flag is b'ECW{hy6r1d1z4t10n_1s_th3_n3w_tr3nd_n0j2VNbreR0XL5wj}'