rsa_chiffrement_francais.py

Created by ahenkes

Created on December 22, 2025

6.97 KB

Programmes Python interactifs pour démontrer le chiffrement RSA sur les calculatrices graphiques (TI-Nspire et NumWorks): https://github.com/alexander-henkes/rsa-calculator-python


# Chiffrement RSA: Mise en œuvre mathématique d'un processus de chiffrement complet

from math import gcd

# Test de primalité
def est_premier(n):
  """Vérifie si un nombre est premier"""
  if n<2:return False  # Les nombres inférieurs à 2 ne sont pas premiers
  if n==2:return True  # 2 est le seul nombre premier pair
  if n%2==0:return False  # Tous les autres nombres pairs ne sont pas premiers
  # Teste uniquement les diviseurs impairs jusqu'à la racine carrée de n
  for i in range(3,int(n**.5)+1,2):
    if n%i==0:return False
  return True

# Saisie d'un nombre premier avec validation
def saisie_premier(nom):
  """Invite l'utilisateur à saisir un nombre premier et valide l'entrée"""
  while True:
    try:
      nombre=int(input('Nombre premier '+nom+': '))
      if nombre<2:print(str(nombre)+' est trop petit!');continue
      if est_premier(nombre):print('Entrée valide: '+str(nombre)+' est un nombre premier!');return nombre
      else:print(str(nombre)+" n'est pas un nombre premier!")
    except:print('Entrée invalide!')

# Algorithme d'Euclide étendu
def euclide_etendu(a,b):
  """Calcule PGCD et les coefficients x, y pour a*x + b*y = PGCD(a,b)"""
  if b==0:return a,1,0
  else:g,x1,y1=euclide_etendu(b,a%b);x=y1;y=x1-a//b*y1;return g,x,y

# Calculer l'inverse modulaire
def inverse_mod(e,phi):
  """Calcule l'inverse modulaire de e modulo phi"""
  g,x,y=euclide_etendu(e,phi)
  if g!=1:return  # Aucun inverse n'existe si PGCD != 1
  return x%phi

# Exponentiation modulaire (efficace)
def puissance_mod(base,exposant,module):
  """Calcule (base^exposant) mod module efficacement"""
  resultat=1;base=base%module
  while exposant>0:
    if exposant%2==1:resultat=resultat*base%module
    exposant=exposant>>1;base=base*base%module
  return resultat

# Trouver un e approprié
def trouve_e(phi):
  """Trouve un e approprié qui est premier avec phi"""
  candidats=[3,5,7,11,13,17,19,23,29,31]
  # Essayer d'abord les petits nombres premiers
  for e in candidats:
    if e<phi and gcd(e,phi)==1:return e
  # Si aucun ne convient, rechercher systématiquement
  for e in range(2,phi):
    if gcd(e,phi)==1:return e

# Convertir une lettre en nombre
def lettre_vers_nombre(lettre):
  """Convertit une lettre en nombre (A=0, B=1, ..., Z=25)"""
  lettre=lettre.upper()
  if'A'<=lettre<='Z':return ord(lettre)-ord('A')

# Convertir un nombre en lettre
def nombre_vers_lettre(nombre):
  """Convertit un nombre en lettre (0=A, 1=B, ..., 25=Z)"""
  if 0<=nombre<=25:return chr(nombre+ord('A'))

# Fonction principale: Processus RSA
def rsa():
  # Sortie: En-tête
  print('='*30);print('Chiffrement RSA');print('='*30);print()

  # ÉTAPE 1: Choisir les nombres premiers
  print('ÉTAPE 1: Choisir les nombres');print('premiers');print('-'*30)
  p=saisie_premier('p')
  # S'assurer que q est différent de p
  while True:
    q=saisie_premier('q')
    if q!=p:break
    print('Erreur: p et q doivent')
    print('être différents!')
  print('Sélectionné: p='+str(p)+', q='+str(q))
  input('Continuer avec Entrée ...');print()

  # ÉTAPE 2: Calculer n et phi(n)
  print('ÉTAPE 2: n et phi(n)');print('-'*30)
  n=p*q  # Module n = p * q
  phi=(p-1)*(q-1)  # Fonction d'Euler phi(n) = (p-1)*(q-1)
  print('n = p*q = '+str(p)+'*'+str(q)+' = '+str(n))
  print('phi(n) = (p-1)*(q-1)')
  print('phi(n) = '+str(p-1)+'*'+str(q-1)+' = '+str(phi))
  input('Continuer avec Entrée ...');print()

  # ÉTAPE 3: Déterminer la clé publique e
  print('ÉTAPE 3: Clé publique e');print('-'*30)
  print('Note: e doit être premier')
  print('avec phi(n) = '+str(phi)+', c.-à-d. (PGCD(e, phi(n)) = 1)')
  suggestion=trouve_e(phi)
  print('Suggestion: e = '+str(suggestion))
  reponse=input('Utiliser? (O/N): ')
  # L'utilisateur peut accepter la suggestion ou saisir son propre e
  if reponse.lower()=='o':e=suggestion
  else:
    while True:
      e=int(input('Utiliser e personnalisé: '))
      if e>=phi:print('e doit être < '+str(phi)+'!');continue
      if gcd(e,phi)==1:print('Entrée valide:');print('PGCD('+str(e)+','+str(phi)+')=1');break
      else:print('PGCD('+str(e)+','+str(phi)+')!=1')
  print('Clé publique: ('+str(e)+', '+str(n)+')')
  input('Continuer avec Entrée ...');print()

  # ÉTAPE 4: Calculer la clé privée d
  print('ÉTAPE 4: Clé privée d');print('-'*30)
  print('d est l\'inverse modulaire')
  print('de e mod phi(n)')
  print('d*e = 1 (mod '+str(phi)+')')
  print('Calculer avec l\'algorithme')
  print('d\'Euclide étendu:')
  d=inverse_mod(e,phi)
  print('d = '+str(d))
  # Vérification: d * e mod phi doit égaler 1
  print('Vérification: '+str(d)+'*'+str(e))
  print('mod '+str(phi)+' = '+str(d*e%phi))
  print('Clé privée: ('+str(d)+', '+str(n)+')')
  input('Continuer avec Entrée ...');print()

  # ÉTAPE 5: Chiffrer le message
  print('ÉTAPE 5: Chiffrement');print('-'*30)
  print('Chiffrement: c=m^e mod n')
  print('c = m^'+str(e)+' mod '+str(n))
  print()
  print('Codage des lettres:')
  print('A=0, B=1, C=2, ..., Z=25')
  print()
  # Saisie de lettre avec validation
  while True:
    lettre=input('Lettre (A-Z): ').strip()
    if len(lettre)==1:
      m=lettre_vers_nombre(lettre)
      if m is not None:
        if m<n:print("'"+lettre.upper()+"' = "+str(m));break
        else:print('Erreur: '+str(m)+' >= '+str(n));print('Choisir des nombres premiers plus petits!')
      else:print('Invalide! Seulement A-Z autorisé!')
    else:print('Une seule lettre!')
  # Effectuer le chiffrement: c = m^e mod n
  c=puissance_mod(m,e,n)
  print()
  print('c = '+str(m)+'^'+str(e)+' mod '+str(n))
  print('c = '+str(c))
  print('Lettre chiffrée: '+str(c))
  input('Continuer avec Entrée ...');print()

  # ÉTAPE 6: Déchiffrer le message
  print('ÉTAPE 6: Déchiffrement');print('-'*30)
  print('Déchiffrement:')
  print('m = c^d mod n')
  print('m = '+str(c)+'^'+str(d)+' mod '+str(n))
  # Effectuer le déchiffrement: m = c^d mod n
  m_nouveau=puissance_mod(c,d,n)
  lettre_nouvelle=nombre_vers_lettre(m_nouveau)
  print('m = '+str(c)+'^'+str(d)+' mod '+str(n))
  print('m = '+str(m_nouveau))
  print('Lettre déchiffrée: '+str(lettre_nouvelle))
  # Vérification: La valeur déchiffrée correspond-elle à l'original?
  if m==m_nouveau:print('Réussi!')
  else:print('Erreur!')
  input('Continuer avec Entrée ...');print()

# RÉSUMÉ: Afficher toutes les valeurs importantes
  print('='*30);print('RÉSUMÉ');print('='*30)
  print('Nombres premiers: p='+str(p)+', q='+str(q))
  print('Module (p*q): n='+str(n))
  print('Fonction phi d\'Euler: phi='+str(phi))
  print('Clé publique: ('+str(e)+','+str(n)+')')
  print('Clé privée: ('+str(d)+','+str(n)+')')
  print('Texte clair (lettre): '+lettre.upper())
  print('Texte clair (nombre): m='+str(m))
  print('Nombre chiffré: c='+str(c))
  print('Nombre déchiffré: m='+str(m_nouveau))
  print('Lettre déchiffrée: '+str(lettre_nouvelle))
  print('='*30)

# Boucle de répétition potentielle
while True:
  rsa()  # Exécuter un processus RSA
  print()
  encore=input('Relancer le calcul? (O/N): ')
  if encore.lower()!='o':print('Programme terminé!');break
  print('\n'*2)

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.