public boolean upload(
      String sourceFile, String destFile, String group, UserToken token, Key key, int keyNum) {

    if (destFile.charAt(0) != '/') {
      destFile = "/" + destFile;
    }

    try {
      FileInputStream fis = new FileInputStream(sourceFile);
      File encryptFile = new File(sourceFile + "_encrypt");
      encryptFile.createNewFile();
      FileOutputStream fos = new FileOutputStream(encryptFile);

      // Initial Vector must be 16 bytes
      byte[] initialVector = {
        0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf
      };
      IvParameterSpec ivs = new IvParameterSpec(initialVector);
      byte[] buf = new byte[1024];
      Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, key, ivs);
      byte[] cipherBytes;

      // create a new local encrypted file
      do {
        buf = new byte[1024];
        int n = fis.read(buf);

        if (n > 0) {
          System.out.printf(".");
        } else if (n < 0) {
          System.out.println("Read error");
        }

        cipherBytes = cipher.doFinal(buf);
        fos.write(cipherBytes);
      } while (fis.available() > 0);
      System.out.println();

      // send encrypted file to server
      Envelope message = null, env = null;
      // Tell the server to return the member list
      message = new Envelope("UPLOADF");
      message.addObject(destFile);
      message.addObject(group);
      message.addObject(token);
      message.addObject(keyNum);
      message.addObject(initialVector);

      String concat =
          destFile
              + group
              + token.toString()
              + keyNum
              + "UPLOADF"
              + nonce; // concatinates all of the objects in envelope
      byte[] hasharray = concat.getBytes(); // turn the concat into a byte array
      Mac mac = Mac.getInstance("HmacSHA1");
      mac.init(HMACkey);
      mac.update(hasharray);
      String stringhash =
          new String(mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!
      message.addObject(stringhash);
      message.addObject(nonce);
      nonce++;

      byte[] messageBytes = Envelope.toByteArray(message);

      // Encrypt envelope w/ AES
      cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.ENCRYPT_MODE, AESkey);
      cipherBytes = cipher.doFinal(messageBytes);

      output.writeObject(cipherBytes);

      byte[] responseCipherBytes =
          (byte[])
              input.readObject(); // if response isnt ready it should check whether it was forged

      // Decrypt response
      cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.DECRYPT_MODE, AESkey);
      byte[] responseBytes = cipher.doFinal(responseCipherBytes);

      env = Envelope.getEnvelopefromBytes(responseBytes);
      if (env.getMessage().equals("READY")) {
        System.out.printf("Meta data upload successful\n");
      } else if ((Integer) env.getObjContents().get(1) == nonce) {
        String hash = (String) env.getObjContents().get(0);
        concat = env.getMessage() + nonce; // reconstructs the hash
        hasharray = concat.getBytes();
        mac = Mac.getInstance("HmacSHA1");
        File HASHfile = new File("FHASHKey.bin");
        fis = new FileInputStream(HASHfile);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Key HMACkey = (Key) ois.readObject();
        mac.init(HMACkey);
        mac.update(hasharray);
        String newhash = new String(mac.doFinal(), "UTF8");
        nonce++;

        // check hashes for equality
        if (hash.equals(newhash) != true) {
          System.out.println("HASH EQUALITY FAIL2, disconnecting for your own safety");
          disconnect();
          return false;
        }
      } else {
        System.out.println("Nonce FAIL UPLOADF");
        disconnect();
        return false;
      }
      // If server indicates success, return the member list

      FileInputStream encryptFIS = new FileInputStream(encryptFile);
      do {
        if ((Integer) env.getObjContents().get(1) == nonce) {
          buf = new byte[1024];
          if (!env.getMessage().equals("READY")) {
            System.out.printf("Server error: %s\n", env.getMessage());
            return false;
          }

          String hash = (String) env.getObjContents().get(0);
          concat = env.getMessage() + nonce; // reconstructs the hash
          hasharray = concat.getBytes();
          mac = Mac.getInstance("HmacSHA1");
          File HASHfile = new File("FHASHKey.bin");
          fis = new FileInputStream(HASHfile);
          ObjectInputStream ois = new ObjectInputStream(fis);
          Key HMACkey = (Key) ois.readObject();
          mac.init(HMACkey);
          mac.update(hasharray);
          String newhash = new String(mac.doFinal(), "UTF8");
          nonce++;

          ois.close();

          // check hashes for equality
          if (hash.equals(newhash) != true) {
            System.out.println("HASH EQUALITY FAIL3, disconnecting for your own safety");
            disconnect();
            return false;
          }

          message = new Envelope("CHUNK");
          int n = encryptFIS.read(buf); // can throw an IOException
          if (n > 0) {
            System.out.printf(".");
          } else if (n < 0) {
            System.out.println("Read error");
            return false;
          }

          message.addObject(buf);
          message.addObject(new Integer(n));
          concat = n + "CHUNK" + nonce; // concatinates all of the objects in envelope
          hasharray = concat.getBytes(); // turn the concat into a byte array
          mac = Mac.getInstance("HmacSHA1");
          mac.init(HMACkey);
          mac.update(hasharray);
          stringhash =
              new String(
                  mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!
          message.addObject(stringhash);
          message.addObject(nonce);
          nonce++;

          messageBytes = Envelope.toByteArray(message);

          // Encrypt envelope w/ AES
          cipher = Cipher.getInstance("AES");
          cipher.init(Cipher.ENCRYPT_MODE, AESkey);
          cipherBytes = cipher.doFinal(messageBytes);
          System.out.println("Concatsent" + concat);

          output.writeObject(
              cipherBytes); ///////////////////////////////////////////
                            // HERE/////////////////////////////////

          responseCipherBytes = (byte[]) input.readObject();

          // Decrypt response
          cipher.init(Cipher.DECRYPT_MODE, AESkey);
          responseBytes = cipher.doFinal(responseCipherBytes);

          env = Envelope.getEnvelopefromBytes(responseBytes);

        } else {
          System.out.println("Nonce FAIL UPLOADF");
          disconnect();
          return false;
        }
      } while (encryptFIS.available() > 0);
      encryptFIS.close();

      // If server indicates success, return the member list
      if (env.getMessage().compareTo("READY") == 0
          && (Integer) env.getObjContents().get(1) == nonce) {
        nonce++;
        message = new Envelope("EOF");
        concat = "EOF" + nonce; // concatinates all of the objects in envelope
        hasharray = concat.getBytes(); // turn the concat into a byte array
        mac = Mac.getInstance("HmacSHA1");
        mac.init(HMACkey);
        mac.update(hasharray);
        stringhash =
            new String(mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!

        message.addObject(stringhash);
        message.addObject(nonce);
        System.out.println(nonce);
        nonce++;

        messageBytes = Envelope.toByteArray(message);

        // Encrypt envelope w/ AES
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, AESkey);
        cipherBytes = cipher.doFinal(messageBytes);

        output.writeObject(cipherBytes);

        responseCipherBytes = (byte[]) input.readObject();

        // Decrypt response
        cipher.init(Cipher.DECRYPT_MODE, AESkey);
        responseBytes = cipher.doFinal(responseCipherBytes);

        env = Envelope.getEnvelopefromBytes(responseBytes);

        if (env.getMessage().compareTo("OK") == 0
            && (Integer) env.getObjContents().get(1) == nonce) {
          System.out.printf("\nFile data upload successful\n");
        } else if ((Integer) env.getObjContents().get(1) != nonce) {
          System.out.println("Nonce FAIL UPLOADF");
          disconnect();
          return false;
        } else {
          System.out.printf("\nUpload failed: %s\n", env.getMessage());
          return false;
        }
      } else if ((Integer) env.getObjContents().get(1) != nonce) {
        System.out.println("Nonce FAIL UPLOADF");
        disconnect();
        return false;
      } else {
        System.out.printf("Upload failed: %s\n", env.getMessage());
        return false;
      }
    } catch (Exception e1) {
      System.err.println("Error: " + e1.getMessage());
      e1.printStackTrace(System.err);
      return false;
    }
    return true;
  }
  public static void main(String[] args) throws Exception {

    String digestType = args[0];
    String digestFile = args[1];

    Vector<String> digestListFiles = new Vector<String>();
    Vector<byte[]> calcDigests = new Vector<byte[]>();

    BufferedReader reader = null;
    byte[] fileContent;
    int i;

    for (i = 2; i < args.length; i++) {
      digestListFiles.add(args[i]);
    }

    // le os arquivos e calcula o digest de seus conteudos.
    for (i = 0; i < digestListFiles.size(); i++) {

      File file = new File(digestListFiles.get(i));

      fileContent = readFile(file);
      MessageDigest messageDigest;

      try {
        messageDigest = MessageDigest.getInstance(digestType);
      } catch (Exception e) {
        System.out.println("Inexistant cryptography algorithm given!");
        return;
      }

      messageDigest.update(fileContent);
      calcDigests.add(messageDigest.digest());
    }

    File digestListFile = new File(digestFile);

    // verifica se o arquivo existe.
    // caso nao exista, cria um novo.
    if (!digestListFile.exists()) digestListFile.createNewFile();

    // lista dos arquivos ja lidos
    Vector<String> fileNames = new Vector<String>();
    // lista do tipos dos digest dos arquivos
    Vector<String> fileTypes = new Vector<String>();
    // lista dos digest dos conteudos dos arquivos
    Vector<String> fileDigests = new Vector<String>();

    try {
      reader = new BufferedReader(new FileReader(digestListFile));
      String line;
      String[] splitLine;

      while ((line = reader.readLine()) != null) {
        splitLine = line.split(" ");
        fileNames.add(splitLine[0]); // le o nome do arquivo
        fileTypes.add(splitLine[1]); // le o tipo do digest
        fileDigests.add(splitLine[2]); // le o digest em hex
      }

    } catch (IOException e) {
      System.out.println("Problems reading digest file! " + e.getStackTrace().toString());
    }

    STATUS status;
    int pos;
    for (i = 0; i < digestListFiles.size(); i++) {

      // procura
      pos = find(fileNames, digestListFiles.get(i), fileTypes, digestType);

      if (pos != -1) { // achou

        // verifica se o conteudo eh igual
        if (fileDigests.get(pos).contentEquals(calcHex(calcDigests.get(i)))) {
          status = STATUS.OK; // conteudo igual
        } else {
          status = STATUS.NOTOK; // conteudo diferente
        }

      } else {
        // nao achou!
        // insere no arquivo
        writeToEOF(
            digestListFiles.get(i) + " " + digestType + " " + calcHex(calcDigests.get(i)) + "\n",
            digestListFile);

        fileNames.add(digestListFiles.get(i));
        fileTypes.add(digestType);
        fileDigests.add(calcHex(calcDigests.get(i)));

        status = STATUS.NOTFOUND;
      }

      System.out.println(
          digestListFiles.get(i)
              + " "
              + digestType
              + " "
              + calcHex(calcDigests.get(i))
              + " ("
              + status.toString()
              + ")");
    }
  }
  public boolean download(
      String sourceFile, String destFile, UserToken token, HashMap<String, ArrayList<Key>> keys) {
    try {
      destFile = "." + destFile;

      if (sourceFile.charAt(0) == '/') {
        sourceFile = sourceFile.substring(1);
      }

      File file = new File(destFile);

      if (!file.exists()) {
        file.createNewFile();

        FileOutputStream fos = new FileOutputStream(file);
        Envelope env = new Envelope("DOWNLOADF"); // Success
        env.addObject(sourceFile);
        env.addObject(token);
        String concat =
            sourceFile
                + token.toString()
                + "DOWNLOADF"
                + nonce; // concatinates all of the objects in envelope
        byte[] hasharray = concat.getBytes(); // turn the concat into a byte array
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(HMACkey);
        mac.update(hasharray);
        String stringhash =
            new String(mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!
        env.addObject(stringhash);
        env.addObject(nonce);
        nonce++;

        byte[] envBytes = Envelope.toByteArray(env);

        // Encrypt envelope w/ AES
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, AESkey);
        byte[] cipherBytes = cipher.doFinal(envBytes);

        output.writeObject(cipherBytes); // here in download

        byte[] responseCipherBytes = (byte[]) input.readObject();

        // Decrypt response
        cipher.init(Cipher.DECRYPT_MODE, AESkey);
        byte[] responseBytes = cipher.doFinal(responseCipherBytes);

        env = Envelope.getEnvelopefromBytes(responseBytes);
        ShareFile sf = (ShareFile) env.getObjContents().get(2);
        int keyNum = sf.getKeyNum();
        ArrayList<Key> groupKeys = keys.get(sf.getGroup());
        Key key = groupKeys.get(keyNum);
        byte[] initialVector = sf.getIV();
        IvParameterSpec ivs = new IvParameterSpec(initialVector);
        byte[] decryptBuf = new byte[1024];

        while (env.getMessage().compareTo("CHUNK") == 0
            && (Integer) env.getObjContents().get(4) == nonce) {
          String hash = (String) env.getObjContents().get(3);
          concat =
              (Integer) env.getObjContents().get(1)
                  + env.getMessage()
                  + nonce; // reconstructs the hash
          System.out.println("Concat:" + concat);
          hasharray = concat.getBytes();
          mac = Mac.getInstance("HmacSHA1");
          File HASHfile = new File("FHASHKey.bin");
          FileInputStream fis = new FileInputStream(HASHfile);
          ObjectInputStream ois = new ObjectInputStream(fis);
          HMACkey = (Key) ois.readObject();
          mac.init(HMACkey);
          mac.update(hasharray);
          String newhash = new String(mac.doFinal(), "UTF8");
          nonce++;

          // check hashes for equality
          if (hash.equals(newhash) != true) {
            System.out.println("HASH EQUALITY FAIL1");
            disconnect();
            return false;
          } else {
            decryptBuf = new byte[1024];
            System.out.println("env.getMessage: " + env.getMessage());
            cipher = Cipher.getInstance("AES/CBC/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, key, ivs);
            decryptBuf = cipher.doFinal((byte[]) env.getObjContents().get(0));

            // Write encrypted file to disk
            fos.write(decryptBuf);
            System.out.printf(".");
            env = new Envelope("DOWNLOADF"); // Success
            concat = env.getMessage() + nonce; // concatinates all of the objects in envelope
            hasharray = concat.getBytes(); // turn the concat into a byte array
            mac = Mac.getInstance("HmacSHA1");
            mac.init(HMACkey);
            mac.update(hasharray);
            stringhash =
                new String(
                    mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!
            env.addObject(stringhash);
            env.addObject(nonce);
            nonce++;

            envBytes = Envelope.toByteArray(env);

            // Encrypt envelope w/ AES
            cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, AESkey);
            cipherBytes = cipher.doFinal(envBytes);

            output.writeObject(cipherBytes);

            responseCipherBytes = (byte[]) input.readObject();

            // Decrypt response
            cipher.init(Cipher.DECRYPT_MODE, AESkey);
            responseBytes = cipher.doFinal(responseCipherBytes);

            env = Envelope.getEnvelopefromBytes(responseBytes);
          }
        }
        fos.close();
        if (env.getMessage().compareTo("EOF") == 0
            && (Integer) env.getObjContents().get(1) == nonce) {
          String hash = (String) env.getObjContents().get(0);
          concat = env.getMessage() + nonce; // reconstructs the hash
          hasharray = concat.getBytes();
          mac = Mac.getInstance("HmacSHA1");
          File HASHfile = new File("FHASHKey.bin");
          FileInputStream fis = new FileInputStream(HASHfile);
          ObjectInputStream ois = new ObjectInputStream(fis);
          HMACkey = (Key) ois.readObject();
          mac.init(HMACkey);
          mac.update(hasharray);
          String newhash = new String(mac.doFinal(), "UTF8");

          if (hash.equals(newhash) != true) // check hashes for equality
          {
            System.out.println("HASH EQUALITY FAIL2");
            disconnect();
          }

          fos.close();
          System.out.printf("\nTransfer successful file %s\n", sourceFile);
          nonce++;
          env = new Envelope("OK"); // Success
          concat = env.getMessage() + nonce; // concatinates all of the objects in envelope
          hasharray = concat.getBytes(); // turn the concat into a byte array
          mac = Mac.getInstance("HmacSHA1");
          mac.init(HMACkey);
          mac.update(hasharray);
          stringhash =
              new String(
                  mac.doFinal(), "UTF8"); // turn the hash into a string for easy comparision!
          env.addObject(stringhash);
          env.addObject(nonce);
          nonce++;

          envBytes = Envelope.toByteArray(env);

          // Encrypt envelope w/ AES
          cipher = Cipher.getInstance("AES");
          cipher.init(Cipher.ENCRYPT_MODE, AESkey);
          cipherBytes = cipher.doFinal(envBytes);

          output.writeObject(cipherBytes);

        } else if ((Integer) env.getObjContents().get(1) != nonce) {
          System.out.println("Nonce FAIL DOWNLOADF");
          disconnect();
          return false;
        } else {
          System.out.printf("Error reading file %s (%s)\n", sourceFile, env.getMessage());
          file.delete();
          return false;
        }
      } else {
        System.out.printf("Error couldn't create file %s\n", destFile);
        return false;
      }

    } catch (InvalidAlgorithmParameterException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalBlockSizeException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
      System.out.println(1);
    } catch (BadPaddingException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
      System.out.println(2);
    } catch (InvalidKeyException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
      System.out.println(3);
    } catch (NoSuchAlgorithmException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
      System.out.println(4);
    } catch (NoSuchPaddingException ex) {
      Logger.getLogger(FileClient.class.getName()).log(Level.SEVERE, null, ex);
      System.out.println(5);
    } catch (IOException e1) {

      System.out.printf("Error couldn't create file %s\n", destFile);
      return false;

    } catch (ClassNotFoundException e1) {
      e1.printStackTrace(System.err);
    }
    return true;
  }
Exemplo n.º 4
0
  public boolean connect(String username, String weakSecret, final String server, final int port) {
    System.out.println("attempting to connect");

    try {
      sock = new Socket();
      sock.connect(new InetSocketAddress(server, port));
      output = new ObjectOutputStream(sock.getOutputStream());
      input = new ObjectInputStream(sock.getInputStream());
      output.writeObject(username);

      // do DH exchange and agree on starting message index
      try {
        if (weakSecret != null) // group server connect
        {
          HashMap<String, SecretKey> secretKeys =
              DHKeyExchange.generateSecretKeyWithWeakSecret(username, weakSecret, input, output);
          if (secretKeys == null) throw new Exception("Unable to verify server");
          encryptionKey = secretKeys.get("encryptionKey");
          signingKey = secretKeys.get("signingKey");
        } else // file server connect
        {
          PublicKey fileServerPublicKey = (PublicKey) input.readObject(); // read in public key

          File savedKeys = new File("savedkeys.bin");
          ArrayList<PublicKey> knownKeys = new ArrayList<PublicKey>();
          if (savedKeys.exists()) {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(savedKeys));
            knownKeys = (ArrayList<PublicKey>) in.readObject();
          }
          if (!knownKeys.contains(fileServerPublicKey)) // prompt the user to verify the key
          {
            MessageDigest sha = MessageDigest.getInstance("SHA-1");
            byte[] digest = sha.digest(fileServerPublicKey.getEncoded());
            System.out.println("RSA key fingerprint is " + getFingerprint(digest));
            System.out.println(
                "Please verify this is correct by contacting the file server owner.");
            System.out.println(
                "Do you want to add this key to your list of saved servers? (yes/no)");
            Scanner scanner = new Scanner(System.in);
            String answer = scanner.nextLine();
            if (answer.toLowerCase().equals("yes")) {
              knownKeys.add(fileServerPublicKey);
              savedKeys.delete();
              savedKeys.createNewFile();
              ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(savedKeys));
              out.writeObject(knownKeys);
              out.flush();
              out.close();
              output.writeObject("yes");
            } else {
              output.writeObject("no");
              System.out.println("Exiting");
              System.exit(0);
            }
          } else // accpet the key without prompt
          output.writeObject("yes");

          generateRSAKeypair();
          output.writeObject(publicKey);
          HashMap<String, SecretKey> secretKeys =
              DHKeyExchange.generateSecretKeySignedExchange(
                  input, output, privateKey, fileServerPublicKey);
          if (secretKeys == null) throw new Exception("Unable to verify server");
          encryptionKey = secretKeys.get("encryptionKey");
          signingKey = secretKeys.get("signingKey");
        }

        encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        byte[] key = sha.digest(encryptionKey.getEncoded());
        key = Arrays.copyOf(key, 16); // use only first 128 bit

        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes));
        decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes));

        BigInteger R = new BigInteger(128, new SecureRandom());
        output.writeObject(encryptCipher.doFinal(R.toByteArray()));
        BigInteger start = new BigInteger(decryptCipher.doFinal((byte[]) input.readObject()));
        if (start.compareTo(R) < 0) throw new Exception("Invalid message index from server");
        else messageIndex = start.add(BigInteger.ONE);
      } catch (Exception ex) {
        System.out.println("Failed to connect: " + ex.getMessage());
        // if anything fails, we are not connected
        sock = null;
        return false;
      }
    } catch (IOException ex) {
      return false;
    }

    return true;
  }