{"id":1086,"date":"2016-08-04T19:29:42","date_gmt":"2016-08-05T02:29:42","guid":{"rendered":"http:\/\/technofovea.com\/blog\/?p=1086"},"modified":"2016-08-11T22:51:13","modified_gmt":"2016-08-12T05:51:13","slug":"1086","status":"publish","type":"post","link":"http:\/\/technofovea.com\/blog\/archives\/1086","title":{"rendered":"Uncertain Base64 &#8211; Overwatch Puzzle"},"content":{"rendered":"<p>As I mentioned in yesterday&#8217;s post, there&#8217;s an Overwatch graphic of some base64 text with an unclear font&#8230; But what&#8217;s the point of writing something to solve a puzzle when you aren&#8217;t sure you have the right question?<br \/>\n<a href=\"http:\/\/technofovea.com\/blog\/wp-content\/uploads\/2016\/08\/owhint_vague.png\"><img loading=\"lazy\" src=\"http:\/\/technofovea.com\/blog\/wp-content\/uploads\/2016\/08\/owhint_vague-300x75.png\" alt=\"Overwatch Base64 Issues\" width=\"300\" height=\"75\" class=\"aligncenter size-medium wp-image-1094\" srcset=\"http:\/\/technofovea.com\/blog\/wp-content\/uploads\/2016\/08\/owhint_vague-300x75.png 300w, http:\/\/technofovea.com\/blog\/wp-content\/uploads\/2016\/08\/owhint_vague.png 753w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nSo I made this little function which takes a base64-string and generates visually-similar versions:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/python\r\nimport itertools\r\nimport binascii\r\n\r\ndef B64Variants(val, confusions = None):\r\n    if confusions is None:\r\n        confusions = [&quot;Il1&quot;,&quot;O0&quot;] # Use defaults\r\n    val = val.translate(None, &quot; \\n\\t&quot;) # Remove whitespace\r\n    sections = []        \r\n    for char in val:\r\n        confused = False\r\n        for group in confusions:\r\n            if char in group:\r\n                confused = True                \r\n                sections.append(list(group))\r\n                \r\n        if not confused:   \r\n            if (len(sections) &gt; 0) and isinstance(sections[-1],str):\r\n                sections[-1] = sections[-1] + char\r\n            else:\r\n                sections.append(char)       \r\n    # Tidy up so we have a consistent list-of-lists\r\n    for i,v in enumerate(sections):\r\n        if isinstance(v,str):\r\n            sections[i] = [v]                \r\n    for varBits in apply(itertools.product, sections):\r\n        yield &quot;&quot;.join(varBits)\r\n\r\nif __name__ == &quot;__main__&quot;:\r\n    sample = binascii.b2a_base64(&quot;Hello, World!&quot;)\r\n    print &quot;given&quot;, sample\r\n    for var in B64Variants(sample):\r\n        print &quot;maybe&quot;, var    \r\n<\/pre>\n<p>Example output:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ngiven SGVsbG8sIFdvcmxkIQ==\r\n\r\nmaybe SGVsbG8sIFdvcmxkIQ==\r\nmaybe SGVsbG8sIFdvcmxklQ==\r\nmaybe SGVsbG8sIFdvcmxk1Q==\r\nmaybe SGVsbG8slFdvcmxkIQ==\r\nmaybe SGVsbG8slFdvcmxklQ==\r\nmaybe SGVsbG8slFdvcmxk1Q==\r\nmaybe SGVsbG8s1FdvcmxkIQ==\r\nmaybe SGVsbG8s1FdvcmxklQ==\r\nmaybe SGVsbG8s1Fdvcmxk1Q==\r\n<\/pre>\n<p>I think the next step is to try hooking this up to code which tries to decode the cipher-stream byte by byte, skipping to a new password (or a new Base64 source-string) when the decoded byte goes outside conventional ASCII. (I&#8217;m gambling that it&#8217;ll contain an ASCII message, if it doesn&#8217;t then it&#8217;s hard to know if you&#8217;ve successfully cracked it.)<\/p>\n<p>Finally, what happens if we apply this to one of the transcriptions people have made from the Overwatch Summer Games video? <\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nU2FsdGVkXI+vupppZksvRf5pq5g5XjFRIipRkwBOKIY96Qsv2Lm+3IcmzaAILwytX\/z66ZVWEQMccfIg+9m5UbuI+sit+A9cenDxxqkIaxbm4cMeh2oKhqIHhdaBKOi6XX2XDWpa6+P5o9MQw==\r\nU2FsdGVkXI+vupppZksvRf5pq5g5XjFRIipRkwBOKIY96Qsv2Lm+3IcmzaAILwytX\/z66ZVWEQMccfIg+9m5UbuI+sit+A9cenDxxqkIaxbm4cMeh2oKhqIHhdaBK0i6XX2XDWpa6+P5o9MQw==\r\nU2FsdGVkXI+vupppZksvRf5pq5g5XjFRIipRkwBOKIY96Qsv2Lm+3IcmzaAILwytX\/z66ZVWEQMccfIg+9m5UbuI+sit+A9cenDxxqkIaxbm4cMeh2oKhqlHhdaBKOi6XX2XDWpa6+P5o9MQw==\r\nU2FsdGVkXI+vupppZksvRf5pq5g5XjFRIipRkwBOKIY96Qsv2Lm+3IcmzaAILwytX\/z66ZVWEQMccfIg+9m5UbuI+sit+A9cenDxxqkIaxbm4cMeh2oKhqlHhdaBK0i6XX2XDWpa6+P5o9MQw==\r\nU2FsdGVkXI+vupppZksvRf5pq5g5XjFRIipRkwBOKIY96Qsv2Lm+3IcmzaAILwytX\/z66ZVWEQMccfIg+9m5UbuI+sit+A9cenDxxqkIaxbm4cMeh2oKhq1HhdaBKOi6XX2XDWpa6+P5o9MQw==\r\n..snip..\r\n<\/pre>\n<p>78,732 variations in total. Uh oh. I&#8217;m happy with the output, but whatever I use to go through these, it needs to be able to memoize or somehow reuse whatever progress it can from variant-to-variant, rather than starting over with each new string. <\/p>\n<h3>P.S.<\/h3>\n<p>A more-realistic number would be <strong>6,561<\/strong>, since we know that the first <code>1<\/code> is good because it&#8217;s part of the OpenSSL header, and because the letter <code>O<\/code> is visibly wider than zero.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As I mentioned in yesterday&#8217;s post, there&#8217;s an Overwatch graphic of some base64 text with an unclear font&#8230; But what&#8217;s the point of writing something to solve a puzzle when you aren&#8217;t sure you have the right question? So I made this little function which takes a base64-string and generates visually-similar versions: Example output: I [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,4],"tags":[30,26],"_links":{"self":[{"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/posts\/1086"}],"collection":[{"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/comments?post=1086"}],"version-history":[{"count":9,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/posts\/1086\/revisions"}],"predecessor-version":[{"id":1118,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/posts\/1086\/revisions\/1118"}],"wp:attachment":[{"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/media?parent=1086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/categories?post=1086"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/technofovea.com\/blog\/wp-json\/wp\/v2\/tags?post=1086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}