[[oktatas:programozás:java|< Java]] ====== Titkosítás Java nyelven====== * **Szerző:** Sallai András * Copyright (c) 2014, Sallai András * Szerkesztve: 2014, 2023 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== Szöveg titkosítása ===== Az alábbi programban egy szöveget titkosítok majd visszafejtem. A titkosító és visszafejtő kulcs egy bájt sorozat. A következőkben a használható titkosító algoritmusokat és kulcsméreteket láthatjuk: ^ Algoritmus ^ Kulcsméret ^ | DES | 56 bit | | AES | 128 bit | | DESede | 168 bit és 112 bit | | RC2 | 128 bit | | RC4 | 128 bit | import javax.crypto.*; import javax.crypto.spec.*; import java.io.*; class ap { public static void main(String args[]) throws Exception { String Algoritmus = "AES"; int Kulcsmeret = 128; KeyGenerator kgen = KeyGenerator.getInstance(Algoritmus); kgen.init(Kulcsmeret); //128 jó; 192 és 256 bites lehet, hogy nem elérhető SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); SecretKeySpec key = new SecretKeySpec(raw, Algoritmus); // A kulcs generálást magunk is megtehetjük (ekkor az eddigiek kihagyhatók): /* SecretKeySpec key = new SecretKeySpec(new byte[] {56,57,58,59,56,57,58,59,56,57,58,59,56,57,58,59 }, "AES"); */ System.out.println("Kulcsméret: " + key.getEncoded().length); Cipher c = Cipher.getInstance(Algoritmus); c.init(Cipher.ENCRYPT_MODE, key); byte[] titkosSzoveg = new byte[16]; titkosSzoveg = c.doFinal("titkoső".getBytes("UTF-8")); System.out.println("Titkosítva: " + new String(titkosSzoveg)); c.init(Cipher.DECRYPT_MODE, key); byte[] tisztaSzoveg = new byte[10]; tisztaSzoveg = c.doFinal(titkosSzoveg); System.out.println("Visszafejtett: " + new String(tisztaSzoveg)); } } ==== Coder osztály készítése ==== import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class Coder { public static String encrypt(String clearText, SecretKeySpec key) { String result = ""; try { result = tryEncrypt(clearText, key); } catch (NoSuchAlgorithmException e) { System.err.println("Hiba! Nincs ilyen algoritmus!"); }catch(NoSuchPaddingException e) { System.err.println("Hiba! Nincs ilyen kitöltő!"); }catch(InvalidKeyException e) { System.err.println("Hiba! Érvénytelen kulcs!"); }catch(UnsupportedEncodingException e) { System.err.println("Hiba! Nem támogatott kódolás!"); }catch(IllegalBlockSizeException e) { System.out.println("Hiba! Illegális blokkméret!"); }catch(BadPaddingException e) { System.err.println("Hiba! Rossz kitöltő!"); } return result; } public static String tryEncrypt(String clearText, SecretKeySpec key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainTextByteArray = clearText.getBytes("UTF-8"); byte[] secretTextByteArray = cipher.doFinal(plainTextByteArray); String secretText = new String(Base64.getEncoder().encode(secretTextByteArray)); return secretText; } public static String decrypt(String secretText, SecretKeySpec key) { String result = ""; try { result = tryDecrypt(secretText, key); } catch (NoSuchAlgorithmException e) { System.err.println("Hiba! Nincs ilyen algoritmus!"); }catch(NoSuchPaddingException e) { System.err.println("Hiba! Nincs ilyen kitöltő!"); }catch(InvalidKeyException e) { System.err.println("Hiba! Érvénytelen kulcs!"); }catch(UnsupportedEncodingException e) { System.err.println("Hiba! Nem támogatott kódolás!"); }catch(IllegalBlockSizeException e) { System.out.println("Hiba! Illegális blokkméret!"); }catch(BadPaddingException e) { System.err.println("Hiba! Rossz kitöltő!"); } return result; } public static String tryDecrypt(String secretText, SecretKeySpec key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] encryptedByteArray = Base64.getDecoder().decode(secretText); byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray); String clearText = new String(decryptedByteArray, "UTF-8"); return clearText; } public static SecretKeySpec generateKey() throws NoSuchAlgorithmException { SecretKeySpec key; String algoritmus = "AES"; int kulcsmeret = 128; KeyGenerator keyGenerator = KeyGenerator.getInstance(algoritmus); keyGenerator.init(kulcsmeret); SecretKey secretKey = keyGenerator.generateKey(); byte[] raw = secretKey.getEncoded(); key = new SecretKeySpec(raw, algoritmus); return key; } } Használat: import javax.crypto.spec.SecretKeySpec; public class App { public static void main(String[] args) throws Exception { System.out.println("--Titkostás--"); SecretKeySpec key = Coder.generateKey(); String secretText = Coder.encrypt("titok", key); System.out.println(secretText); String clearText = Coder.decrypt(secretText, key); System.out.println(clearText); } } ==== Kulcsgenerálás másként ==== import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class Coder { public static String encrypt(String clearText, Key key) { String result = ""; try { result = tryEncrypt(clearText, key); } catch (NoSuchAlgorithmException e) { System.err.println("Hiba! Nincs ilyen algoritmus!"); }catch(NoSuchPaddingException e) { System.err.println("Hiba! Nincs ilyen kitöltő!"); }catch(InvalidKeyException e) { System.err.println("Hiba! Érvénytelen kulcs!"); }catch(UnsupportedEncodingException e) { System.err.println("Hiba! Nem támogatott kódolás!"); }catch(IllegalBlockSizeException e) { System.out.println("Hiba! Illegális blokkméret!"); }catch(BadPaddingException e) { System.err.println("Hiba! Rossz kitöltő!"); } return result; } public static String tryEncrypt(String clearText, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainTextByteArray = clearText.getBytes("UTF-8"); byte[] secretTextByteArray = cipher.doFinal(plainTextByteArray); String secretText = new String(Base64.getEncoder().encode(secretTextByteArray)); return secretText; } public static String decrypt(String secretText, Key key) { String result = ""; try { result = tryDecrypt(secretText, key); } catch (NoSuchAlgorithmException e) { System.err.println("Hiba! Nincs ilyen algoritmus!"); }catch(NoSuchPaddingException e) { System.err.println("Hiba! Nincs ilyen kitöltő!"); }catch(InvalidKeyException e) { System.err.println("Hiba! Érvénytelen kulcs!"); }catch(UnsupportedEncodingException e) { System.err.println("Hiba! Nem támogatott kódolás!"); }catch(IllegalBlockSizeException e) { System.out.println("Hiba! Illegális blokkméret!"); }catch(BadPaddingException e) { System.err.println("Hiba! Rossz kitöltő!"); } return result; } public static String tryDecrypt(String secretText, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] encryptedByteArray = Base64.getDecoder().decode(secretText); byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray); String clearText = new String(decryptedByteArray, "UTF-8"); return clearText; } public static SecretKeySpec generateKey() throws NoSuchAlgorithmException { SecretKeySpec key; String algoritmus = "AES"; int kulcsmeret = 128; KeyGenerator keyGenerator = KeyGenerator.getInstance(algoritmus); keyGenerator.init(kulcsmeret); SecretKey secretKey = keyGenerator.generateKey(); byte[] raw = secretKey.getEncoded(); key = new SecretKeySpec(raw, algoritmus); return key; } } Használat: import java.security.Key; import javax.crypto.spec.SecretKeySpec; public class App { public static void main(String[] args) throws Exception { System.out.println("--Titkostás--"); String key = "1234567890123456"; // 128 bites kulcs Key aeskey = new SecretKeySpec(key.getBytes(), "AES"); String secretText = Coder.encrypt("titok", aeskey); System.out.println(secretText); String clearText = Coder.decrypt(secretText, aeskey); System.out.println(clearText); } } ===== Jelszó titkosítás ===== A jelszavakat csak egyirányú titkosítással szoktuk titkosítani, mivel a visszafejtés nem szükséges. A bekért jelszót lekódoljuk a tárolt jelszó algoritmusával. A két kódolt jelszót hasonlítom össze. Az ilyen egyirányú algoritmusokkal készült karaktersorozatot kivonatnak hívjuk, vagyis digest angolosan. import java.security.*; import java.io.*; class md5 { public static void main(String args[]) throws IOException, NoSuchAlgorithmException { System.out.println("Titkosítás egyirányba"); // Lehetséges algoritmusok: SHA, MD5, SHA1 SHA-1, SHA-256, SHA-384, SHA-512 MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] sb = md.digest("baa".getBytes()); System.out.println(new String(sb)); byte[] sa = md.digest("aaa".getBytes()); System.out.println(new String(sa)); System.in.read(); } } Ez a program már lekódolja az eredmény viszont nem nyomtatható karaktereket eredményez. Ezért a következő kóddal szokás kiegészíteni: import java.security.*; import java.io.*; import java.util.Arrays; // Ez opcionális class md52 { public static void main(String args[]) throws IOException, NoSuchAlgorithmException { System.out.println("Titkosítás egyirányba"); // Lehetséges algoritmusok: SHA, MD5 MessageDigest md = MessageDigest.getInstance("NIST"); byte[] sb = md.digest("titkos".getBytes()); System.out.println(new String(sb)); System.out.println(Arrays.toString(sb)); //Tömbként íratjuk ki (opcionális) //átalakítjuk megjeleníthető karakterekké: StringBuffer hexSzoveg = new StringBuffer(); for (int i=0; i Az SHA-512 algoritmust szoktuk használni. De mit jelent a 512. Az 512, 512 bitet jelent. Azaz 64 byte. Egy byte-t 2 hexadecimális karakterrel ábrázolunk, az egy SHA-512-es algoritmussal kódolt jelszó 128 darab karaktert fog tartalmazni. A "titok" szó SHA-512 algoritmussal kódolt kivonata: f5596f6fef51169defe7cc7bba87576562d91e2ffb34d235e9ad9e13319c6f0e080c0d69a85135ae60f6bd42967159a5111a8ed65393df3cc7e2afa4301d939f Az "alma" szó SHA-512 algoritmussal kódolt kivonata: 83b05d98186648cd5576ed158c9cf2174413b86d48720c3ffbe6452bc38a6527256ff3435eb1698f24efbc880c8ea870afe314f3004c71cfdd5f0e3c00e3979f Az SHA1 160 bites kódolás, 40 karaktert eredményez. A "titok" szó SHA1 kivonata: 46ff53e764c4acf97b54db2020573049d2e3dab3 Az "alma" szó SHA1 kivonata: 5f5ea3800d9a62bc5a008759dbbece9cad5db58f ===== Minta ===== MAINCLASS=Program01 SOURCES=Program01.java all: javac $(SOURCES) LINJUNIT=/usr/share/java/junit4.jar TESTSOURCE=Program01Test testl: javac -cp .:$(LINJUNIT) $(TESTSOURCE).java java -cp .:$(LINJUNIT) org.junit.runner.JUnitCore $(TESTSOURCE) WINJUNIT=c:\bin\SWScite\SWScite_0.5.2_20140505\javalibs\junit-4.11.jar WINHAMCREST=c:\bin\SWScite\SWScite_0.5.2_20140505\javalibs\hamcrest-core-1.3.jar testw: javac -cp .;$(WINJUNIT);$(WINHAMCREST) $(TESTSOURCE).java java -cp .;$(WINJUNIT);$(WINHAMCREST) org.junit.runner.JUnitCore $(TESTSOURCE) jar: echo "Main-Class: $(MAINCLASS)" > manifest.mf jar cvfm $(MAINCLASS).jar manifest.mf *.class echo "#!/bin/bash" > startProgram.sh echo "java -jar $(MAINCLASS).jar" >> startProgram.sh echo "java -jar $(MAINCLASS).JAR" > startProgram.bat import org.junit.Test; import static org.junit.Assert.*; public class Program01Test { @Test public void testDigest() { String d1 = "46ff53e764c4acf97b54db2020573049d2e3dab3"; assertEquals(d1, Program01.digest("titok")); String d2 = "5f5ea3800d9a62bc5a008759dbbece9cad5db58f"; assertEquals(d2, Program01.digest("alma")); } } import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; class Program01 { public static String digest(String clearText) { String digestText = null; try { digestText = tryDigest(clearText); }catch(NoSuchAlgorithmException ex) { System.err.println("Nincs ilyen algoritmus"); } return digestText; } public static String tryDigest(String clearText) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA1"); byte[] sb = md.digest(clearText.getBytes()); StringBuffer hexText = new StringBuffer(); for (int i=0; i ===== Linkek ===== * http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest * http://www.faqs.org/rfcs/rfc3174.html (SHA algoritmus)