Déchiffrement de la pièce commémorative de l'ASD
Le 1er septembre 2022, le gouvernement australien a proposé à la vente sur sa boutique officielle en ligne une pièce commémorative des 75 ans de l'ASD (pour Australian Signals Directorate
), qui est un service de renseignement australien ; un genre de NSA dont on ne sait pas grand chose de l'activité si ce n'est qu'il est responsable du renseignement et de la sécurité informatique nationale et également partenaire du programme Echelon.
La description donnée sur la boutique en ligne du gouvernement australien - où la pièce a été victime de son succès et n'est plus trouvable - est la suivante :
The Royal Australian Mint commemorates the 75th anniversary of the ASD with this unique and enigmatic 2022 50c Uncirculated Coin. Embedded in the coin design are four levels of coded messages, and two bonus codes, ready for budding sleuths to crack. Can you break the codes and discover all the secret messages?
Si l'on visite le site de l'ASD on y trouve des informations supplémentaires :
In tribute to the importance of code breaking and evolution of signals intelligence, mulitple layers of cryptographic code have been included in the design of the coin. ASD cryptographic experts collaborated with the Royal Australian Mint to design the coins unique and enigmatic code. A hidden message will be revealed once each layer of code has been cracked. All that is needed is a pen, paper, Wikipedia and brainpower.
Il est également possible d'y trouver des images de la pièce telle qu'elle a été forgée :
Note
On peut apercevoir des caractères géométriques côté pile au centre en bas de la pièce. Des détails sur ces symboles peuvent être trouvés sur le site internet des designers ayant conçu ces visuels pour l'ASD. Ce logo (qui signifie littéralement "ASD") est également présent sur le site de l'ASD et n'a - à priori - par de rapport avec les différents problèmes de déchiffrement présent sur cette pièce.
Déchiffrement du 1er code
Côté face on a un portrait de la Reine Élizabeth II ainsi que le texte suivant :
ELIZABETH II AUSTRALIA 2022 · 50 CENTS
⠉ ⠃⠋ ⠁ ⠑ ⠙
On peut noter que des caractères à priori en braille se trouve sous certaines lettre de la pièce, ce qui donne le tableau de correspondance suivant :
Lettre | Braille | Transcription |
---|---|---|
B | ⠉ | C |
T | ⠃ | B |
H | ⠋ | F |
A | ⠁ | A |
S | ⠑ | E |
A | ⠙ | D |
Après quelque essais on peut remarquer que si l'on ordonne les lettres BTHASA
de la première colonne en fonction de l'ordre alphabétique des lettres en braille de la seconde on obtient :
ATBASH
Cette solution semble faire référence au chiffrement Atbash, une méthode de substitution ou les lettres de l'alphabet sont remplacées par leur équivalent "en miroir" (la lettre A
devient Z
, B
devient Y
, C
devient X
, etc).
Déchiffrement du 2ème code
Côté pile le premier cercle contient la suite de caractère suivante :
·DVZIVZFWZXRLFHRMXLMXVKGZMWNVGRXFOLFHRMVCVXFGRLM·URMWXOZIRGBRM7DRWGSC5WVKGS
On peut constater en effectuant une analyse fréquentielle qu'on a 19 lettres différentes réparties comme suit :
d | v | z | i | f | w | x | r | l | h | m | k | g | n | o | c | u | b | s |
2 | 7 | 5 | 2 | 5 | 5 | 6 | 9 | 4 | 2 | 7 | 2 | 6 | 1 | 2 | 2 | 1 | 1 | 2 |
De nombreuses lettres sont répétées ce qui laisse supposer que ce texte a été chiffré en utilisant une méthode de substitution. En se basant sur l'indice de la précédente épreuve, on peut supposer que le texte est chiffré en utilisant le chiffrement Atbash. Vérifions cette théorie avec quelque lignes de Python :
result = []
alphabet = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
reversed = alphabet[::-1]
for i in list("·DVZIVZFWZXRLFHRMXLMXVKGZMWNVGRXFOLFHRMVCVXFGRLM·URMWXOZIRGBRM7DRWGSC5WVKGS"):
if(i in alphabet):
result.append(reversed[alphabet.index(i)])
else:
result.append(i)
print("".join(result))
On obtient le résultat suivant :
·WEAREAUDACIOUSINCONCEPTANDMETICULOUSINEXECUTION·FINDCLARITYIN7WIDTHX5DEPTH
Qui, si l'on rajoute des espaces, nous donne :
· WE ARE AUDACIOUS IN CONCEPT AND METICULOUS IN EXECUTION · FIND CLARITY IN 7 WIDTH X 5 DEPTH
Déchiffrement du 3ème code
Toujours côté pile le second cercle contient la suite de caractères suivante :
BGOAMVOEIATSIRLNGTTNEOGRERGXNTEAIFCECAIEOALEKFNR5LWEFCHDEEAEEE7NMDRXX5
Une analyse fréquentielle du texte nous donne le résultat suivant :
b | g | o | a | m | v | e | i | t | s | r | l | n | x | f | c | k | w | h | d |
1 | 4 | 4 | 6 | 2 | 1 | 13 | 4 | 4 | 1 | 5 | 3 | 5 | 3 | 3 | 3 | 1 | 1 | 1 | 2 |
La distribution est plutôt cohérente avec un texte non chiffré de cette longueur là, ce qui laisse penser qu'il n'y a pas eu de substitution des lettres du texte mais qu'il faut réordonner celles-ci.
D'après l'indice donné par le précédent déchiffré, il faudrait ré-ordonner les lettres sous forme de matrice 5*7 (sachant que la chaine de caractères contient 70 lettres). Une fois de plus on peut vérifier cette hypothèse facilement avec Python :
text = "BGOAMVOEIATSIRLNGTTNEOGRERGXNTEAIFCECAIEOALEKFNR5LWEFCHDEEAEEE7NMDRXX5"
text = text[0:35]
c = 7
print("\n".join([text[i:i+c] for i in range(0, len(text), c)]))
On obtient le résultat suivant :
BGOAMVO
EIATSIR
LNGTTNE
OGRERGX
NTEAIFC
ECAIEOA
LEKFNR5
LWEFCHD
EEAEEE7
NMDRXX5
On peut remarquer que ce résultat peut être séparé en deux carrés de texte :
BGOAMVO ECAIEOA
EIATSIR LEKFNR5
LNGTTNE LWEFCHD
OGRERGX EEAEEE7
NTEAIFC NMDRXX5
Si on lit ces carrés colonne par colonne on obtient :
BELONGING TO A GREAT TEAM STRIVING FOR EXCELLENCE WE MAKE A DIFFERENCE XOR HEX A5D75
Ce texte nous donne un nouvel indice : un message en hexadécimal peut être décodé en utilisant une fonction XOR avec la clef A5D75
.
Déchiffrement du 4ème code
Dans le tiers inférieur droit du côté pile de la pièce on a les caractères suivant en hexadécimal :
E3B
8287D4
290F723381
4D7A47A291DC
0F71B2806D1A53B
311CC4B97A0E1CC2B9
3B31068593332F10C6A335
2F14D1B27A3514D6F7382F1A
D0B0322955D1B83D3801CDB2
287D05C0B82A311085A03329
1D85A3323855D6BC333119D
6FB7A3C11C4A72E3C17CCB
B33290C85B6343955CCBA3
B3A1CCBB62E341ACBF72
E3255CAA73F2F14D1B27A
341B85A3323855D6BB33
3055C4A53F3C55C7B22
E2A10C0B97A291DC0F
73E3413C3BE392819
D1F73B331185A33
23855CCBA2A3
206D6BE383
1108B
Si l'on prend l'indice de l'étape précédente et que l'on essaye d'appliquer une opération XOR avec les caractères A5D75
répétées sur la chaîne de caractères hexadécimaux présent dans le coin inférieur droit (du côté pile de la pièce), on a :
string = "E3B8287D4290F7233814D7A47A291DC0F71B2806D1A53B311CC4B97A0E1CC2B93B31068593332F10C6A3352F14D1B27A3514D6F7382F1AD0B0322955D1B83D3801CDB2287D05C0B82A311085A033291D85A3323855D6BC333119D6FB7A3C11C4A72E3C17CCBB33290C85B6343955CCBA3B3A1CCBB62E341ACBF72E3255CAA73F2F14D1B27A341B85A3323855D6BB333055C4A53F3C55C7B22E2A10C0B97A291DC0F73E3413C3BE392819D1F73B331185A3323855CCBA2A3206D6BE3831108B"
key = "A5D75"
result = []
for i in range(0, len(string)):
result.append(format(int(string[i], 16) ^ int(key[i % len(key)], 16), "x"))
print(bytearray.fromhex("".join(result)).decode())
Quelques notes sur ce code :
int(string[i], 16)
permet de transformer un caractère hexadécimal en un nombre en base 10- l'utilisation du symbole
^
représente une opération XOR en Python bytearray.fromhex("".join(result)).decode()
transforme notre tableau de résultat en une chaîne de caractères hexadécimale et la décode en ASCII
Par ailleurs, comme expliquer dans la solution de l'épreuve du challenge 6 de cryptopals il est possible de résoudre ce type de problème sans connaitre la clef ni sa longueur.
On obtient le résultat suivant :
For 75 years the Australian Signals Directorate has brought together people with the skills, adaptability and imagination to operate in the slim area between the difficult and the impossible.
Déchiffrement du 5ème code
Côté pile on peut noter que le premier cercle contient des caractères normaux, foncés, ou rayés :
·DVZIVZFWZXRLFHRMXLMXVKGZMWNVGRXFOLFHRMVCVXFGRLM·URMWXOZIRGBRM7DRWGSC5WVKGS
Après de nombreux tests et échecs, je suis arrivé à la conclusion que le chiffrement utilisé était du Morse avec la logique suivante :
- un caractère rayés / souligné (Z, L, M, etc) représente un espace séparant des caractères
- un caractère normal représente un tiret
-
- un caractère foncé (F, H, R, etc) représente un point
.
En faisant cette conversion on obtient le résultat suivant :
·VZIVZFWZXRLFHRMXLMXVKGZMWNVGRXFOLFHRMVCVXFGRLM·URMWXOZIRGBRM7DRWGSC5WVKGS
.---- ----. ....- --... -.. ... -... .- .-.. -... . .-. - .--. .- .-. -.-
On peut écrire du code Python pour essayer de décoder ce message :
morse_code_map = {
".-": "A",
"-...": "B",
"-.-.": "C",
"-..": "D",
".": "E",
"..-.": "F",
"--.": "G",
"....": "H",
"..": "I",
".---": "J",
"-.-": "K",
".-..": "L",
"--": "M",
"-.": "N",
"---": "O",
".--.": "P",
"--.-": "Q",
".-.": "R",
"...": "S",
"-": "T",
"..-": "U",
"...-": "V",
".--": "W",
"-..-": "X",
"-.--": "Y",
"--..": "Z",
".----": "1",
"..---": "2",
"...--": "3",
"....-": "4",
".....": "5",
"-....": "6",
"--...": "7",
"---..": "8",
"----.": "9",
"-----": "0",
}
morse_string = " .---- ----. ....- --... -.. ... -... .- .-.. -... . .-. - .--. .- .-. -.-".split(" ")
result = []
for char in morse_string:
if char in morse_code_map:
result.append(morse_code_map[char])
else:
result.append(char)
print("".join(result))
On obtient le résultat suivant :
1947DSBALBERTPARK
Ces éléments représentent :
1947
: l'année de création de l'ASDDSB
: le nom d'origine de l'ASD (DSB pour "Defence Signals Bureau")ALBERT PARK
: nom de la caserne ou fût fondé l'ASD
Déchiffrement du 6ème code
Si l'on regarde attentivement le cercle intérieur de la pièce côté pile, on peut voir que certains caractères sont écrits avec une teinte plus foncée :
BGOAMVOEIATSIRLNGTTNEOGRERGXNTEAIFCECAIEOALEKFNR5LWEFCHDEEAEEE7NMDRXX5
On peut émettre l'hypothèse que cette alternance entre lettre normal et lettre foncée est un code binaire. Si l'on remplace par 0
les lettres normales et par 1
les lettres foncées on obtient :
0111110010110001110110111100001110100011011001101100111110011011001101
Si l'on utilise Python pour décoder cette suite de caractère binaire en Ascii :
binary_string = b"0111110010110001110110111100001110100011011001101100111110011011001101"
result = []
for i in range(0, len(binary_string), 7):
chunk = binary_string[i:i+7]
ascii_char = chr(int(chunk, 2))
result.append(ascii_char)
print("".join(result))
Le résultat obtenu est une suite de caracètre inintelligible.
Essayons à l'inverse de donner la valeur 1
au caractères normaux et 0
aux caractères foncés :
1000001101001110001001000011110001011100100110010011000001100100110010
Si l'on refait une conversion de binaire à ascii, on obtient :
ASDCbr2022
Le mot Cbr
semble faire référence à l'indicatif de la capitale de l'Australie, Canberra.