Projekt 1 klart praktiskt
This commit is contained in:
		
						commit
						74d60a2cb5
					
				
					 6 changed files with 299 additions and 0 deletions
				
			
		
							
								
								
									
										60
									
								
								src/rsa/EuclideanAlgorithm.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/rsa/EuclideanAlgorithm.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,60 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigInteger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class EuclideanAlgorithm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static BigInteger modularInverse(BigInteger a, BigInteger m) {
 | 
				
			||||||
 | 
					        BigInteger m0 = m, t, q;
 | 
				
			||||||
 | 
					        BigInteger x0 = BigInteger.ZERO, x1 = BigInteger.ONE;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        if (m.equals(BigInteger.ONE)) return BigInteger.ZERO; // Ingen invers om m = 1
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        while (a.compareTo(BigInteger.ONE) > 0) {
 | 
				
			||||||
 | 
					            q = a.divide(m);  // Kvoten
 | 
				
			||||||
 | 
					            t = m;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            // m = a % m, liknar Euklides algoritm
 | 
				
			||||||
 | 
					            m = a.mod(m);
 | 
				
			||||||
 | 
					            a = t;
 | 
				
			||||||
 | 
					            t = x0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            // Uppdatera x0 och x1
 | 
				
			||||||
 | 
					            x0 = x1.subtract(q.multiply(x0));
 | 
				
			||||||
 | 
					            x1 = t;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // Hantera negativa x1
 | 
				
			||||||
 | 
					        if (x1.compareTo(BigInteger.ZERO) < 0) {
 | 
				
			||||||
 | 
					            x1 = x1.add(m0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        return x1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static BigInteger gcd(BigInteger a, BigInteger b) {
 | 
				
			||||||
 | 
					        if (b.equals(BigInteger.ZERO)) {
 | 
				
			||||||
 | 
					            return a;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return gcd(b, a.mod(b));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 3️⃣ Testa algoritmen med några stora tal
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        System.out.println("=== Test av modular invers ===");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        BigInteger a = new BigInteger("65537"); // Typiskt RSA e = 2^16 + 1
 | 
				
			||||||
 | 
					        BigInteger m = new BigInteger("973157123091"); // Slumpmässigt stort tal
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // Kontrollera om invers finns
 | 
				
			||||||
 | 
					        if (gcd(a, m).equals(BigInteger.ONE)) {
 | 
				
			||||||
 | 
					            BigInteger inv = modularInverse(a, m);
 | 
				
			||||||
 | 
					            System.out.println("Modulär invers av " + a + " mod " + m + " är: " + inv);
 | 
				
			||||||
 | 
					            // Kontroll: Ska ge 1 → (a * inv) % m == 1
 | 
				
			||||||
 | 
					            System.out.println("Verifiering: (" + a + " * " + inv + ") mod " + m + " = " + a.multiply(inv).mod(m));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            System.out.println("Ingen invers existerar för a mod m.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/rsa/Main.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/rsa/Main.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigInteger;
 | 
				
			||||||
 | 
					import java.util.Random;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Main {
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        System.out.println("=== Startar RSA-programmet ===");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 1️⃣ Generera RSA-nycklar
 | 
				
			||||||
 | 
					        int bitLength = 512;
 | 
				
			||||||
 | 
					        RSAKeyGenerator rsa = new RSAKeyGenerator(bitLength);
 | 
				
			||||||
 | 
					        BigInteger[] publicKey = rsa.getPublicKey();
 | 
				
			||||||
 | 
					        BigInteger[] privateKey = rsa.getPrivateKey();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println("\n--- Genererade nycklar ---");
 | 
				
			||||||
 | 
					        System.out.println("Publik nyckel:  N = " + publicKey[0] + ", e = " + publicKey[1]);
 | 
				
			||||||
 | 
					        System.out.println("Privat nyckel:  N = " + privateKey[0] + ", d = " + privateKey[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 2️⃣ Skapa ett slumpmässigt meddelande som är mindre än N
 | 
				
			||||||
 | 
					        BigInteger message = new BigInteger(bitLength - 1, new Random());
 | 
				
			||||||
 | 
					        System.out.println("\nOriginal meddelande: " + message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 3️⃣ Kryptera meddelandet
 | 
				
			||||||
 | 
					        BigInteger ciphertext = RSAEncryptor.encrypt(message, publicKey);
 | 
				
			||||||
 | 
					        System.out.println("Krypterat meddelande: " + ciphertext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 4️⃣ Dekryptera meddelandet
 | 
				
			||||||
 | 
					        BigInteger decrypted = RSAEncryptor.decrypt(ciphertext, privateKey);
 | 
				
			||||||
 | 
					        System.out.println("Dekrypterat meddelande: " + decrypted);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 5️⃣ Verifiera att dekrypteringen fungerar
 | 
				
			||||||
 | 
					        boolean isCorrect = message.equals(decrypted);
 | 
				
			||||||
 | 
					        System.out.println("\nStämmer dekrypteringen? " + (isCorrect ? "JA! ✅" : "NEJ ❌"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								src/rsa/PerformanceTest.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/rsa/PerformanceTest.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PerformanceTest {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										102
									
								
								src/rsa/PrimeGenerator.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/rsa/PrimeGenerator.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,102 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigInteger;
 | 
				
			||||||
 | 
					import java.security.SecureRandom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PrimeGenerator {
 | 
				
			||||||
 | 
					    private static final SecureRandom random = new SecureRandom();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 1️⃣ Implementera Rabin-Miller primtalstest
 | 
				
			||||||
 | 
					    public static boolean isPrime(BigInteger n, int k) {
 | 
				
			||||||
 | 
					        if (n.equals(BigInteger.ONE) || n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
 | 
				
			||||||
 | 
					            return false; // 1 eller jämna tal är inte primtal (förutom 2)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // Skriv n-1 som 2^r * s, där s är udda
 | 
				
			||||||
 | 
					        BigInteger s = n.subtract(BigInteger.ONE);
 | 
				
			||||||
 | 
					        int r = 0;
 | 
				
			||||||
 | 
					        while (s.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
 | 
				
			||||||
 | 
					            s = s.divide(BigInteger.TWO);
 | 
				
			||||||
 | 
					            r++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // Kör testet k gånger med slumpmässiga baser
 | 
				
			||||||
 | 
					        for (int i = 0; i < k; i++) {
 | 
				
			||||||
 | 
					            BigInteger a = uniformRandom(BigInteger.TWO, n.subtract(BigInteger.ONE)); // Slumpmässig bas
 | 
				
			||||||
 | 
					            BigInteger x = a.modPow(s, n);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            if (x.equals(BigInteger.ONE) || x.equals(n.subtract(BigInteger.ONE))) {
 | 
				
			||||||
 | 
					                continue; // Möjligt primtal
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            boolean isComposite = true;
 | 
				
			||||||
 | 
					            for (int j = 0; j < r - 1; j++) {
 | 
				
			||||||
 | 
					                x = x.modPow(BigInteger.TWO, n);
 | 
				
			||||||
 | 
					                if (x.equals(n.subtract(BigInteger.ONE))) {
 | 
				
			||||||
 | 
					                    isComposite = false;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            if (isComposite) {
 | 
				
			||||||
 | 
					                return false; // n är sammansatt
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        return true; // n är möjligen primtal
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Hjälpmetod för att generera ett slumpmässigt BigInteger mellan min och max
 | 
				
			||||||
 | 
					    private static BigInteger uniformRandom(BigInteger min, BigInteger max) {
 | 
				
			||||||
 | 
					        BigInteger result;
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            result = new BigInteger(max.bitLength(), random);
 | 
				
			||||||
 | 
					        } while (result.compareTo(min) < 0 || result.compareTo(max) > 0);
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 2️⃣ Generera ett primtal med angiven bitstorlek
 | 
				
			||||||
 | 
					    public static BigInteger generatePrime(int bitLength) {
 | 
				
			||||||
 | 
					        BigInteger prime;
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            prime = new BigInteger(bitLength, random).setBit(0); // Se till att det är udda
 | 
				
			||||||
 | 
					        } while (!isPrime(prime, 20)); // Testa med 20 iterationer av Rabin-Miller
 | 
				
			||||||
 | 
					        return prime;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 3️⃣ Generera 100 primtal av viss storlek och mät tiden
 | 
				
			||||||
 | 
					    public static void benchmarkPrimes(int bitLength) {
 | 
				
			||||||
 | 
					        long startTime = System.nanoTime();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        for (int i = 0; i < 100; i++) {
 | 
				
			||||||
 | 
					            generatePrime(bitLength);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        long endTime = System.nanoTime();
 | 
				
			||||||
 | 
					        double elapsedTime = (endTime - startTime) / 1_000_000_000.0; // Konvertera till sekunder
 | 
				
			||||||
 | 
					        System.out.println("Bitlängd: " + bitLength + " | Tid: " + elapsedTime + " sekunder");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        System.out.println("=== Benchmark: Primtalsgenerering ===");
 | 
				
			||||||
 | 
					        System.out.println("| Bitlängd | Antal | Tid (ms) |");
 | 
				
			||||||
 | 
					        System.out.println("|----------|-------|----------|");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        int[] bitSizes = {512, 1024, 2048, 4096};  // Bitstorlekar att testa
 | 
				
			||||||
 | 
					        for (int bitSize : bitSizes) {
 | 
				
			||||||
 | 
					            long startTime = System.currentTimeMillis();  // Starta tidtagning
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            for (int i = 0; i < 100; i++) {
 | 
				
			||||||
 | 
					                generatePrime(bitSize);  // Generera primtal
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            long endTime = System.currentTimeMillis();  // Sluta tidtagning
 | 
				
			||||||
 | 
					            long elapsedTime = endTime - startTime;  // Total tid i ms
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            // Skriv ut tabellrad
 | 
				
			||||||
 | 
					            System.out.printf("| %8d | %4d  | %8d |\n", bitSize, 100, elapsedTime);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        System.out.println("\nBenchmark färdig! 🎉");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								src/rsa/RSAEncryptor.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/rsa/RSAEncryptor.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigInteger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RSAEncryptor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static BigInteger encrypt(BigInteger message, BigInteger[] publicKey) {
 | 
				
			||||||
 | 
					        BigInteger N = publicKey[0];
 | 
				
			||||||
 | 
					        BigInteger e = publicKey[1];
 | 
				
			||||||
 | 
					        return message.modPow(e, N); // Effektiv modular exponentiation
 | 
				
			||||||
 | 
					    }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static BigInteger decrypt(BigInteger ciphertext, BigInteger[] privateKey) {
 | 
				
			||||||
 | 
					        BigInteger N = privateKey[0];
 | 
				
			||||||
 | 
					        BigInteger d = privateKey[1];
 | 
				
			||||||
 | 
					        return ciphertext.modPow(d, N); // Effektiv modular exponentiation
 | 
				
			||||||
 | 
					    }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        System.out.println("=== Test av RSA Kryptering/Dekryptering ===");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 1️⃣ Generera RSA-nycklar
 | 
				
			||||||
 | 
					        RSAKeyGenerator rsa = new RSAKeyGenerator(512);
 | 
				
			||||||
 | 
					        BigInteger[] publicKey = rsa.getPublicKey();
 | 
				
			||||||
 | 
					        BigInteger[] privateKey = rsa.getPrivateKey();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 2️⃣ Slumpmässigt meddelande att kryptera
 | 
				
			||||||
 | 
					        BigInteger message = new BigInteger("123456789");
 | 
				
			||||||
 | 
					        System.out.println("Original meddelande: " + message);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 3️⃣ Kryptera meddelandet
 | 
				
			||||||
 | 
					        BigInteger ciphertext = encrypt(message, publicKey);
 | 
				
			||||||
 | 
					        System.out.println("Krypterat meddelande: " + ciphertext);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 4️⃣ Dekryptera meddelandet
 | 
				
			||||||
 | 
					        BigInteger decrypted = decrypt(ciphertext, privateKey);
 | 
				
			||||||
 | 
					        System.out.println("Dekrypterat meddelande: " + decrypted);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 5️⃣ Verifiera att dekrypteringen är korrekt
 | 
				
			||||||
 | 
					        System.out.println("Stämmer dekrypteringen? " + message.equals(decrypted));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										53
									
								
								src/rsa/RSAKeyGenerator.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/rsa/RSAKeyGenerator.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,53 @@
 | 
				
			||||||
 | 
					package src.rsa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigInteger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RSAKeyGenerator {
 | 
				
			||||||
 | 
					    private BigInteger p, q, N, e, d;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // 1️⃣ Konstruktor: Generera nycklar
 | 
				
			||||||
 | 
					    public RSAKeyGenerator(int bitLength) {
 | 
				
			||||||
 | 
					        generateKeys(bitLength);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void generateKeys(int bitLength) {
 | 
				
			||||||
 | 
					        System.out.println("Genererar RSA-nycklar med " + bitLength + "-bitars primtal...");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 1️⃣ Generera stora primtal p och q
 | 
				
			||||||
 | 
					        p = PrimeGenerator.generatePrime(bitLength);
 | 
				
			||||||
 | 
					        q = PrimeGenerator.generatePrime(bitLength);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 2️⃣ Beräkna N = p * q
 | 
				
			||||||
 | 
					        N = p.multiply(q);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 3️⃣ Beräkna Euler φ(N) = (p-1) * (q-1)
 | 
				
			||||||
 | 
					        BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 4️⃣ Välj publik exponent e (standard är 65537)
 | 
				
			||||||
 | 
					        e = new BigInteger("65537");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // 5️⃣ Beräkna privat exponent d = e⁻¹ mod φ(N) med utökade Euklides algoritm
 | 
				
			||||||
 | 
					        d = EuclideanAlgorithm.modularInverse(e, phi);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        System.out.println("Nycklar genererade!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BigInteger[] getPublicKey() {
 | 
				
			||||||
 | 
					        return new BigInteger[]{N, e};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public BigInteger[] getPrivateKey() {
 | 
				
			||||||
 | 
					        return new BigInteger[]{N, d};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        RSAKeyGenerator rsa = new RSAKeyGenerator(512);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        System.out.println("\n=== RSA Nycklar ===");
 | 
				
			||||||
 | 
					        System.out.println("Public Key:  N = " + rsa.getPublicKey()[0] + ", e = " + rsa.getPublicKey()[1]);
 | 
				
			||||||
 | 
					        System.out.println("Private Key: N = " + rsa.getPrivateKey()[0] + ", d = " + rsa.getPrivateKey()[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue