{"id":95,"date":"2022-10-24T06:16:18","date_gmt":"2022-10-24T06:16:18","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/paul\/?p=95"},"modified":"2022-10-24T06:37:41","modified_gmt":"2022-10-24T06:37:41","slug":"writeup-super_otp","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/paul\/2022\/10\/24\/writeup-super_otp\/","title":{"rendered":"Writeup: super_otp"},"content":{"rendered":"\n<p>One time pads are perfectly secure.<sup>*<\/sup> Here is an example of an extra perfectly secure<sup>\u2020<\/sup> implementation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># get 3 one time pads\notps = &#091;urandom(MAX_LENGTH) for _ in range(3)]\n\n# combine the one time pads into a \"super\" one time pad\nsuper_otp = xor_list(otps)\n\n# encrypt the flag using the super one time pad\nenc_flag = xor_bytes(FLAG.encode(), super_otp)\n\n# print out the encrypted flag\nprint(f'The encrypted flag in base 64:')\nprint(b64encode(enc_flag).decode())\n\nfor otp in otps:\n    # get the message that the user wants to encrypt (up to 60 characters)\n    print('Enter message you would like to encrypt (input truncated to 60 characters): ')\n    user_message = str(input())&#091;:60]\n\n    # encrypt the message using xor\n    enc_message = xor_bytes(user_message.encode(), otp)\n\n    # print encrypted message\n    print(f'Your encrypted message is in base 64:')\n    print(b64encode(enc_message).decode())<\/code><\/pre>\n\n\n\n<p>If I had a nickel for every time this challenge reused a key, I&#8217;d have zero nickels. Which isn&#8217;t a lot, but &#8211; wait a second, zero nickels? We don&#8217;t reuse the key at all? So it&#8217;s perfectly secure?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The encrypted flag in base 64:LtVYq6Y989bBhQ4S4hEJ8NgsOzNUs1DxJy6YEyAoEnter message you would like to encrypt (input truncated to 60 characters): NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\nYour encrypted message is in base 64:\nWyn1xCotf77chnIDI5qvv2ttfdR7sfe4ylx3jbma34PUk70ngFUJQDaIO3WWmg5YdznQdlZjn9DiEnter message you would like to encrypt (input truncated to 60 characters): NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\nYour encrypted message is in base 64:\nwgL55ruDV80AgYSPD2Ec0xDA8JYgp+\/WpaC7qkKb4NJ45bAkILw66ZfnwNigbI9d0rAMBfqR7dSv\nEnter message you would like to encrypt (input truncated to 60 characters): NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\nYour encrypted message is in base 64:lsJuvRa54tkgkuXi9PawjKOgymF3g0rjWM1bP7AbjGnNfvawy38iA+TuTDvc9Wejj5KWrto5s<\/code><\/pre>\n\n\n\n<p>OK, so it&#8217;s sort of reused. But more importantly, we can control the plaintext. He who controls the plaintext, controls the key. Or at least can figure out what the key is.<\/p>\n\n\n\n<p>Anyways, one aspect of OTP&#8217;s is that the key and plaintext are interchangeable. If you know the plaintext, you can XOR it with the ciphertext and it will reveal the key. Similarly, XORing &#8220;any bytes&#8221; with null bytes results in &#8220;any bytes.&#8221; That was a confusing way to say that XOR does nothing when one or more sides is a 0. So if we send 60 null bytes instead of &#8220;NOOOOOO&#8221;, we get to see what the key for each message was.<\/p>\n\n\n\n<p>With that, we send 60 null bytes to see what the key for each message was<\/p>\n\n\n\n<p>Then, we XOR them together.<\/p>\n\n\n\n<p>Then, we XOR that with the bytes of the flag.<\/p>\n\n\n\n<p>Then, we have the flag in plaintext.<\/p>\n\n\n\n<p>Submitting osu{nev3r_R3uSE_On3_7iM3_P@D$} completes the challenge!<\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-verse\">* Unless they're part of a CTF challenge<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>One time pads are perfectly secure.* Here is an example of an extra perfectly secure\u2020 implementation. If I had a nickel for every time this challenge reused a key, I&#8217;d have zero nickels. Which isn&#8217;t a lot, but &#8211; wait a second, zero nickels? We don&#8217;t reuse the key at all? So it&#8217;s perfectly secure? &hellip; <a href=\"https:\/\/blogs.oregonstate.edu\/paul\/2022\/10\/24\/writeup-super_otp\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Writeup: super_otp<\/span><\/a><\/p>\n","protected":false},"author":11809,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-95","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/95","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/users\/11809"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/comments?post=95"}],"version-history":[{"count":3,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/95\/revisions"}],"predecessor-version":[{"id":99,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/95\/revisions\/99"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/media?parent=95"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/categories?post=95"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/tags?post=95"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}