on trouve le projet complet projetRSA16

genrsa16.c

Ce code va nous générer une clé privée et une clé publique

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/**
 * is_prime - Teste si un entier n est premier (test simple)
 * @n: le nombre à tester
 * 
 * Retourne 1 si premier, 0 sinon
 * 
 * Méthode : on teste la divisibilité par tous les entiers impairs de 3 à sqrt(n)
 */
igenrnt is_prime(int n) {
    if (n < 2) return 0;       // Les nombres < 2 ne sont pas premiers
    if (n == 2) return 1;      // 2 est premier
    if (n % 2 == 0) return 0;  // Les nombres pairs > 2 ne sont pas premiers

    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) return 0; // Divisible par i -> pas premier
    }
    return 1; // Aucun diviseur trouvé -> premier
}

/**
 * random_prime - Génère un nombre premier impair aléatoire dans [min..max]
 * 
 * Boucle jusqu'à obtenir un nombre premier
 */
int random_prime(int min, int max) {
    int p;
    do {
        p = rand() % (max - min + 1) + min; // Tirage aléatoire dans l'intervalle
        if (p % 2 == 0) p++;                // S'assurer que p est impair
    } while (!is_prime(p));                 // Répéter tant que p n'est pas premier
    return p;
}

/**
 * egcd - Algorithme d'Euclide étendu pour calculer le PGCD de a et b
 *       et trouver les coefficients x et y tels que a*x + b*y = gcd(a, b)
 * 
 * Retourne le PGCD et remplit x et y par les coefficients de Bézout
 */
int egcd(int a, int b, int *x, int *y) {
    if (b == 0) {
        *x = 1; *y = 0;
        return a; // PGCD trouvé = a
    }
    int x1, y1;
    int gcd = egcd(b, a % b, &x1, &y1);  // Appel récursif
    *x = y1;
    *y = x1 - (a / b) * y1;               // Mise à jour des coefficients
    return gcd;
}

/**
 * modinv - Calcul de l'inverse modulaire de e modulo phi
 *          C'est-à-dire trouver d tel que (d*e) mod phi = 1
 * 
 * Utilise l'algorithme d'Euclide étendu
 * Retourne -1 si l'inverse n'existe pas
 */
int modinv(int e, int phi) {
    int x, y;
    int g = egcd(e, phi, &x, &y);
    if (g != 1) return -1; // Inverse modulaire n'existe que si e et phi sont premiers entre eux
    return (x % phi + phi) % phi; // On normalise x pour qu'il soit positif
}

int main() {
    // Initialisation du générateur de nombres aléatoires avec l'heure actuelle
    srand(time(NULL));

    // Génération aléatoire de deux nombres premiers p et q distincts dans [50..100]
    int p = random_prime(50, 100);
    int q;
    do {
        q = random_prime(50, 100);
    } while (q == p); // On s'assure que p et q soient différents

    int n = p * q;           // Calcul de n = p*q, utilisé pour la clé publique et privée
    int phi = (p - 1) * (q - 1); // Calcul de phi(n), la fonction d'Euler

    // Choix de e : on cherche un nombre impair e premier avec phi
    int e;
    for (e = 3; e < phi; e += 2) {
        int x, y;
        if (egcd(e, phi, &x, &y) == 1)
            break; // e trouvé, premier avec phi
    }

    // Calcul de d, l'inverse modulaire de e modulo phi
    int d = modinv(e, phi);
    if (d == -1) {
        fprintf(stderr, "Erreur : pas d'inverse modulaire pour e=%d\n", e);
        return EXIT_FAILURE;
    }

    // Affichage des résultats (clés publique et privée)
    printf("p = %d, q = %d\n", p, q);
    printf("n = %d\n", n);
    printf("phi = %d\n", phi);
    printf("Clé publique (e, n) : (%d, %d)\n", e, n);
    printf("Clé privée  (d, n) : (%d, %d)\n", d, n);

    return EXIT_SUCCESS;
}
# compilation du code
gcc genrsa16.c -o genrsa16
bruno@debian:~/Works/langageC/rsa16/projet_rsa16$ ./genrsa16 
p = 73, q = 59
n = 4307
phi = 4176
Clé publique (e, n) : (5, 4307)
Clé privée  (d, n) : (3341, 4307)

on va noter la clé public d’Alice , ici 5 et 4307 que Alice va diffuser , surtout a Bob , elle va garder la clé privée de son coté bien secrète 3341 4307

rsa16.c

#include <stdio.h>
#include <stdlib.h>

typedef unsigned short u16;

/**
 * modexp - Calcul rapide de l’exponentiation modulaire (base^exp mod modulo)
 */
u16 modexp(u16 base, u16 exp, u16 mod) {
    u16 result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1) result = (result * base) % mod;
        base = (base * base) % mod;
        exp >>= 1;
    }
    return result;
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        fprintf(stderr, "Usage : %s fichier.txt e n\n", argv[0]);
        return EXIT_FAILURE;
    }

    u16 e = (u16)atoi(argv[2]);
    u16 n = (u16)atoi(argv[3]);

    FILE *in = fopen(argv[1], "rb");
    if (!in) {
        perror("fopen input");
        return EXIT_FAILURE;
    }

    char outname[256];
    snprintf(outname, sizeof(outname), "%s.chi", argv[1]);
    FILE *out = fopen(outname, "wb");
    if (!out) {
        perror("fopen output");
        fclose(in);
        return EXIT_FAILURE;
    }

    int ch;
    while ((ch = fgetc(in)) != EOF) {
        u16 encrypted = modexp((u16)ch, e, n);
        fwrite(&encrypted, sizeof(u16), 1, out);
    }

    fclose(in);
    fclose(out);
    printf("Fichier chiffré : %s\n", outname);
    return EXIT_SUCCESS;
}gedit rsa

Bob va lui faire un petit message secret en code ascii

echo "Bonjour Alice, voila mon message secret !" > message.txt
cat message.txt
Bonjour Alice, voila mon message secret !
bruno@debian:~/Works/langageC/rsa16/projet_rsa16$ ./rsa16 message.txt 5 4307
Fichier chiffré : message.txt.chi
bruno@debian:~/Works/langageC/rsa16/projet_rsa16$ cat message.txt.chi 
y�~y^
�V
 �1
   ���V
       �y1
          �KV
             |
              y�V
                 |
                  ��	�	K
                                 	�V
                                          �	�����V
                                                      ��b

Ce message est devenu illisible !

Bob le transmet à Alice , qui dispose de sa clé privée

decrsa16.c

#include <stdio.h>
#include <stdlib.h>

/**
 * modexp - Calcul rapide de l’exponentiation modulaire (base^exp mod modulo)
 * 
 * @param base La base (entier)
 * @param exp L'exposant (clé privée d)
 * @param mod Le modulo n
 * @return (base^exp) mod mod
 */
typedef unsigned short u16;
u16 modexp(u16 base, u16 exp, u16 mod) {
    u16 result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1) result = (result * base) % mod;
        base = (base * base) % mod;
        exp >>= 1;
    }
    return result;
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        fprintf(stderr, "Usage : %s fichier.chi d n\n", argv[0]);
        return EXIT_FAILURE;
    }

    FILE *in = fopen(argv[1], "rb");
    if (!in) {
        perror("fopen");
        return EXIT_FAILURE;
    }

    // Conversion des paramètres d et n passés en argument (clé privée)
    u16 d = (u16)atoi(argv[2]);
    u16 n = (u16)atoi(argv[3]);

    FILE *out = fopen("dechiffre.txt", "wb");
    if (!out) {
        perror("fopen output");
        fclose(in);
        return EXIT_FAILURE;
    }

    u16 chunk;
    // Lecture bloc par bloc (2 octets) du fichier chiffré
    while (fread(&chunk, sizeof(u16), 1, in) == 1) {
        // Déchiffrement RSA : m = c^d mod n
        u16 decrypted = modexp(chunk, d, n);
        fputc((char)decrypted, out);
    }

    fclose(in);
    fclose(out);
    printf("Déchiffré dans dechiffre.txt\n");
    return EXIT_SUCCESS;
}

bruno@debian:~/Works/langageC/rsa16/projet_rsa16$ ./decrsa16 message.txt.chi 3341 4307
Déchiffré dans dechiffre.txt
bruno@debian:~/Works/langageC/rsa16/projet_rsa16$ cat dechiffre.txt
Bonjour Alice, voila mon message secret !
bruno@debian:~/Works/langageC/rsa16/projet_rsa16$

A vous de jouer

vous pouvez tester avec un autre jeu de clés