# The Enigmatic Playlist There were several pieces to this puzzle, including a Meta, Not Meta, a [playlist](https://defcon.social/@goldbug/110878955315575347), and a [video of the goldbug trophy flashing](https://twitter.com/CryptoVillage/status/1690569834625716224). ## Flashing trophy The long and short flashes could be decoded as morse code to spell `GINLIOYWUMZHJWERMTOEFYMLYTA` This seems to either be a string of garbage, or a ciphertext of sorts. ## Playlist We were unsure how the playlist was related to the puzzle, and solved the meta as a logic puzzle. In hindsight, each of the 15 songs are loosely related to one of the puzzle answers, and the ordering helps with solving the meta. ## Not Meta This gives us a clue of how the meta should work. - There are 26 small rotors containig the letters A-Z marked above some squares, which together also contain the set of all 26 letters. - The reflector and plug board operate like that of an enigma machine, but are otherwise less constrained than the rotors. ## Meta Place the 15 regular puzzle solutions into the spaces given, satisfying the following conditions: 1. Rotors: There are three rotors, each represented by 26 small icons labelled with the letters A-Z. The letters corresponding to these icons must also contain the letters A-Z. 2. Reflectors: There are 13 reflector icons labelled with unique letters, so we made the assumption that these must uniquely correspond to the remaining 13 letters of the alphabet. 3. Plug board: Similar to the reflectors, we assumed that the letters in the plugboard icons must also uniquely correspond to 5 of the remaining letters of the alphabet Consider the "rare" English letters (such as Z, X, and Q). There were only a few of these letters in the puzzle answers, and since each rotor needed to match the full English alphabet, these letters needed to match one of each rotor. Using this together with the reflector rule gave us enough constraints to solve the puzzle manually. After placing all 15 answers into their correct positions, the icons, Start Pos, and Turnover labels give the configuration for an enigma machine. We plugged these configurations into a python enigma encoder we found online. ```python #Enigma Encoder - www.101computing.net/enigma-encoder/ # ----------------- Enigma Settings ----------------- rotors = ("I","II","III") reflector = "UKW-B" ringSettings ="AAA" ringPositions = "IRH" plugboard = "FD JI RM VT XA" # --------------------------------------------------- def caesarShift(str, amount): output = "" for i in range(0,len(str)): c = str[i] code = ord(c) if ((code >= 65) and (code <= 90)): c = chr(((code - 65 + amount) % 26) + 65) output = output + c return output def encode(plaintext): global rotors, reflector,ringSettings,ringPositions,plugboard #Enigma Rotors and reflectors rotor1 = "LSGVURXTABQFCOMHNIEJDWPYKZ" rotor1Notch = "E" rotor2 = "ENQHFOSBUWKZLXMDCYIVPAGJRT" rotor2Notch = "S" rotor3 = "KHYVRAFDBQPWTLZCXUNJSOMEIG" rotor3Notch = "O" rotorDict = {"I":rotor1,"II":rotor2,"III":rotor3} rotorNotchDict = {"I":rotor1Notch,"II":rotor2Notch,"III":rotor3Notch} reflectorStr = "QY VF DM XU JA RK WI EP SG NB LC HO ZT" reflectorDict = {**{a:b for a,b in reflectorStr.split(" ")}, **{b:a for a,b in reflectorStr.split(" ")}} alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" rotorANotch = False rotorBNotch = False rotorCNotch = False #A = Left, B = Mid, C=Right rotorA = rotorDict[rotors[0]] rotorB = rotorDict[rotors[1]] rotorC = rotorDict[rotors[2]] rotorANotch = rotorNotchDict[rotors[0]] rotorBNotch = rotorNotchDict[rotors[1]] rotorCNotch = rotorNotchDict[rotors[2]] rotorALetter = ringPositions[0] rotorBLetter = ringPositions[1] rotorCLetter = ringPositions[2] rotorASetting = ringSettings[0] offsetASetting = alphabet.index(rotorASetting) rotorBSetting = ringSettings[1] offsetBSetting = alphabet.index(rotorBSetting) rotorCSetting = ringSettings[2] offsetCSetting = alphabet.index(rotorCSetting) rotorA = caesarShift(rotorA,offsetASetting) rotorB = caesarShift(rotorB,offsetBSetting) rotorC = caesarShift(rotorC,offsetCSetting) if offsetASetting>0: rotorA = rotorA[26-offsetASetting:] + rotorA[0:26-offsetASetting] if offsetBSetting>0: rotorB = rotorB[26-offsetBSetting:] + rotorB[0:26-offsetBSetting] if offsetCSetting>0: rotorC = rotorC[26-offsetCSetting:] + rotorC[0:26-offsetCSetting] ciphertext = "" #Converplugboard settings into a dictionary plugboardConnections = plugboard.upper().split(" ") plugboardDict = {} for pair in plugboardConnections: if len(pair)==2: plugboardDict[pair[0]] = pair[1] plugboardDict[pair[1]] = pair[0] plaintext = plaintext.upper() for letter in plaintext: encryptedLetter = letter if letter in alphabet: #Rotate Rotors - This happens as soon as a key is pressed, before encrypting the letter! rotorTrigger = False #Third rotor rotates by 1 for every key being pressed if rotorCLetter == rotorCNotch: rotorTrigger = True rotorCLetter = alphabet[(alphabet.index(rotorCLetter) + 1) % 26] #Check if rotorB needs to rotate if rotorTrigger: rotorTrigger = False if rotorBLetter == rotorBNotch: rotorTrigger = True rotorBLetter = alphabet[(alphabet.index(rotorBLetter) + 1) % 26] #Check if rotorA needs to rotate if (rotorTrigger): rotorTrigger = False rotorALetter = alphabet[(alphabet.index(rotorALetter) + 1) % 26] else: #Check for double step sequence! if rotorBLetter == rotorBNotch: rotorBLetter = alphabet[(alphabet.index(rotorBLetter) + 1) % 26] rotorALetter = alphabet[(alphabet.index(rotorALetter) + 1) % 26] #Implement plugboard encryption! if letter in plugboardDict.keys(): if plugboardDict[letter]!="": encryptedLetter = plugboardDict[letter] #Rotors & Reflector Encryption offsetA = alphabet.index(rotorALetter) offsetB = alphabet.index(rotorBLetter) offsetC = alphabet.index(rotorCLetter) # Wheel 3 Encryption pos = alphabet.index(encryptedLetter) let = rotorC[(pos + offsetC)%26] pos = alphabet.index(let) encryptedLetter = alphabet[(pos - offsetC +26)%26] # Wheel 2 Encryption pos = alphabet.index(encryptedLetter) let = rotorB[(pos + offsetB)%26] pos = alphabet.index(let) encryptedLetter = alphabet[(pos - offsetB +26)%26] # Wheel 1 Encryption pos = alphabet.index(encryptedLetter) let = rotorA[(pos + offsetA)%26] pos = alphabet.index(let) encryptedLetter = alphabet[(pos - offsetA +26)%26] # Reflector encryption! if encryptedLetter in reflectorDict.keys(): if reflectorDict[encryptedLetter]!="": encryptedLetter = reflectorDict[encryptedLetter] #Back through the rotors # Wheel 1 Encryption pos = alphabet.index(encryptedLetter) let = alphabet[(pos + offsetA)%26] pos = rotorA.index(let) encryptedLetter = alphabet[(pos - offsetA +26)%26] # Wheel 2 Encryption pos = alphabet.index(encryptedLetter) let = alphabet[(pos + offsetB)%26] pos = rotorB.index(let) encryptedLetter = alphabet[(pos - offsetB +26)%26] # Wheel 3 Encryption pos = alphabet.index(encryptedLetter) let = alphabet[(pos + offsetC)%26] pos = rotorC.index(let) encryptedLetter = alphabet[(pos - offsetC +26)%26] #Implement plugboard encryption! if encryptedLetter in plugboardDict.keys(): if plugboardDict[encryptedLetter]!="": encryptedLetter = plugboardDict[encryptedLetter] ciphertext = ciphertext + encryptedLetter return ciphertext #Main Program Starts Here print(" ##### Enigma Encoder #####") print("") plaintext = input("Enter text to encode or decode:\n") ciphertext = encode(plaintext) print("\nEncoded text: \n " + ciphertext) ``` This could then be used to decrypt the ciphertext from before. ``` $ python3 enigma.py ##### Enigma Encoder ##### Enter text to encode or decode: GINLIOYWUMZHJWERMTOEFYMLYTA Encoded text: SHORTXDISTANCEXPLENTYXTOXDO ``` ::: spoiler Answer **SHORT DISTANCE PLENTY TO DO**