From e9182bbd6b361ee28ee511fae8e7020c6a00e84c Mon Sep 17 00:00:00 2001 From: Nikola-Mircic Date: Sat, 30 Dec 2023 11:37:25 +0100 Subject: [PATCH] Encrypting and decrypting user's API key --- .gitignore | 1 + src/efakturaplus/App.java | 27 ++++ src/efakturaplus/gui/KeyPanel.java | 236 ++++++++++++++++++++++++----- src/efakturaplus/gui/Window.java | 6 +- 4 files changed, 227 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index eced22f..7355df1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /bin/ /samples/ /PDFs/ +user.enc \ No newline at end of file diff --git a/src/efakturaplus/App.java b/src/efakturaplus/App.java index 8a839c6..6ac6551 100644 --- a/src/efakturaplus/App.java +++ b/src/efakturaplus/App.java @@ -1,10 +1,37 @@ package efakturaplus; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.InputStreamReader; + import efakturaplus.gui.Window; +import efakturaplus.models.User; public class App { public static void main(String[] args) { + try { + File f = new File("user.enc"); + + if(f.exists()) { + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new FileReader(f)); + StringBuilder sb = new StringBuilder(); + String line; + while((line = br.readLine()) == null) { + sb.append(line); + } + + User.API_KEY = sb.toString(); + } + + }catch(Exception e){ + System.out.println("Error reading a file!"); + }; + @SuppressWarnings("unused") Window w = new Window(); } diff --git a/src/efakturaplus/gui/KeyPanel.java b/src/efakturaplus/gui/KeyPanel.java index e3bd86f..09612e3 100644 --- a/src/efakturaplus/gui/KeyPanel.java +++ b/src/efakturaplus/gui/KeyPanel.java @@ -1,66 +1,226 @@ package efakturaplus.gui; -import java.awt.Color; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import javax.crypto.*; +import javax.crypto.spec.*; + +import sun.misc.*; + +import java.util.Arrays; +import java.util.Base64; import javax.swing.BorderFactory; +import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JPasswordField; import javax.swing.JTextField; +import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import ch.randelshofer.util.ArrayUtil; import efakturaplus.models.User; public class KeyPanel extends JPanel { private static final long serialVersionUID = 1L; + + private String password; + private byte[] iv; + + JLabel keyLabel, passLabel, passLabel2; + JTextField keyInput; + JPasswordField passInput, passInput2; private Window parent; + + private boolean registeredUser; public KeyPanel(Window parent, int width, int height) { this.parent = parent; this.setSize(width, height); this.setLayout(null); - - addLabel(width, height); - addTextField(width, height); - } - - private void addLabel(int width, int height) { - JLabel label = new JLabel("Please enter your API key here:"); - label.setFont(new Font("Arial", Font.PLAIN, 20)); - label.setBounds(width/2-150, height/2-75, 350, 50); - - label.setForeground(Color.black); - - this.add(label); + + addComponents(width, height); } - private void addTextField(int width, int height) { - JTextField keyInput = new JTextField(); - keyInput.setBounds(width/2-150, height/2-25, 300, 60); - - keyInput.setBorder(BorderFactory.createLineBorder(Color.black, 3, true)); - - keyInput.setBorder(BorderFactory.createCompoundBorder( - keyInput.getBorder(), - BorderFactory.createEmptyBorder(15, 15, 15, 15))); - - keyInput.setFont(new Font("Arial", Font.PLAIN, 20)); - - keyInput.addActionListener(new ActionListener() { - + private void addComponents(int width, int height) { + + Font font = new Font("Arial", Font.PLAIN, 20); + + passLabel = new JLabel("Please enter your password here:"); + passLabel.setFont(font); + passLabel.setForeground(Color.black); + + passInput = new JPasswordField(); + addBorder(passInput, Color.black); + passInput.setFont(font); + + passInput.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - User.API_KEY = keyInput.getText(); - System.out.println(User.API_KEY); - - parent.showMainPanel(); + submitData(); } }); - - this.add(keyInput); + + File userData = new File("user.enc"); + + if(!userData.exists()) { + keyLabel = new JLabel("Please enter your API key here:"); + keyLabel.setFont(font); + keyLabel.setForeground(Color.black); + keyLabel.setBounds(width/2-150, height/4-75, 350, 50); + + keyInput = new JTextField(); + keyInput.setBounds(width/2-150, height/4-25, 300, 60); + addBorder(keyInput, Color.black); + keyInput.setFont(font); + + keyInput.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + submitData(); + } + }); + + passLabel.setText("Please enter new password:"); + passLabel.setBounds(width/2-150, height/2-75, 350, 50); + passInput.setBounds(width/2-150, height/2-25, 300, 60); + + passLabel2 = new JLabel("Please enter your password again:"); + passLabel2.setFont(font); + passLabel2.setForeground(Color.black); + passLabel2.setBounds(width/2-150, height*3/4-75, 350, 50); + + + passInput2 = new JPasswordField(); + addBorder(passInput2, Color.black); + passInput2.setFont(font); + passInput2.setBounds(width/2-150, height*3/4-25, 300, 60); + + passInput2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + submitData(); + } + }); + + this.add(keyLabel); + this.add(keyInput); + this.add(passLabel); + this.add(passInput); + this.add(passLabel2); + this.add(passInput2); + }else { + passLabel.setBounds(width/2-150, height/2-75, 350, 50); + passInput.setBounds(width/2-150, height/2-25, 300, 60); + this.add(passLabel); + this.add(passInput); + } + } + + private void addBorder(JComponent comp, Color c) { + comp.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(c, 3, true), + BorderFactory.createEmptyBorder(15, 15, 15, 15))); + } + + private void submitData() { + File userData = new File("user.enc"); + + if(!userData.exists()) { + User.API_KEY = keyInput.getText(); + + try { + encryptData(); + } catch (Exception e) { + e.printStackTrace(); + } + + addComponents(getWidth(), getHeight()); + } + else { + try { + System.out.println("Decrypted: "+decryptData()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void encryptData() throws NoSuchAlgorithmException, InvalidKeySpecException { + SecureRandom random = new SecureRandom(); + byte[] salt = new byte[8]; + random.nextBytes(salt); + + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec spec = new PBEKeySpec(passInput.getPassword(), salt, 65536, 256); + SecretKey tmp = factory.generateSecret(spec); + SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secret); + AlgorithmParameters params = cipher.getParameters(); + byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); + byte[] ciphertext = cipher.doFinal(keyInput.getText().getBytes()); + + System.out.println("IV length: "+iv.length); + System.out.println("Cipher text length: "+ciphertext.length); + + FileOutputStream fos = new FileOutputStream("user.enc"); + + fos.write(iv); + fos.write(salt); + fos.write(ciphertext); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private String decryptData() { + String content = ""; + + try (FileInputStream fileIn = new FileInputStream("user.enc")) { + byte[] fileIv = new byte[16]; + byte[] salt = new byte[8]; + byte[] data = new byte[16]; + + fileIn.read(fileIv); + fileIn.read(salt); + fileIn.read(data); + + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec spec = new PBEKeySpec(passInput.getPassword(), salt, 65536, 256); + SecretKey tmp = factory.generateSecret(spec); + SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); + + System.out.println(fileIv.toString()); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(fileIv)); + String plaintext = new String(cipher.doFinal(data)); + + content = plaintext; + + }catch(Exception e) { + e.printStackTrace(); + } + + return content; } - } diff --git a/src/efakturaplus/gui/Window.java b/src/efakturaplus/gui/Window.java index 767279b..35abb35 100644 --- a/src/efakturaplus/gui/Window.java +++ b/src/efakturaplus/gui/Window.java @@ -47,11 +47,7 @@ public Window(String title) { this.add(keyPanel, "KEY_PANEL"); this.add(mainPanel, "MAIN_PANEL"); - if(User.API_KEY == "") { - showKeyPanel(); - }else { - showMainPanel(); - } + showKeyPanel(); this.setVisible(true); }