[[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)