Пример #1
0
  public void run() {
    try {
      ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
      ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());

      BigInteger bg = dhSpec.getG();
      BigInteger bp = dhSpec.getP();
      oos.writeObject(bg);
      oos.writeObject(bp);

      KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
      kpg.initialize(1024);
      KeyPair kpa = (KeyPair) ois.readObject();
      KeyAgreement dh = KeyAgreement.getInstance("DH");
      KeyPair kp = kpg.generateKeyPair();

      oos.writeObject(kp);

      dh.init(kp.getPrivate());
      Key pk = dh.doPhase(kpa.getPublic(), true);

      MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
      byte[] rawbits = sha256.digest(dh.generateSecret());

      Cipher c = Cipher.getInstance(CIPHER_MODE);
      SecretKey key = new SecretKeySpec(rawbits, 0, 16, "AES");
      byte ivbits[] = (byte[]) ois.readObject();
      IvParameterSpec iv = new IvParameterSpec(ivbits);
      c.init(Cipher.DECRYPT_MODE, key, iv);

      Mac m = Mac.getInstance("HmacSHA1");
      SecretKey mackey = new SecretKeySpec(rawbits, 16, 16, "HmacSHA1");
      m.init(mackey);

      byte ciphertext[], cleartext[], mac[];
      try {
        while (true) {
          ciphertext = (byte[]) ois.readObject();
          mac = (byte[]) ois.readObject();
          if (Arrays.equals(mac, m.doFinal(ciphertext))) {
            cleartext = c.update(ciphertext);
            System.out.println(ct + " : " + new String(cleartext, "UTF-8"));
          } else {
            // System.exit(1);
            System.out.println(ct + "error");
          }
        }
      } catch (EOFException e) {
        cleartext = c.doFinal();
        System.out.println(ct + " : " + new String(cleartext, "UTF-8"));
        System.out.println("[" + ct + "]");
      } finally {
        if (ois != null) ois.close();
        if (oos != null) oos.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
Пример #2
0
  @Test
  public void testStandardVectorMac() throws Exception {
    Mac mac = macFactory.create();
    mac.init(seed.getKey());
    mac.update(seed.getData());

    byte[] actual = new byte[mac.getBlockSize()];
    mac.doFinal(actual);
    assertArrayEquals(
        "Mismatched results for actual="
            + BufferUtils.toHex(BufferUtils.EMPTY_HEX_SEPARATOR, actual),
        expected,
        actual);
  }
Пример #3
0
  /**
   * Performs a handshake for key exchange between two people. This method must be called by both
   * people to ensure that the agreement has been reached on both ends.
   *
   * @param otherKey the serialized string version of the public key for the other person. Must not
   *     be null.
   */
  public void handShake(String otherKey) {
    if (DEBUG) {
      System.out.println("Performing handshake...");
    }
    try {
      byte[] otherPubBytes = new Base64().decode(otherKey);
      ByteArrayInputStream bais = new ByteArrayInputStream(otherPubBytes);
      ObjectInputStream ois = new ObjectInputStream(bais);

      KeyAgreement keyAgree = KeyAgreement.getInstance("DiffieHellman");
      keyAgree.init(privKey);
      Key otherPub = (Key) ois.readObject();
      keyAgree.doPhase(otherPub, true);
      msgKey = keyAgree.generateSecret("DESede");
      cipher = Cipher.getInstance("DESede");
      mac = Mac.getInstance("HmacSHA512");
      if (DEBUG) {
        System.out.println("Handshake completed");
      }
    } catch (Exception e) {
      System.out.println("Could not complete handshake...");
      System.out.println("Agreement not confirmed");
      if (DEBUG) {
        e.printStackTrace();
      }
    }
  }
Пример #4
0
 /**
  * Encrypts the given msg and returns the ciphertext for the encryted message
  *
  * @param msg != null
  * @return the encrypted message or null if encryption fails
  */
 public String encryptMsg(String msg) {
   try {
     cipher.init(Cipher.ENCRYPT_MODE, msgKey);
     mac.init(msgKey);
     byte[] c1 = cipher.doFinal(msg.getBytes());
     String c1Str = new Base64().encodeToString(c1);
     byte[] m = mac.doFinal(c1);
     String mStr = new Base64().encodeToString(m);
     return (c1Str + "::::" + mStr).replace("\r\n", "_").replace("\r", "-").replace("\n", "~");
   } catch (Exception e) {
     System.out.println("Could not encrypt the message");
     if (DEBUG) {
       e.printStackTrace();
     }
     return null;
   }
 }
Пример #5
0
 /**
  * Decrypts the given String and returns the decrypted message if the message is verified to come
  * from the correct sender, or null otherwise
  *
  * @param encryptedMsg != null
  * @param nonce must be the nonce sent to the sender to use in the encryption of the message
  * @return the decrypted message or null if the message is not verified
  */
 public String decryptMsgNonce(String encryptedMsg) {
   try {
     cipher.init(Cipher.DECRYPT_MODE, msgKey);
     mac.init(msgKey);
     encryptedMsg = encryptedMsg.replace("~", "\n").replace("-", "\r").replace("_", "\r\n");
     String[] encMsgParts = encryptedMsg.split("::::");
     String encMsg = encMsgParts[0];
     String checkM = encMsgParts[1];
     byte[] encBytes = new Base64().decode(encMsg);
     byte[] message = cipher.doFinal(encBytes);
     byte[] m = mac.doFinal(encBytes);
     String mStr = new Base64().encodeToString(m);
     if (mStr.equals(checkM)) {
       String mess = new String(message);
       String[] parts = mess.split(":::");
       String msg = parts[0];
       int n = Integer.parseInt(parts[1]);
       if (nonceSet.contains(n)) {
         nonceSet.remove(n);
         return msg;
       } else {
         if (DEBUG) {
           System.out.println("Nonces don't match...");
           System.out.println("Expected: " + nonceSet.toString() + ", Actual: " + n);
         }
         return null;
       }
     } else {
       if (DEBUG) {
         System.out.println("MACs don't match...");
       }
       return null;
     }
   } catch (Exception e) {
     System.out.println("Could not decrypt");
     if (DEBUG) {
       e.printStackTrace();
     }
   }
   return null;
 }
 public static void main(String[] args) throws Exception {
   //
   // check args and get plaintext
   if (args.length != 1) {
     System.err.println("Usage: java MessageAuthenticationCodeExample text");
     System.exit(1);
   }
   byte[] plainText = args[0].getBytes("UTF8");
   //
   // get a key for the HmacMD5 algorithm
   System.out.println("\nStart generating key");
   KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
   SecretKey MD5key = keyGen.generateKey();
   System.out.println("Finish generating key");
   //
   // get a MAC object and update it with the plaintext
   Mac mac = Mac.getInstance("HmacMD5");
   mac.init(MD5key);
   mac.update(plainText);
   //
   // print out the provider used and the MAC
   System.out.println("\n" + mac.getProvider().getInfo());
   System.out.println("\nMAC: ");
   System.out.println(new String(mac.doFinal(), "UTF8"));
 }
Пример #7
0
 /**
  * Decrypts the given String and returns the decrypted message if the message is verified to come
  * from the correct sender, or null otherwise
  *
  * @param encryptedMsg != null
  * @return the decrypted message or null if the message is not verified
  */
 public String decryptMsg(String encryptedMsg) {
   try {
     cipher.init(Cipher.DECRYPT_MODE, msgKey);
     mac.init(msgKey);
     encryptedMsg = encryptedMsg.replace("~", "\n").replace("-", "\r").replace("_", "\r\n");
     String[] encMsgParts = encryptedMsg.split("::::");
     String encMsg = encMsgParts[0];
     String checkM = encMsgParts[1];
     byte[] encBytes = new Base64().decode(encMsg);
     byte[] message = cipher.doFinal(encBytes);
     byte[] m = mac.doFinal(encBytes);
     String mStr = new Base64().encodeToString(m);
     if (mStr.equals(checkM)) return new String(message);
     if (DEBUG) {
       System.out.println("MACs don't match...");
     }
   } catch (Exception e) {
     System.out.println("Could not decrypt");
     if (DEBUG) {
       e.printStackTrace();
     }
   }
   return null;
 }
Пример #8
0
  /**
   * Creates a message authentication code (MAC) for the given input.
   *
   * @param msg input
   * @param k secret key
   * @param a encryption algorithm
   * @param enc encoding
   * @return MAC
   * @throws QueryException query exception
   */
  Item hmac(final byte[] msg, final byte[] k, final byte[] a, final byte[] enc)
      throws QueryException {

    // create hash value from input message
    final Key key = new SecretKeySpec(k, string(a));

    final byte[] aa = a.length == 0 ? DEFA : a;
    if (!ALGHMAC.contains(lc(aa))) throw CX_INVHASH.get(info, aa);

    final boolean b64 = eq(lc(enc), BASE64) || enc.length == 0;
    if (!b64 && !eq(lc(enc), HEX)) throw CX_ENC.get(info, enc);

    try {
      final Mac mac = Mac.getInstance(string(ALGHMAC.get(lc(aa))));
      mac.init(key);
      final byte[] hash = mac.doFinal(msg);
      // convert to specified encoding, base64 as a standard, else use hex
      return Str.get(b64 ? org.basex.util.Base64.encode(hash) : hex(hash, true));
    } catch (final NoSuchAlgorithmException e) {
      throw CX_INVHASH.get(info, e);
    } catch (final InvalidKeyException e) {
      throw CX_KEYINV.get(info, e);
    }
  }
Пример #9
0
 private byte[] sign(byte[] dataToSign) throws NoSuchAlgorithmException, InvalidKeyException {
   Mac hmacSHA1 = Mac.getInstance("HmacSHA1");
   hmacSHA1.init(this.hmacKey);
   return hmacSHA1.doFinal(dataToSign);
 }
Пример #10
0
 private boolean verify(byte[] dataToVerify, byte[] signature)
     throws NoSuchAlgorithmException, InvalidKeyException {
   Mac hmacSHA1 = Mac.getInstance("HmacSHA1");
   hmacSHA1.init(this.hmacKey);
   return Arrays.equals(hmacSHA1.doFinal(dataToVerify), signature);
 }
  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;
  }
  @SuppressWarnings("unchecked")
  public List<String> listFiles(UserToken token) {
    try {
      Envelope env = null, e = null;
      // Tell the server to return the member list
      env = new Envelope("LFILES");
      env.addObject(token); // Add requester's token
      String concat =
          token.toString() + "LFILES" + 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);

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

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

      env = Envelope.getEnvelopefromBytes(responseBytes);

      if (env.getMessage().equals("FAIL")) {
        System.out.println("Error occured in ListFiles, disconnecting");
        disconnect();
        return null;
      } else if ((Integer) env.getObjContents().get(2) == nonce) {
        List<String> files = (List<String>) env.getObjContents().get(0);
        String hash = (String) env.getObjContents().get(1);
        concat = files.toString() + 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);
        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 FAIL");
          disconnect();
        } else {
          // If server indicates success, return the member list
          if (env.getMessage().equals("OK")) {
            return files; // This cast creates compiler warnings. Sorry.
          }
        }
      } else {
        System.out.println("Nonce FAIL LFILES");
        disconnect();
        return null;
      }

      return null;
    } catch (Exception e) {
      System.err.println("Error: " + e.getMessage());
      e.printStackTrace(System.err);
      return null;
    }
  }
  public boolean delete(String filename, UserToken token) {
    try {
      String remotePath;
      if (filename.charAt(0) == '/') {
        remotePath = filename.substring(1);
      } else {
        remotePath = filename;
      }
      Envelope env = new Envelope("DELETEF"); // Success
      env.addObject(remotePath);
      env.addObject(token);
      String concat =
          remotePath
              + token.toString()
              + "DELETEF"
              + 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);

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

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

      env = Envelope.getEnvelopefromBytes(responseBytes);
      System.out.println(env.getMessage());
      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");
        FileInputStream 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++;

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

        if (env.getMessage().compareTo("OK") == 0) {
          System.out.printf("File %s deleted successfully\n", filename);
        } else {
          System.out.printf("Error deleting file %s (%s)\n", filename, env.getMessage());
          return false;
        }
      }
    } catch (IllegalBlockSizeException ex) {
      ex.printStackTrace(System.err);
    } catch (BadPaddingException ex) {
      ex.printStackTrace(System.err);
    } catch (InvalidKeyException ex) {
      ex.printStackTrace(System.err);
    } catch (NoSuchAlgorithmException ex) {
      ex.printStackTrace(System.err);
    } catch (NoSuchPaddingException ex) {
      ex.printStackTrace(System.err);
    } catch (IOException e1) {
      e1.printStackTrace(System.err);
    } catch (ClassNotFoundException e1) {
      e1.printStackTrace(System.err);
    }

    return true;
  }
  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;
  }
  public boolean sendToken(UserToken token) {
    try {
      Envelope env = new Envelope("SENDT"); // Success
      env.addObject(token);

      String concat =
          token.toString() + "SENDT" + 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);

      Cipher cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.ENCRYPT_MODE, AESkey);
      byte[] cipherBytes = cipher.doFinal(envBytes);
      output.writeObject(cipherBytes);

      // receive from thread
      byte[] responseCipherBytes = (byte[]) input.readObject();

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

      env = Envelope.getEnvelopefromBytes(responseBytes);
      if ((Integer) env.getObjContents().get(1) == nonce) {
        String hash = (String) env.getObjContents().get(0);
        concat = "OK" + 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);
        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 FAIL");
          return false;
        }

        if (env.getMessage().compareTo("OK") == 0) {
          System.out.printf("OK RECEIVED");
          return true;
        } else {
          System.out.printf("FAILURE");
          return false;
        }
      }
    } catch (Exception e) {
      System.out.println(e);
    }
    return false;
  }