# 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**