Skip to content

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)=Encaps(pk)(k, c) = \text{Encaps}(pk): The encapsulation algorithm takes a public key pkpk and returns a shared secret key kk, and the encrypted secret key cc.
  • k=Decaps(c,sk)k = \text{Decaps}(c, sk): The decapsulation algorithm takes a ciphertext cc and a secret key sksk and returns the shared secret key kk.

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, WW is a combiner function that takes the two shared secret keys k1k1 and k2k2, and the ciphertext cc and returns the shared secret key kk. 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 cc into crsac_{rsa} and ckyberc_{kyber} and the public key pkpk into pkrsapk_{rsa} and pkkyberpk_{kyber}: pk=pkrsapkkyberpk = pk_{rsa} || pk_{kyber} c=crsackyberc = c_{rsa} || c_{kyber}
    1. Use the RSA and Kyber encapsulation services to get new key encapsulations: k1rsa,c1rsa=Encaps1(pkrsa)k1_{rsa}, c1_{rsa} = \text{Encaps1}(pk_{rsa}) k1kyber,c1kyber=Encaps2(pkkyber)k1_{kyber}, c1_{kyber} = \text{Encaps2}(pk_{kyber})
    1. Combine them with the original ciphertext, and combine them together: c2=c1rsackyberc2 = c1_{rsa} || c_{kyber} c3=crsac1kyberc3 = c_{rsa} || c1_{kyber} c4=c1rsac1kyberc4 = c1_{rsa} || c1_{kyber}
    1. Use the Decapsulation Oracle on c2c2 and c3c3 to get the shared secret keys k2k2 and k3k3 k2=Decaps(c2)k2 = \text{Decaps}(c2) k3=Decaps(c3)k3 = \text{Decaps}(c3) k4=Decaps(c4)k4 = \text{Decaps}(c4)
    1. XOR k2k2 and k3k3 to get the shared secret key kk (and xor with k4k4 to “remove” the added components in k2k2 and k3k3): k=k2k3k4k = 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}'