Encrypted file exchange in Java

krakatoa
CERTIFIED EXPERT
Everything will happen at least once, otherwise there would be no such thing as probability.
 Probably.

AI : Guess until you get it right.
Published:
Updated:
Edited by: Andrew Leniart
A small  app supported on a minimalist GUI framework, allowing two hosts to send and receive any kind and any number of files between them.
This is a functioning, but work-in-progress application, pushing out a decentralized model for exchanging files between two networked computers. The architecture is peer-to-peer.

The salient Java and networking principles at work in this application can be summarised as follows :

Both endpoints run a listening ServerSocket standing ready to host a connection from the other. For that, one end (at least) requires the remote terminal's IP address. Each peer's world-facing IP address is conveniently displayed on the GUI at startup for this purpose.

With the remote peer's IP address input into the local app, a button click initiates a connection. This involves first interrogating the app's USB stick (which must be present in one of the computers in real-time), for the ROM's unique disk ID for the stick. This ID is then compared with the ID embedded in the compiled code and exchanged via an MD5 hash with the other peer. If the exchange of IDs results in a match, an SSL connection is established, and file transfers may be undertaken.

A JFileChooser button is activated to choose files to send on the wire. These files can be picked from any visible path (directory) on the local infrastructure. Received files are automatically placed into a directory of their own, which the user must make prior to using the app (with the source code as it stands). The receiving directory, in this case, is called "InFiles", and resides in a parent directory called "TransferHolder", which must also be created by the user in advance, off the root of C: The TransferHolder directory is simply a convenience directory in which files that the user intends to send can be held - (although, as described earlier, they can be chosen from anywhere on the visible system).

The programme runs only on Windows. Native calls to the OS asking for the USB disk ID mean that it has not been adapted for other platforms. Deployment on a Java JVM prior to version 12 will require changes to those native method calls since parameters have changed. There should be no problems when Java version 12 and above in service, however.

There is no intervening station or server between the peers, and therefore the 'session' and its immediate metadata exist only on the sending and receiving peers. The files are encrypted in transit with SSL/TLS. The establishment and negotiation of the SSL connection can be observed at startup by using the command line syntax for launching the app of  :

java -Djavax.net.debug=ssl Serpent
or

java -jar -Djavax.net.debug=ssl Serpent.jar
if running as a .jar file.

Naturally, as a user, you would need to arrange your own keystore and security PKI specifics, in addition to determining the USB stick's disk ID from examining the registry entry. (Tips on both these areas are given at the unconventional comment top of the source code file).

The main code - in Serpent.java - is supported by a class making native calls to the Windows OS. This class is USBVerify.java.

Here is the main class source :

//Code By: GB. Aug Sept Oct 2018.

//keytool -genkeypair -keyalg RSA -keysize 2048 -keystore test.jks -storepass lssetna

//javac Serpent.java

//jar cfmv Serpent.jar MANIFEST.MF Serpent*.class USBVerify.class SSL_Padlock.jpg test.jks //Arrange your own keystore and Manifest.

//java -Djavax.net.debug=ssl Serpent

//java -jar -Djavax.net.debug=ssl Serpent.jar

// Ports : 40000 and 40001.

//HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum"     - Key entry of disk drives, incl USB

//sleeperror catch added 09 Apr 2019.

/* Preparation sequence :

*****************************************

1. javac Serpent.java

2. jar cfmv Serpent.jar MANIFEST.MF Serpent*.class USBVerify.class SSL_Padlock.jpg test.jks

run . . .

3. java -jar Serpent.jar  

OR

Double-click the Serpent.jar


*****************************************

*/


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.prefs.Preferences;

import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.event.*;
import java.nio.file.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import javax.net.*;
import javax.net.ssl.*;
import java.security.KeyStore;
import java.security.Security;
import java.nio.ByteOrder;
import java.security.Provider;
import java.security.MessageDigest;
import java.util.stream.Stream;

 
 class Serpent extends JFrame implements ActionListener{
 
 JButton showfilechooser;
 JTextArea ipBox;
 JFileChooser jfc;
 String targetIPAddress;
 boolean notconnected = true;
 ServerSocket servermonitorsocket;
 Socket aliveSocket;
 SSLSocket sslSocket;
 Client client;
 ConnectionMonitor connectionmonitor;
 boolean aclientrunning = false;
 String myIP;
 File[] outgoingFiles;
 File[] incomingFiles;
 ObjectOutputStream oos;
 ObjectInputStream ois;
 JButton joinButton;
 Thread thread;
 String remoteserverIP;
 JRadioButton jrb;
 boolean loopbacktry;
 PrintWriter pW;
 BufferedReader bR;
 boolean keepasserver; 
 
   
 private final int BASECHUNK = 32768;
 
 private boolean engaged; 
 private USBVerify cid;
 private Boolean commsClearThisEnd = false;
 private Boolean commsAllClear = false;
 
 
     
    public static void main(String[] args){

                Serpent serpent = new Serpent(args);
                if(!(serpent.chkRegKey()==true)){serpent.commsClearThisEnd = false;}
                else{serpent.commsClearThisEnd = true;}
                    
            
    }
 
 
    private Serpent(String[] args){
    
            
            init();
            
            new Thread(new ServDriver()).start();
            
                        
    }
    
    
    
    private boolean chkRegKey(){
          
    try{
        
        this.cid = new USBVerify(); 
               
        return  this.cid.verifyCruz();
        
    }catch(Exception ptolomy){ptolomy.printStackTrace();return false;}
    
    }
    
    
 
    public void actionPerformed(ActionEvent ae){
 
        String buttonName = ((JButton)ae.getSource()).getName();
        
        switch (buttonName) {
        
            case "helpbutton" :  
                
                JOptionPane jop = new JOptionPane();
                
                
                jop.showMessageDialog(this, 
                " *  To connect to a partner, (a.k.a. interlocutor, correspondent), enter their IP address into the white box in the bottom, middle of the main window, and push Enter.\n * Then click \"Connect Out\"\n *  If they are connecting to YOU first, let them know the IP address given above.\n\n ------------------\n\n TO SEND FILES OR TO SEE FILES SENT TO YOU  : \n\n\n TO SEND :\n 1. Click Filechooser to choose files to SEND. You can choose from anywhere on your system. \n 2. Select those files using mouse (and shift key if required).\n 3. Click 'Open Files'.\n\n TO SEE RECEIVED FILES :\n  Look in your 'InFiles' folder for files that have been sent TO YOU.\n\n\n N.B. This version will operate correctly only if 2 nested directories are present : namely \"C:\\TransferHolder\\InFiles\" \n Therefore you should make TransferHolder off the C drive, and a sub-folder called InFiles before you run this programme. \n (The directory you create called TransferHolder is just a suggestion as to where you can keep files you intend to send, but it, and its subfolder \"InFiles\" must both exist). \n Thanks.","The IP Address your partner needs is "+myIP,JOptionPane.INFORMATION_MESSAGE);
                
                break;
                                 
            case "filechooser" :
                
                if(engaged == true){break;}
                
                
                if(( sslSocket== null)||pW.checkError()){return;} 
   
                          
                jfc = new JFileChooser(new JFileChooser().getFileSystemView());
                jfc.setMultiSelectionEnabled(true);
      
                jfc.setSize(new Dimension(500,400));            
                jfc.setVisible(true);
                jfc.setCurrentDirectory(new File("C:/TransferHolder"));
                
                int yes = jfc.showOpenDialog(null);
                
                if (yes == JFileChooser.APPROVE_OPTION) {
                
                    outgoingFiles = jfc.getSelectedFiles();
                                                         
                
                    try{
                                                
                        FileSender fS = new FileSender(outgoingFiles);  
                        
                        Thread t = new Thread(fS);
                        t.start();
                        
                        
                    }catch (Exception nc){nc.printStackTrace();}
                    
                                    
                }
               
                break;
                
            
            case "joinbutton" :
            
            if(ipBox.getText().equals("")){return;}
            if(loopbacktry){ipBox.setText("");loopbacktry=false;return;}
            
            if(aclientrunning){pW.close();System.out.println("A connection is already current.");}
            
              
            if(keepasserver){return;}
              
            GetSocket gs = new GetSocket();
                  
                    gs.getSock(targetIPAddress,40000);
                             

                    if(aclientrunning ){
                    
                    try{
                            thread = null;client.keeprunning = false; client = null;
                    }catch(Exception sleeperror){aclientrunning = false;/*sleeperror.printStackTrace();System.out.println("Recovering possible sleeperror");*/}
                            client  = new Client();
                            thread = new Thread(client);
                            thread.start();       
                    }
                    
                    
                   
                    else {
                            
                            client = new Client();
                            thread = new Thread(client);
                            thread.start();
                            
                    } 
                            
                    aclientrunning = true;
                          
                                                
                if(gs.getLSocket(targetIPAddress,40001)){
                    aliveSocket = gs.lSock;
                    ConnectionMonitor cm = new ConnectionMonitor();
                    Thread cmThread = new Thread(cm);
                    cmThread.start();
                }
           
                gs = null;
                
                break;
        }       
       
    }
    
 
    void init(){
    
        this.setSize(new Dimension(550,185));
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        
        showfilechooser = new JButton("Show Filechooser");
        showfilechooser.setName("filechooser");
        showfilechooser.addActionListener(this);
        
        this.add(new JPanel(), BorderLayout.NORTH);
        this.add(new JPanel(), BorderLayout.WEST);
        this.add(new JPanel(), BorderLayout.EAST);
        
       
        JPanel jp = new JPanel();
        this.add(jp, BorderLayout.CENTER);
        jp.add(showfilechooser);
        JButton helpButton = new JButton("Help");
        helpButton.setName("helpbutton");
        jp.add(helpButton);
        helpButton.addActionListener(this);
         
                
        ipBox = new JTextArea();
        ipBox.setMaximumSize(new Dimension(90,18));
        ipBox.addKeyListener(new IPInputListener());
        ipBox.setLineWrap(true);
        ipBox.setVisible(true); 
        
                
        JPanel southPanel = new JPanel();
        southPanel.setLayout(new GridLayout());
        southPanel.setPreferredSize(new Dimension(this.getWidth(),19));
        
        this.add(southPanel,BorderLayout.SOUTH);
        
        jrb = new JRadioButton("Idle",false);
        jrb.setEnabled(false);
        jrb.setOpaque(true);
        jrb.setBackground(java.awt.Color.GRAY);
        jrb.setForeground(java.awt.Color.BLACK);

        joinButton = new JButton("Connect Out");
        joinButton.setName("joinbutton"); 
        joinButton.addActionListener(this);
                
        southPanel.add(jrb);
        southPanel.add(ipBox); 
        southPanel.add(joinButton);  
        
        this.setTitle("World-facing IP address is > "+(myIP=findMyIP()));
        
        
        try{
        
            InputStream streamForPadlock = Thread.currentThread().getContextClassLoader().getResourceAsStream("SSL_Padlock.jpg");
            ImageIcon padlockImage = new ImageIcon(ImageIO.read(streamForPadlock).getScaledInstance(1800,1800,Image.SCALE_DEFAULT));
            this.setIconImage(padlockImage.getImage());
            
        }catch(Exception ioex){ioex.printStackTrace();}
        
        this.setVisible(true);
    
    }

        
    public class GetSocket{
              
        
        public Socket lSock;
        
        public SSLSocket getSock(String host, int port){
                   
                                        
                    try{
                        if(host.equals(InetAddress.getLocalHost().toString().substring(InetAddress.getLocalHost().toString().indexOf("/")+1))){return null;}
                    }catch(Exception ukhe){}
                    
        
                    try{   
                        
                                    
                        InputStream keyInput = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.jks");
                        
                        KeyStore keyyStore = KeyStore.getInstance(KeyStore.getDefaultType());   

                        keyyStore.load(keyInput, "lssetna".toCharArray());

                        // initialize a key manager factory with the key store
                        KeyManagerFactory keyyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());    
                        keyyFactory.init(keyyStore, "lssetna".toCharArray());
                                              
                        
                        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                        trustManagerFactory.init(keyyStore);
                        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
                        
                        SSLContext ctxx = SSLContext.getInstance("SSL");
                        ctxx.init(null, trustManagers, null);                                             
                        SSLSocketFactory ssl_s_f = ctxx.getSocketFactory();
                                           
                        
                        try{
                       
                                                
                        sslSocket = (SSLSocket) ssl_s_f.createSocket(InetAddress.getByName(host),port);
                        
                        }catch(IOException ioexxx){/*ioexxx.printStackTrace();*/pW.close();jrb.setSelected(false);jrb.setBackground(java.awt.Color.GRAY);jrb.setOpaque(true);jrb.setText("Idle");} //Produces a Timeout exception, so it needs to be handled or ignored. (better).
                                                                                                   
                    }catch(Exception unhe){unhe.printStackTrace();jrb.setSelected(false);jrb.setBackground(java.awt.Color.GRAY);jrb.setOpaque(true);jrb.setText("Idle");ipBox.setBackground(java.awt.Color.RED);ipBox.setText("No connection to that IP");pW.close();return null;}
                    
                    return sslSocket;
        
        }
        
        public boolean getLSocket(String host, int port){
        
            try{
                
                        lSock = new Socket();
                        lSock.connect(new InetSocketAddress(host, port), 20000);
                
            }catch(Exception unhe){jrb.setSelected(false);jrb.setBackground(java.awt.Color.GRAY);jrb.setOpaque(true);jrb.setText("Idle");ipBox.setBackground(java.awt.Color.RED);ipBox.setText("No connection to that IP");pW.close();return false;}
            
            return true;
        }
    
    }
  
    
    private class ConnectionMonitor implements Runnable{
    
        boolean talking;
    
        private void clearUp(){
               
                        jrb.setSelected(false);
                        jrb.setBackground(java.awt.Color.GRAY);
                        jrb.setOpaque(true);
                        jrb.setText("Idle");
                        ipBox.setText("");
                        client.keeprunning = false;
                        Thread.yield();
                         
                        try{
                        
                        pW.close();
                        bR.close();
                        
                        client = null;
                                              
                        }catch(Exception bye){}
        
        }
    
        public void run(){
        
                talking = true;
        
                try{
                    pW = new PrintWriter(new OutputStreamWriter(aliveSocket.getOutputStream(), "UTF-8"), true);
                    bR = new BufferedReader(new InputStreamReader(aliveSocket.getInputStream(), "UTF-8"));
                    
                    
                try {
                
                while (talking) { //*****maintain connection*****
           
                  
                        pW.println("noOp");
                                      
                        try{Thread.sleep(10000);}catch(Exception woken){}
                    
                        if (pW.checkError()) {
                        
                            clearUp(); 
                        }
                    
                                         
                                 
                }
                
            } catch (Exception intsoc) {}
            }catch(Exception setupex){}
            
        }
    
    }
    
    public class Client implements Runnable{
    
        private boolean keeprunning;
                  
        
        Client(){ 
                 
                jrb.setSelected(true);
                jrb.setOpaque(true);
                jrb.setBackground(java.awt.Color.GREEN);
                jrb.setText("Live");
                
                                
                ipBox.setBackground(java.awt.Color.WHITE);
                try{ipBox.setText("Partner :"+sslSocket.getRemoteSocketAddress());}catch(Exception tex){tex.printStackTrace();}
                       
        }
            
    
        public void run(){
        
            byte[] content = new byte[BASECHUNK];
            File fout;
            Long presentfilesize = 0L;
            long bytetally = 0;
            FileOutputStream fos = null;
              
            
            keeprunning=true;
         
                try{  
                
                    oos = new ObjectOutputStream(sslSocket.getOutputStream());
                    ois = new ObjectInputStream(sslSocket.getInputStream()); 
                    byte[] bA = null;
                                        
                                        
                    try{
                        oos.writeObject(commsClearThisEnd);
                        Boolean commsClearOtherEnd = (Boolean)ois.readObject();
                        commsAllClear = commsClearThisEnd ^ commsClearOtherEnd;
                        //System.out.println("commsClearThisEnd is "+commsClearThisEnd+" commsClearOtherEnd is "+commsClearOtherEnd+"  commsAllClear is "+commsAllClear); //DEBUG
                        
                        //Serpent.this.setTitle("commsClearThisEnd is "+commsClearThisEnd+" commsClearOtherEnd is "+commsClearOtherEnd+"  commsAllClear is "+commsAllClear);try{Thread.sleep(15000);}catch(Exception time){time.printStackTrace();} //DEBUG
                        
                        if(!(commsAllClear)){System.exit(0);}
                        
                        else{
                            if(commsClearThisEnd){
                            
                                MDCheck mdc = new MDCheck();
                                bA = mdc.genMDigest(cid.THISCRUZER);
                                
                                oos.writeObject(bA);
                            }
                            
                            else{
                                    
                                
                                byte[] inc = (byte[])ois.readObject();
                                
                                
                                MDCheck localmd = new MDCheck();
                                
                                        
                                byte[] bal = localmd.genMDigest(cid.THISCRUZER);
                                
                                if(!(MessageDigest.isEqual(bal, inc))){System.exit(-1);}
                                //else{/*System.out.println("Everything matches.");*/} //DEBUG
                            }
                        }
                    }catch(Exception noncompliance){}
                    
                                         
                }catch(IOException ioex){keeprunning = false;client=null;System.gc();return;}                      
               
                              
            while(keeprunning){
            
                    
                    try{
                               
                    Vector<? extends Object>vector = new Vector<>();
                    vector = (Vector<? extends Object>)(ois.readObject());   //read in vector of filenames

                    Window windowin = new Window(Serpent.this);
                    windowin.setSize(new Dimension(500,30));
                    windowin.setBackground(Color.YELLOW);
                    windowin.setLocationRelativeTo(null);
                    JLabel jlabelin = new JLabel();
                    windowin.add(jlabelin);
                    jlabelin.setVisible(true);
                    windowin.setVisible(true);                    
                    
                    
                    for(int s=0;s<vector.size();s++){
                    
                        fout = (new File("C:/TransferHolder/InFiles/"+vector.elementAt(s)));
                        
                        fos = new FileOutputStream(fout);
                        
                        presentfilesize = (Long)ois.readObject();
                        
                        try{
                        
                            int i = 0;
                            
                            jlabelin.setText("Receiving File . . . "+fout.toPath().toString());
                                
                            
                            while(!((i = ois.read(content,0,BASECHUNK))==-1)){
                            
                                                                
                                    bytetally+=i;

                                    if(bytetally-1 == presentfilesize){fos.write(content,0,i-1);break;} 
                                    
                                    fos.write(content,0,i); 
                                                                        
                                    //System.out.println("Content 0 = "+content[0]); //DEBUG
                                    //System.out.println("bytetally = "+bytetally+" presentfilesize = "+presentfilesize); //DEBUG
                                    
                                    content = new byte[BASECHUNK];
                                 
                            }
                            
                        }catch(Exception except){}
                                   
                            try{
                              bytetally=0;
                              presentfilesize = 0L;
                              fos.close();
                              //System.out.println("finished write to disk"); //DEBUG
                            }catch(Exception ending){}
                            
                    }
                   
                   
                    jlabelin.setText(" "+vector.size()+" file(s) received.");
                    try{Thread.sleep(1800);}catch(InterruptedException intex){intex.printStackTrace();}
                    windowin.setVisible(false); 
                   
                    JOptionPane jop = new JOptionPane();
                    
                    if(vector.size() >1){
                        
                         jop.showMessageDialog(Serpent.this," You have received "+vector.size()+" new files.");
                         jop.grabFocus();
                        
                    }
                    
                    else if(vector.size() == 1){
                        
                         jop.showMessageDialog(Serpent.this," You have received 1 new file.");
                         jop.grabFocus();
                        
                        }
                    
                    }catch(Exception socketDown){keeprunning = false;/*socketDown.printStackTrace();*/} 
                    
                }//keeprunning
                                 
            }//run
          
        }//client   
    
   
    class FileSender implements Runnable{
    
        File[] files;
        FileInputStream fis;
        //long accum = 0; //DEBUG
        byte[] endb = {-1};
        byte[] actual;
        Long thisfilesize = 0L;
        
        
        FileSender(File[] files){
        
            engaged = true;
            this.files = files;
             
        }
        
                
        
            public void run(){sendFiles(this.files);engaged = false;}
    
            private void sendFiles(File[] fArr){
            
                        
            Vector<String>vec = new Vector<String>(fArr.length);
    
                        
            for(File fi : fArr){vec.add(fi.getName());}
            
            
            //for(String s : vec) {System.out.println(s);} //DEBUG
                        
                        
             try{
                    
                  if(!(vec == null)){oos.writeObject(vec);} //send the filenames
                  
             }catch(IOException oosexception){oosexception.printStackTrace();}
             
            Window windowout = new Window(Serpent.this);
            windowout.setSize(new Dimension(500,30));
            windowout.setBackground(Color.YELLOW);
            windowout.setLocationRelativeTo(null);
            JLabel jlabelout = new JLabel();
            windowout.add(jlabelout);
            jlabelout.setVisible(true);
            windowout.setVisible(true);
            
                                   
                for(File file : files){
            
                    try{
       
                        fis = new FileInputStream(file);
                                                
                        oos.writeObject(file.length());
                   
                        byte[] bA = new byte[BASECHUNK];
                  
                        int i = 0;
                        
                        jlabelout.setText("Dispatching File . . . "+file.toPath().toString());
                        
                        try{
                        
                        while((i = fis.read(bA))!=-1){
                        
                                                                
                                actual = Arrays.copyOfRange(bA,0,i); 
                                oos.write(actual);
                            
                                //if(!(i==-1)){accum+=i;} //DEBUG
                                                               
                                bA = new byte[BASECHUNK];        
                    
                            }
                            
                     }catch(Exception indexoobx){}
                    
                    //System.out.println("Final i = "+i+"  "+"accum is "+accum+" file length is "+file.length()); //DEBUG
                    
                      try{
                      
                        //accum=0; //DEBUG
                        fis.close();  
                        oos.write(endb);
                        oos.flush();
                        
                      }catch(Exception changefile){}
                      
                    }catch(Exception ex){}
                    
                }
                
                jlabelout.setText(" "+files.length+" file(s) sent.");
                try{Thread.sleep(1800);}catch(InterruptedException intex){}
                windowout.setVisible(false);    
                                
        }

    }
    
    
    class ServDriver implements Runnable{
 
        public void run(){
 
            try{
            
          InputStream keystoreInput = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.jks");
                            
          KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());   

          keyStore.load(keystoreInput, "lssetna".toCharArray());

          // initialize a key manager factory with the key store
          KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());    
          keyFactory.init(keyStore, "lssetna".toCharArray());
  
          // get the key managers from the factory
          KeyManager[] keyManagers = keyFactory.getKeyManagers();
          
          SSLContext ctx = SSLContext.getInstance("SSL");
          ctx.init(keyManagers, null, null);
          SSLServerSocketFactory ssl_ss_f = ctx.getServerSocketFactory();

          ServerSocket sslServerSocket = (SSLServerSocket) ssl_ss_f.createServerSocket(40000);
            
          //System.out.println("ServerSocket up . . . "); //DEBUG
          
                        
            servermonitorsocket = new ServerSocket(40001);
                      
            while(true){   
        
                
                sslSocket = (SSLSocket)sslServerSocket.accept();
                
                //System.out.println("Connection established"); //DEBUG
                                
                sslSocket.setNeedClientAuth(false); 
                                             
                client = new Client();
          
                new Thread(client).start();
                
                aliveSocket = servermonitorsocket.accept(); 
              
                connectionmonitor = new ConnectionMonitor();
                
                Thread thr = new Thread(connectionmonitor);
                thr.setDaemon(true);
                thr.start();
                        
            }
        
            }catch(Exception sockex){}
    
        }
 
    }
    
    
    private String findMyIP(){
    
        String myIP = null;
        InetAddress ipAddress = null;
        
                try{
            
                        //ALL THESE 'WORK' - USE ANY ONE:
                        
                  URL url = new URL("https://whatsmyip.com");
                  //URL url = new URL("https://www.whatismyip.com/what-is-my-public-ip-address/");
                  //URL url = new URL("https://iplocation.net");
                  //URL url = new URL("https://cmyip.com");
                  
                        //ALL THE ABOVE WORK
                  
                URLConnection urlconn = url.openConnection();
                        //urlconn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
                urlconn.setRequestProperty("User-Agent","");
                        //Map<String, java.util.List<String>> map = new HashMap<String, java.util.List<String>>();
                        //map = urlconn.getHeaderFields();
                        //for(String s : map.keySet()){System.out.println(map.get(s)+"\n");}
                                
                
                BufferedReader bis = null;
            
                try{
                             
                Pattern pattern = Pattern.compile("(?<![0-9a-zA-Z.])(?:\\d{1,3}\\.){3}\\d{1,3}(?![0-9a-zA-Z.])"); 
          
                bis = new BufferedReader(new InputStreamReader(urlconn.getInputStream()));
            
                String line;
                       
                while(!((line = bis.readLine())==null)){
                
                    Matcher matcher = pattern.matcher(line); 
                    if(matcher.find()){
                        ipAddress = InetAddress.getByName(matcher.group());
                        //System.out.println(ipAddress); //DEBUG
                        if(!(ipAddress == null)){break;}
                    }
                    
                }
                
                }catch(IOException ioe){ioe.printStackTrace();}
                }catch(Exception mfuex){}
                
                myIP = ipAddress.toString();
                
                return myIP.replace("/","");
    
    }
        
 
        class IPInputListener extends KeyAdapter{
     
            public void keyReleased(KeyEvent k){
                
                if((ipBox.getBackground()==Color.GREEN)||(ipBox.getBackground()==Color.RED)){ipBox.setBackground(Color.WHITE);}
                if(!((k.getKeyChar()=='.')||(Character.isDigit(k.getKeyChar())))&&!(k.getKeyCode()==KeyEvent.VK_ENTER)){ipBox.setText("");ipBox.setBackground(Color.RED);try{Thread.sleep(300);}catch(Exception waiting){}return;}
                else if(ipBox.getText().length()>15&&!(k.getKeyCode()==KeyEvent.VK_ENTER)){ipBox.setText("");ipBox.setBackground(Color.RED);try{Thread.sleep(300);}catch(Exception waiting){}return;}
                
                if(k.getKeyCode()==KeyEvent.VK_ENTER){
                               
                    targetIPAddress = ipBox.getText();
                    
                    if(Pattern.matches("(?<![0-9a-zA-Z.])(?:\\d{1,3}\\.){3}\\d{1,3}(?![0-9a-zA-Z.])", targetIPAddress.trim())){
                    
                        ipBox.setText(ipBox.getText().trim()); //trim MUST be present.
                        ipBox.setBackground(Color.GREEN);
                        targetIPAddress = ipBox.getText();
                        remoteserverIP = targetIPAddress;
                        
                    }
                    else{ipBox.setText("");ipBox.setBackground(Color.RED);try{Thread.sleep(500);}catch(Exception waiting){}}
                }
                if(ipBox.getText().indexOf("127.")==0){
                    ipBox.setText("Loopback not addressable.");loopbacktry=true;
                }
                 
            }
        
        }
        
        
    public static String myPublicIp() {

        
        boolean found = true;
        
    try {
        String command = "nslookup myip.opendns.com resolver1.opendns.com";
        Process proc = Runtime.getRuntime().exec(command);

        BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String s;
        
        while ((s = stdInput.readLine()) != null) {
        
            if(s.contains("Address:")){found = !found;}
            if(found==true&&(s.contains("Address:"))){return s.substring("Address:".length(),s.length()).trim().toString();}
            
                        
        }
        
    } catch (IOException e) {
        e.printStackTrace();
        return null ;
    }

        return null ;
    }
    
            
       
 class MDCheck {


    private byte[] genMDigest(String thisCruzID)throws Exception{
        
        
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        
        md.update(thisCruzID.getBytes());
        
                //byte[] digest = md.digest(); 
                //MessageDigest md2 = MessageDigest.getInstance("SHA-256");
                //md2.update(receivedCruzID.getBytes());
                //byte[] digest2 = md2.digest();       
                //if (MessageDigest.isEqual(digest, digest2)){
                    //return "true";
                //}
                //else {return "false";}
        
        return md.digest();
       
    }
 }      
              
        
 }   



Here, USBVerify.java, the gateway to Windows OS calls to access the USB drive :

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.prefs.Preferences;


class USBVerify {


  public static final int HKEY_CURRENT_USER = 0x80000001;
  public static final int HKEY_LOCAL_MACHINE = 0x80000002;
  public static final int REG_SUCCESS = 0;
  public static final int REG_NOTFOUND = 2;
  public static final int REG_ACCESSDENIED = 5;

  public static final int KEY_WOW64_32KEY = 0x0200;
  public static final int KEY_WOW64_64KEY = 0x0100;

  public static final int KEY_ALL_ACCESS = 0xf003f;
  public static final int KEY_READ = 0x20019;
  public static Preferences userRoot = Preferences.userRoot();
  public static Preferences systemRoot = Preferences.systemRoot();
  public static Class<? extends Preferences> userClass = userRoot.getClass();
  public static Method regOpenKey = null;
  public static Method regCloseKey = null;
  public static Method regQueryValueEx = null;
  public static Method regEnumValue = null;
  public static Method regQueryInfoKey = null;
  public static Method regEnumKeyEx = null;
  public static Method regCreateKeyEx = null;
  public static Method regSetValueEx = null;
  public static Method regDeleteKey = null;
  public static Method regDeleteValue = null;
  
  
   public final String THISCRUZER = "4X530812210217XXX315&0"; // Enter USB Disk ID here
  
  static {
  
    try {
      
      regOpenKey     = userClass.getDeclaredMethod("WindowsRegOpenKey",     new Class[] { long.class, byte[].class, int.class });
      regOpenKey.setAccessible(true);
      regCloseKey    = userClass.getDeclaredMethod("WindowsRegCloseKey",    new Class[] { long.class });
      regCloseKey.setAccessible(true);
      regQueryValueEx= userClass.getDeclaredMethod("WindowsRegQueryValueEx",new Class[] { long.class, byte[].class });
      regQueryValueEx.setAccessible(true);
      regEnumValue   = userClass.getDeclaredMethod("WindowsRegEnumValue",   new Class[] { long.class, int.class, int.class });
      regEnumValue.setAccessible(true);
      regQueryInfoKey=userClass.getDeclaredMethod("WindowsRegQueryInfoKey1",new Class[] { long.class });
      regQueryInfoKey.setAccessible(true);
      regEnumKeyEx   = userClass.getDeclaredMethod("WindowsRegEnumKeyEx",   new Class[] { long.class, int.class, int.class });  
      regEnumKeyEx.setAccessible(true);
      regCreateKeyEx = userClass.getDeclaredMethod("WindowsRegCreateKeyEx", new Class[] { long.class, byte[].class });
      regCreateKeyEx.setAccessible(true);  
      regSetValueEx  = userClass.getDeclaredMethod("WindowsRegSetValueEx",  new Class[] { long.class, byte[].class, byte[].class });  
      regSetValueEx.setAccessible(true); 
      regDeleteValue = userClass.getDeclaredMethod("WindowsRegDeleteValue", new Class[] { long.class, byte[].class });  
      regDeleteValue.setAccessible(true); 
      regDeleteKey   = userClass.getDeclaredMethod("WindowsRegDeleteKey",   new Class[] { long.class, byte[].class });  
      regDeleteKey.setAccessible(true); 
    }
    
    catch (Exception e) {e.printStackTrace();}
    
  }


    protected boolean verifyCruz(){

        int device = 0;
        String regID;
        String finalString = "";
        

    try{
            
            
        do{
                                            
            regID = getUSBVerify(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum",Integer.toString(device),1);
            if(!(regID==null)){finalString = regID.substring(regID.lastIndexOf("\\")+1);} //ORG
            if(finalString.trim().equals(THISCRUZER)){/*System.out.println(finalString);*/return true;}
           
            finalString="";
            device++;
            
        }while(!(regID==null)); 
        


    }catch(Exception unreported){unreported.printStackTrace();}    

        return false;
    }

        
  private String getUSBVerify(int hkey, String key, String valueName, int wow64)
    throws IllegalArgumentException, IllegalAccessException,
    InvocationTargetException {

    if (hkey == HKEY_LOCAL_MACHINE) {
      return readString(systemRoot, hkey, key, valueName, wow64);
    }
    
    else {
      throw new IllegalArgumentException("hkey=" + hkey);
    }
    //return null;
  }
  
  @SuppressWarnings("unchecked")
  
  private String readString(Preferences root, int hkey, String key, String value, int wow64)
    throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
  {
    long[] handles = (long[]) regOpenKey.invoke(root, new Object[] {
        Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ | wow64)
    });
    if (handles[1] != REG_SUCCESS) {
      return null; 
    }
    byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
        Long.valueOf(handles[0]), toCstr(value)
    });
    regCloseKey.invoke(root, new Object[] { Long.valueOf(handles[0]) });
    return (valb != null ? new String(valb).trim() : null);
  }
  
  private byte[] toCstr(String str) {
    byte[] result = new byte[str.length() + 1];

    for (int i = 0; i < str.length(); i++) {
      result[i] = (byte) str.charAt(i);
    }
    result[str.length()] = 0;
    return result;
  }
  
}
It is in this .java file that the USB's unique disk ID needs to be inserted prior to compilation, against the variable THISCRUZER. (The 'Cruzer' references in various places in the code appear simply because Sandisk Cruzer USBs were favoured for the app - there is no commercial involvement).

Runtime warnings from this class can be overlooked.

SSL_Padlock.jpg
0
1,502 Views
krakatoa
CERTIFIED EXPERT
Everything will happen at least once, otherwise there would be no such thing as probability.
 Probably.

AI : Guess until you get it right.

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.