Exercice 1 — Migration IPv4 → IPv6
Validation, classification et conversion d'adresses IPv4
Étant donné un fichier texte F_IPV4.txt contenant une adresse IPv4 par ligne, on souhaite vérifier la validité de chaque adresse, déterminer sa classe, la convertir en IPv6 et écrire les résultats dans F_IPV6.txt.
W.X.Y.Z avec W, X, Y, Z ∈ [0, 255].Classes selon les bits de poids fort de W :
| Classe | Bits de début de W | Plage W | Usage |
|---|---|---|---|
| A | 0xxxxxxx | 0–127 | Grands réseaux |
| B | 10xxxxxx | 128–191 | Réseaux moyens |
| C | 110xxxxx | 192–223 | Petits réseaux |
| D | 1110xxxx | 224–239 | Multicast |
| E | 1111xxxx | 240–255 | Réservé |
WXHEX + XXHEX : YXHEX + ZXHEX (le : est inséré au milieu).Exemple : 155.105.50.68
155 →
9B, 105 → 69, 50 → 32, 68 → 44→ Bloc IPv6 : 9B69:3244
Travail demandé :
- Fonction valide(ip) — vérifier la validité d'une adresse IPv4
- Fonction classe(ip) — retourner la classe (A–E) d'une adresse valide
- Fonction adresseip6(ip) — convertir une IPv4 en bloc IPv6
- Fonction Genere() — générer le fichier
F_IPV6.txt
bin(nb) → représentation binaire (ex: bin(155) → '0b10011011')hex(nb) → représentation hexadécimale (ex: hex(155) → '0x9b')Pour enlever le préfixe :
bin(nb)[2:] et hex(nb)[2:].upper()Genere() → valide() → classe() + adresseip6()La fonction auxiliaire
binaire(nb) produit une représentation binaire sur 8 bits (avec zéros de remplissage).def valide(ip):
"""Vérifie si l'adresse IPv4 est valide (4 octets dans [0,255])."""
ad = ip.split('.')
if len(ad) == 4:
if 0 <= int(ad[0]) <= 255 and 0 <= int(ad[1]) <= 255 \
and 0 <= int(ad[2]) <= 255 and 0 <= int(ad[3]) <= 255:
return True
else:
return False
else:
return False
def binaire(nb):
"""Convertit un entier en binaire sur 8 bits (avec zéros de remplissage)."""
val = ['0'] * 8
binn = bin(int(nb)) # ex : '0b10011011'
i = len(val) - len(binn[2:])
for lettre in binn[2:]:
val[i] = lettre
i += 1
return ''.join(val) # ex : '10011011'
def classe(ip):
"""Retourne la classe (A–E) d'une adresse IPv4 valide."""
if valide(ip):
ad = ip.split('.')
binn = binaire(ad[0])
if binn[0] == '0':
return 'A'
elif binn[:2] == '10':
return 'B'
elif binn[:3] == '110':
return 'C'
elif binn[:4] == '1110':
return 'D'
else:
return 'E'
else:
return False
def adresseip6(ip):
"""Convertit une IPv4 valide en bloc IPv6 (32 bits hexadécimaux)."""
if valide(ip):
ad = ip.split('.')
# hex()[2:] enlève le préfixe '0x'
bloc = (hex(int(ad[0]))[2:] + hex(int(ad[1]))[2:]
+ ':' + hex(int(ad[2]))[2:] + hex(int(ad[3]))[2:])
return bloc + '\n'
else:
return ''
def Genere():
"""Lit F_IPV4.txt et génère F_IPV6.txt avec les adresses valides."""
source = open('F_IPV4.txt', 'r')
dest = open('F_IPV6.txt', 'a')
for ligne in source:
ip = ligne.strip()
if valide(ip):
chaine = ip + ' : ' + classe(ip) + ' : ' + adresseip6(ip)
dest.write(chaine)
source.close()
dest.close()
# Test manuel
print(valide("155.105.50.68")) # True
print(classe("155.105.50.68")) # B
print(adresseip6("155.105.50.68")) # 9b69:3244def valide(ip):
"""
Version robuste : gère les erreurs de conversion (try/except).
"""
try:
parties = ip.strip().split('.')
if len(parties) != 4:
return False
return all(0 <= int(p) <= 255 for p in parties)
except ValueError:
return False
def classe(ip):
"""
Version simplifiée : utilise directement la valeur entière de W.
Plus lisible que la comparaison bit à bit.
"""
if not valide(ip):
return False
w = int(ip.split('.')[0])
if w < 128: return 'A' # 0xxxxxxx
if w < 192: return 'B' # 10xxxxxx
if w < 224: return 'C' # 110xxxxx
if w < 240: return 'D' # 1110xxxx
return 'E' # 1111xxxx
def adresseip6(ip):
"""
Version avec format 2 chiffres hex (zfill) pour une représentation correcte.
Ex : 255.0.1.10 → ff00:010a (et non ff0:010a)
"""
if not valide(ip):
return ''
w, x, y, z = [int(p) for p in ip.strip().split('.')]
h = lambda n: hex(n)[2:].zfill(2).upper() # toujours 2 chiffres
return f"{h(w)}{h(x)}:{h(y)}{h(z)}"
def Genere():
"""Version with context managers (fermeture automatique des fichiers)."""
with open('F_IPV4.txt', 'r') as source, open('F_IPV6.txt', 'w') as dest:
for ligne in source:
ip = ligne.strip()
if valide(ip):
dest.write(f"{ip} : {classe(ip)} : {adresseip6(ip)}\n")
# Tests
adresses = ["155.105.50.68", "10.0.0.1", "192.168.1.1",
"225.0.0.1", "256.1.1.1", "abc.def.ghi.jkl"]
for a in adresses:
if valide(a):
print(f"{a:20} | Classe {classe(a)} | IPv6 : {adresseip6(a)}")
else:
print(f"{a:20} | INVALIDE")155.105.50.68 | Classe B | IPv6 : 9B69:3244 10.0.0.1 | Classe A | IPv6 : 0A00:0001 192.168.1.1 | Classe C | IPv6 : C0A8:0101 225.0.0.1 | Classe D | IPv6 : E100:0001 256.1.1.1 | INVALIDE abc.def.ghi.jkl | INVALIDE
hex(int(ad[0]))[2:] qui peut produire un seul chiffre pour des valeurs < 16 (ex: hex(10) = '0xa' → 'a' au lieu de '0a'). Utiliser .zfill(2) garantit toujours 2 chiffres.155.105.50.68
155.105.50.68 : B : 9B69:3244
10011011₂ → bits 10 → Classe B. 155→9B, 105→69, 50→32, 68→44 → bloc 9B69:3244.Exercice 2 — Chiffrement de Polybe
Crypter et décrypter un message avec le carré de Polybe
Règles de construction de la matrice :
- Placer les lettres du mot-clé en premier (sans doublons).
- Compléter avec les lettres restantes de l'alphabet, dans l'ordre, sauf 'W'.
- 'W' dans le message → remplacé par
00. - Espace → remplacé par
_.
Matrice pour le mot-clé 'MYSTER'
| 1 | 2 | 3 | 4 | 5 | |
| 1 | M | Y | S | T | E |
| 2 | R | A | B | C | D |
| 3 | F | G | H | I | J |
| 4 | K | L | N | O | P |
| 5 | Q | U | V | X | Z |
Travail demandé :
- Fonction Crypter_Polybe(message, motcle) — chiffrer un message
- Fonction Decrypter_Polybe(message, motcle) — déchiffrer un message
matrice(motcle)— construit la grille 5×5.Crypter_Polybe(msg, motcle)— parcourt le message lettre par lettre et cherche ses coordonnées dans la matrice.Decrypter_Polybe(msg, motcle)— lit les codes par paires de chiffres et retrouve la lettre correspondante.
def matrice(motcle):
"""Construit la matrice 5×5 de Polybe à partir d'un mot-clé."""
alpha = 'ABCDEFGHIJKLMNOPQRSTUVXYZ' # alphabet sans W
Mat = [[0] * 5 for _ in range(5)]
Mat[0][0] = motcle[0]
i, j = 0, 1
# Placer les lettres du mot-clé (sans doublons)
for pos in range(1, len(motcle)):
if j == 5:
i += 1; j = 0
if motcle[pos] not in motcle[:pos]:
Mat[i][j] = motcle[pos]
j += 1
# Compléter avec l'alphabet restant
for lettre in alpha:
if j == 5:
i += 1; j = 0
if lettre not in motcle:
Mat[i][j] = lettre
j += 1
return Mat
def Crypter_Polybe(msg, motcle):
"""Chiffre un message selon le carré de Polybe."""
Mat = matrice(motcle)
res = ''
for c in msg:
if c == ' ':
res += '_'
elif c == 'W':
res += '00'
else:
# Recherche de la lettre dans la matrice
i = j = 0
while Mat[i][j] != c:
j += 1
if j == 5:
j = 0; i += 1
res += str(i + 1) + str(j + 1)
return res
def Decrypter_Polybe(msg, motcle):
"""Déchiffre un message encodé selon le carré de Polybe."""
Mat = matrice(motcle)
res = ''
k = 0
while k < len(msg):
if msg[k] == '_':
res += ' '; k += 1
elif msg[k] == '0':
res += 'W'; k += 2
else:
i = int(msg[k]) - 1
j = int(msg[k + 1]) - 1
res += Mat[i][j]
k += 2
return res
# Test
cle = "MYSTER"
msg = "CHERCHER POLYBE DANS WIKIPEDIA"
code = Crypter_Polybe(msg, cle)
print(code)
print(Decrypter_Polybe(code, cle))def matrice_dict(motcle):
"""
Construit deux dictionnaires pour un accès O(1) :
- lettre → (ligne, colonne) pour le chiffrement
- (ligne, colonne) → lettre pour le déchiffrement
"""
alpha = 'ABCDEFGHIJKLMNOPQRSTUVXYZ' # sans W
# Construire la séquence : mot-clé (sans doublons) + reste de l'alphabet
sequence = []
vus = set()
for c in motcle + alpha:
if c not in vus:
sequence.append(c)
vus.add(c)
encode = {} # lettre → code "ij"
decode = {} # code "ij" → lettre
for idx, lettre in enumerate(sequence):
ligne = idx // 5 + 1
col = idx % 5 + 1
code = str(ligne) + str(col)
encode[lettre] = code
decode[code] = lettre
return encode, decode
def Crypter_Polybe(msg, motcle):
encode, _ = matrice_dict(motcle)
res = ''
for c in msg:
if c == ' ': res += '_'
elif c == 'W': res += '00'
else: res += encode[c]
return res
def Decrypter_Polybe(msg, motcle):
_, decode = matrice_dict(motcle)
res = ''
k = 0
while k < len(msg):
if msg[k] == '_':
res += ' '; k += 1
elif msg[k] == '0':
res += 'W'; k += 2
else:
res += decode[msg[k:k+2]]; k += 2
return res
# Test
cle = "MYSTER"
msg = "CHERCHER POLYBE DANS WIKIPEDIA"
code = Crypter_Polybe(msg, cle)
print(code)
print(Decrypter_Polybe(code, cle))2433152124331521_454442122315_25224313_003441344515253422 CHERCHER POLYBE DANS WIKIPEDIA
| Code | 00 | 34 | 41 | 45 | 15 | 25 | 34 | 22 |
|---|---|---|---|---|---|---|---|---|
| Lettre | W | I | K | P | E | D | I | A |
Message : CHERCHER POLYBE DANS WIKIPEDIA Clé : MYSTER
2433152124331521_454442122315_25224313_003441344515253422
_ représente un espace, 00 représente la lettre W.Récapitulatif
| Exercice | Fonctions | Technique clé | Complexité |
|---|---|---|---|
| IPv4 → IPv6 | valide, classe, adresseip6, Genere | Manipulation de chaînes, bin(), hex(), fichiers | O(n) — n lignes du fichier |
| Polybe | matrice, Crypter_Polybe, Decrypter_Polybe | Matrice 5×5, recherche de coordonnées | O(m × 25) naïf, O(m) avec dict |
- Pour l'IPv4 : toujours utiliser
try/exceptautour deint()pour gérer les adresses malformées. hex(n)[2:].zfill(2).upper()garantit une représentation hexadécimale sur exactement 2 chiffres.- Le gestionnaire de contexte
with open(...)ferme automatiquement les fichiers, même en cas d'erreur. - Pour le chiffrement de Polybe : un dictionnaire remplace avantageusement la recherche linéaire dans la matrice.
- La symétrie chiffrement/déchiffrement : les mêmes dictionnaires suffisent, il suffit d'inverser la direction de lecture.
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.