чат гпт бустПринцип работы ClassLoader и защита классов
ClassLoader в Java — это часть Java Runtime Environment (JRE), которая загружает классы Java в память при их первом использовании. В Java классы не встроены напрямую в исполняемый код; они загружаются по мере необходимости.
Создание и компиляция нашей .jar
В нашей .jar будет несколько классов: основной класс Main, который будет запускать остальные, и два других класса для проверки работы ClassLoader.
Main.java:
Test1.java:Main:public class Main { public static void main(String[] args) { test2.One(); test3.Two(); } }
Test2.java:test1:public class test1 { public static void One() { System.out.println("был загружен 1 class"); } }
Чтобы скомпилировать эти файлы в .jar:test2:public class test2 { public static void Two() { System.out.println("был загружен 2 class"); } }
Шифрование класса
- Нажмите
Win + R
, введитеcmd
и запустите командную строку.- Перейдите в директорию, где находятся файлы
.java
. Например,C:\Users\user\Desktop
.- Введите команду
javac -d ./build *.java
. В папке build появятся несколько файлов.class
.- Перейдите в директорию build командой
cd build
и создайте .jar файл командойjar cvf test.jar *
.- Откройте созданный .jar файл через WinRAR, перейдите в папку META-INF и откройте файл MANIFEST.MF.
- Вставьте в самом низу
Main-Class: Main
, сохраните документ и выйдите.
Теперь создадим класс Crypter для шифрования нашего класса:
Скомпилируйте и запустите этот класс командойCrypter:import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.swing.*; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.List; public class Crypter extends JFrame { private static final byte[] KEY_BYTES = { (byte)0x01, (byte)0x23, (byte)0x67, (byte)0x45, (byte)0x89, (byte)0xCD, (byte)0xAB, (byte)0xEF, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xEF, (byte)0xCD }; private JTextField inputFileField; private JTextField outputFileField; private JButton encryptButton; public Crypter() { setTitle("File Encrypter"); setSize(400, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 0; gbc.gridy = 0; panel.add(new JLabel("Input File:"), gbc); gbc.gridx = 1; inputFileField = new JTextField(); panel.add(inputFileField, gbc); gbc.gridx = 0; gbc.gridy = 1; panel.add(new JLabel("Output File:"), gbc); gbc.gridx = 1; outputFileField = new JTextField(); panel.add(outputFileField, gbc); gbc.gridx = 1; gbc.gridy = 2; encryptButton = new JButton("Encrypt"); panel.add(encryptButton, gbc); add(panel); encryptButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { encryptFile(); } }); new DropTarget(inputFileField, new FileDropTargetListener()); } private void encryptFile() { File inFile = new File(inputFileField.getText()); File outFile = new File(outputFileField.getText()); try { SecretKey secretKey = new SecretKeySpec(KEY_BYTES, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); FileInputStream fis = new FileInputStream(inFile); byte[] inputBytes = new byte[(int) inFile.length()]; fis.read(inputBytes); byte[] outputBytes = cipher.doFinal(inputBytes); FileOutputStream fos = new FileOutputStream(outFile); fos.write(outputBytes); fis.close(); fos.close(); JOptionPane.showMessageDialog(this, "Encryption completed."); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Error during encryption: " + ex.getMessage()); } } private class FileDropTargetListener extends DropTargetAdapter { @Override public void drop(DropTargetDropEvent dtde) { try { dtde.acceptDrop(DnDConstants.ACTION_COPY); List<File> droppedFiles = (List<File>) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); if (!droppedFiles.isEmpty()) { File file = droppedFiles.get(0); inputFileField.setText(file.getAbsolutePath()); } } catch (Exception ex) { ex.printStackTrace(); } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Crypter().setVisible(true); } }); } }
java Crypter
. Если у вас открылось окно, значит вы сделали всё правильно, дальше можно просто закинуть файл. [Пожалуйста, авторизуйтесь для просмотра ссылки.]
Если вы увидите сообщениеEncryption completed.
Посмотреть вложение 284966
значит шифрование прошло успешно.
Загрузка и расшифровка класса
Теперь напишем загрузчик классов, который будет расшифровывать и загружать наш класс:
Скомпилируйте и запустите этот загрузчик. Если вы увидите 2 сообщенияClassLoader1:import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.lang.reflect.Method; import java.nio.file.Files; import java.security.Key; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; public class ClassLoader1 extends ClassLoader { private static final byte[] KEY_BYTES = { (byte)0x01, (byte)0x23, (byte)0x67, (byte)0x45, (byte)0x89, (byte)0xCD, (byte)0xAB, (byte)0xEF, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xEF, (byte)0xCD }; public ClassLoader1(ClassLoader parent) { super(parent); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { try { File encryptedJarFile = new File("C:/Users/users/Desktop/ja1r.jar"); byte[] encryptedJarBytes = Files.readAllBytes(encryptedJarFile.toPath()); Key key = new SecretKeySpec(KEY_BYTES, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decryptedJarBytes = cipher.doFinal(encryptedJarBytes); try (InputStream is = new ByteArrayInputStream(decryptedJarBytes); JarInputStream jarStream = new JarInputStream(is)) { JarEntry entry; while ((entry = jarStream.getNextJarEntry()) != null) { if (entry.getName().equals(name.replace('.', '/') + ".class")) { byte[] classBytes = jarStream.readAllBytes(); return defineClass(name, classBytes, 0, classBytes.length); } } } throw new ClassNotFoundException("Class " + name + " not found in decrypted jar"); } catch (Exception e) { throw new ClassNotFoundException("Could not load class " + name, e); } } public static void main(String[] args) { ClassLoader1 classLoader = new ClassLoader1(ClassLoader.getSystemClassLoader()); try { Class<?> loadedClass = classLoader.findClass("Main"); System.out.println("Loaded class: " + loadedClass.getName()); Method mainMethod = loadedClass.getMethod("main", String[].class); String[] mainArgs = new String[]{}; mainMethod.invoke(null, (Object) mainArgs); } catch (Exception e) { e.printStackTrace(); } } }
значит загрузка и расшифровка прошли успешноКод:был загружен 1 class был загружен 2 class
Теперь у вас есть базовое понимание работы ClassLoader и пример защиты классов с помощью шифрования. Вы можете доработать этот пример и создать более сложный загрузчик классов.
Upd: поставьте лайк , я старался писать эту тему.
имба спастил себеПринцип работы ClassLoader и защита классов
ClassLoader в Java — это часть Java Runtime Environment (JRE), которая загружает классы Java в память при их первом использовании. В Java классы не встроены напрямую в исполняемый код; они загружаются по мере необходимости.
Создание и компиляция нашей .jar
В нашей .jar будет несколько классов: основной класс Main, который будет запускать остальные, и два других класса для проверки работы ClassLoader.
Main.java:
Test1.java:Main:public class Main { public static void main(String[] args) { test2.One(); test3.Two(); } }
Test2.java:test1:public class test1 { public static void One() { System.out.println("был загружен 1 class"); } }
Чтобы скомпилировать эти файлы в .jar:test2:public class test2 { public static void Two() { System.out.println("был загружен 2 class"); } }
Шифрование класса
- Нажмите
Win + R
, введитеcmd
и запустите командную строку.- Перейдите в директорию, где находятся файлы
.java
. Например,C:\Users\user\Desktop
.- Введите команду
javac -d ./build *.java
. В папке build появятся несколько файлов.class
.- Перейдите в директорию build командой
cd build
и создайте .jar файл командойjar cvf test.jar *
.- Откройте созданный .jar файл через WinRAR, перейдите в папку META-INF и откройте файл MANIFEST.MF.
- Вставьте в самом низу
Main-Class: Main
, сохраните документ и выйдите.
Теперь создадим класс Crypter для шифрования нашего класса:
Скомпилируйте и запустите этот класс командойCrypter:import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.swing.*; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.List; public class Crypter extends JFrame { private static final byte[] KEY_BYTES = { (byte)0x01, (byte)0x23, (byte)0x67, (byte)0x45, (byte)0x89, (byte)0xCD, (byte)0xAB, (byte)0xEF, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xEF, (byte)0xCD }; private JTextField inputFileField; private JTextField outputFileField; private JButton encryptButton; public Crypter() { setTitle("File Encrypter"); setSize(400, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 0; gbc.gridy = 0; panel.add(new JLabel("Input File:"), gbc); gbc.gridx = 1; inputFileField = new JTextField(); panel.add(inputFileField, gbc); gbc.gridx = 0; gbc.gridy = 1; panel.add(new JLabel("Output File:"), gbc); gbc.gridx = 1; outputFileField = new JTextField(); panel.add(outputFileField, gbc); gbc.gridx = 1; gbc.gridy = 2; encryptButton = new JButton("Encrypt"); panel.add(encryptButton, gbc); add(panel); encryptButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { encryptFile(); } }); new DropTarget(inputFileField, new FileDropTargetListener()); } private void encryptFile() { File inFile = new File(inputFileField.getText()); File outFile = new File(outputFileField.getText()); try { SecretKey secretKey = new SecretKeySpec(KEY_BYTES, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); FileInputStream fis = new FileInputStream(inFile); byte[] inputBytes = new byte[(int) inFile.length()]; fis.read(inputBytes); byte[] outputBytes = cipher.doFinal(inputBytes); FileOutputStream fos = new FileOutputStream(outFile); fos.write(outputBytes); fis.close(); fos.close(); JOptionPane.showMessageDialog(this, "Encryption completed."); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Error during encryption: " + ex.getMessage()); } } private class FileDropTargetListener extends DropTargetAdapter { @Override public void drop(DropTargetDropEvent dtde) { try { dtde.acceptDrop(DnDConstants.ACTION_COPY); List<File> droppedFiles = (List<File>) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); if (!droppedFiles.isEmpty()) { File file = droppedFiles.get(0); inputFileField.setText(file.getAbsolutePath()); } } catch (Exception ex) { ex.printStackTrace(); } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Crypter().setVisible(true); } }); } }
java Crypter
. Если у вас открылось окно, значит вы сделали всё правильно, дальше можно просто закинуть файл. [Пожалуйста, авторизуйтесь для просмотра ссылки.]
Если вы увидите сообщениеEncryption completed.
Посмотреть вложение 284966
значит шифрование прошло успешно.
Загрузка и расшифровка класса
Теперь напишем загрузчик классов, который будет расшифровывать и загружать наш класс:
Скомпилируйте и запустите этот загрузчик. Если вы увидите 2 сообщенияClassLoader1:import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.lang.reflect.Method; import java.nio.file.Files; import java.security.Key; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; public class ClassLoader1 extends ClassLoader { private static final byte[] KEY_BYTES = { (byte)0x01, (byte)0x23, (byte)0x67, (byte)0x45, (byte)0x89, (byte)0xCD, (byte)0xAB, (byte)0xEF, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xEF, (byte)0xCD }; public ClassLoader1(ClassLoader parent) { super(parent); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { try { File encryptedJarFile = new File("C:/Users/users/Desktop/ja1r.jar"); byte[] encryptedJarBytes = Files.readAllBytes(encryptedJarFile.toPath()); Key key = new SecretKeySpec(KEY_BYTES, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decryptedJarBytes = cipher.doFinal(encryptedJarBytes); try (InputStream is = new ByteArrayInputStream(decryptedJarBytes); JarInputStream jarStream = new JarInputStream(is)) { JarEntry entry; while ((entry = jarStream.getNextJarEntry()) != null) { if (entry.getName().equals(name.replace('.', '/') + ".class")) { byte[] classBytes = jarStream.readAllBytes(); return defineClass(name, classBytes, 0, classBytes.length); } } } throw new ClassNotFoundException("Class " + name + " not found in decrypted jar"); } catch (Exception e) { throw new ClassNotFoundException("Could not load class " + name, e); } } public static void main(String[] args) { ClassLoader1 classLoader = new ClassLoader1(ClassLoader.getSystemClassLoader()); try { Class<?> loadedClass = classLoader.findClass("Main"); System.out.println("Loaded class: " + loadedClass.getName()); Method mainMethod = loadedClass.getMethod("main", String[].class); String[] mainArgs = new String[]{}; mainMethod.invoke(null, (Object) mainArgs); } catch (Exception e) { e.printStackTrace(); } } }
значит загрузка и расшифровка прошли успешноКод:был загружен 1 class был загружен 2 class
Теперь у вас есть базовое понимание работы ClassLoader и пример защиты классов с помощью шифрования. Вы можете доработать этот пример и создать более сложный загрузчик классов.
Upd: поставьте лайк , я старался писать эту тему.
Проект предоставляет различный материал, относящийся к сфере киберспорта, программирования, ПО для игр, а также позволяет его участникам общаться на многие другие темы. Почта для жалоб: admin@yougame.biz