In 1605 ontwikkelde de Britse filosoof, wetenschapper en politicus Francis Bacon1 een versleutelingsmethode die een geheime tekst kan verbergen in een tekst die er op het eerst gezicht volledig normaal uitziet. Deze baconversleuteling werkt in twee stappen.
Bij het coderen wordt elke letter van de geheime tekst eerst vertaald naar een unieke groep van vijf symbolen uit een alfabet met twee symbolen. In bovenstaande figuur zie je bijvoorbeeld de sleutel met een alfabet van twee symbolen (a en b) die Francis Bacon gebruikte in zijn werk De Augmentis Scientiarum2 (1605). Omdat het ging om een werk in het Latijn, was het gebruikelijk om de letters i en j aan elkaar gelijk te stellen, net zoals de letters u en v.
Aangezien het gaat om een binaire codering die gebruik maakt van twee symbolen op vijf posities, kunnen er dus in totaal $$2^5 = 32$$ karakters gecodeerd worden. Het is dus ook perfect mogelijk om de Baconversleuteling toe te passen met een sleutel die elk van de 26 letters uit ons alfabet op een unieke manier codeert, en bovendien nog ruimte laat voor 6 extra karakters (bijvoorbeeld een spatie en enkele leestekens).
In tweede instantie wordt een willekeurige tekst gekozen of verzonnen, die wordt uitgeschreven aan de hand van twee verschillende lettertypes. Het ene lettertype komt dan bijvoorbeeld overeen met het symbool a, en het andere lettertype met het symbool b uit de vorige stap. Hierbij maakt het dus niet uit welke letter gebruikt wordt, enkel het lettertype wordt gebruikt voor de code. In bovenstaande figuur zie je de lettertypes die Francis Bacon gebruikte. Om te verhullen dat het om een gecodeerd bericht ging, maakte hij gebruik van twee lettertypes die vaak slechts op een subtiele manier van elkaar verschillen. In een handschrift valt een codering met twee nagenoeg gelijke lettertypes immers haast niet op.
In plaats van te spelen met lettertypes, zou je bijvoorbeeld ook het symbool a kunnen voorstellen door kleine letters, en het symbool b door hoofdletters. Laat ons dat eens toepassen in een voorbeeld waarin we het woord ALICE willen versleutelen. In eerste instantie vervangen we elke letter door een reeks van vijf a's of b's:
A L I C E aaaaa ababb abaaa aaaba aabaa
Daarna coderen we deze boodschap aan de hand van kleine letters (voor symbool a) en hoofdletters (voor symbool b) in de tekst Draco Dormiens Numquam Titillandus:
aaaaa ababb abaaa aaaba aabaa draco dOrMI eNsnu mquAm tiTil
Om het principe nog duidelijker te illustreren, hebben we hierbij alle hoofdletters en de corresponderende symbolen b in het vet weergegeven.
Voor het toepassen van de Baconversleuteling leggen we de omzetting van elk van de 26 letters van ons alfabet naar een unieke code van 5 symbolen vast in een tekstbestand. Elke regel van het bestand begint met een hoofdletter, gevolgd door een spatie, de unieke code van 5 symbolen uit het alfabet {a, b}, nog een spatie, en dezelfde unieke code maar dan met 5 symbolen uit het alfabet {0, 1}. Hieronder zie je een voorbeeld van een dergelijk tekstbestand (beperkt tot de eerste regels):
A aaaaa 00000 B aaaab 00001 C aaaba 00010 D aaabb 00011 E aabaa 00100 F aabab 00101 …
Gevraagd wordt:
Schrijf een functie leesSleutel waaraan de locatie van een tekstbestand moet doorgegeven worden. Het gegeven tekstbestand moet een afbeelding bevatten van alle letters van het alfabet naar hun corresponderende code bestaande uit 5 symbolen uit een binair alfabet, in het formaat dat hierboven omschreven wordt. De functie moet een dictionary teruggeven die elke hoofdletter van ons alfabet afbeeldt op de corresponderende code met symbolen uit het alfabet {a, b}, zoals vastgelegd in het gegeven tekstbestand.
Schrijf een functie codeer waaraan twee argumenten moeten doorgegeven worden: i) een dictionary die alle hoofdletters van het alfabet afbeeldt op een unieke code bestaande uit 5 symbolen uit het alfabet {a, b} (cfr. de dictionaries die worden teruggegeven door de functie leesSleutel) en ii) een bericht (string) dat moet gecodeerd worden. De functie heeft ook nog een optionele derde parameter waaraan een tekst (string) kan doorgegeven worden. De functie moet door middel van Baconversleuteling het gegeven bericht coderen in de gegeven tekst, door een binaire code van hoofdletters en kleine letters te gebruiken. Hierbij wordt enkel rekening gehouden met de letters in de gegeven tekst en het gegeven bericht (alle karakters die geen letter zijn moeten genegeerd worden), en wordt geen onderscheid gemaakt tussen hoofdletters en kleine letters in het gegeven bericht. Indien de gegeven tekst te kort is om het gegeven bericht in te coderen, dan volgt na de laatste letter van de tekst gewoon terug de eerste letter van de tekst. Indien geen tekst wordt doorgegeven aan de optionele derde parameter, of indien de gegeven tekst geen enkele letter bevat, dan moet het bericht gecodeerd worden in een willekeurige string van letters.
Schrijf een functie decodeer waaraan twee argumenten moeten doorgegeven worden: i) een dictionary die alle hoofdletters van het alfabet afbeeldt op een unieke code bestaande uit 5 symbolen uit het alfabet {a, b} (cfr. de dictionaries die worden teruggegeven door de functie leesSleutel) en ii) een bericht (string) dat met behulp van de functie codeer gecodeerd werd (op basis van de gegeven dictionary). De functie moet de letters van de originele versie van het bericht teruggeven, in hoofdletters.
Bij onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand sleutel.txt3 zich in de huidige directory bevindt.
>>> sleutel = leesSleutel('sleutel.txt')
>>> sleutel['A']
'aaaaa'
>>> sleutel['Z']
'bbaab'
>>> codeer(sleutel, 'ALICE', 'Draco Dormiens Numquam Titillandus')
'dracodOrMIeNsnumquAmtiTil'
>>> codeer(sleutel, 'ALICE', 'Ora Et Labora')
'oraetlAbORaOraetlaBoraOra'
>>> codeer(sleutel, 'ALICE')
'obthizZhBQwAatlmjrChikWwe'
>>> codeer(sleutel, 'ALICE')
'pwsychLwVIeRqiuxtwKcxqLtn'
>>> decodeer(sleutel, 'dracodOrMIeNsnumquAmtiTil')
'ALICE'
>>> decodeer(sleutel, 'oraetlAbORaOraetlaBoraOra')
'ALICE'
>>> decodeer(sleutel, 'obthizZhBQwAatlmjrChikWwe')
'ALICE'
>>> decodeer(sleutel, 'pwsychLwVIeRqiuxtwKcxqLtn')