private static void saveKey(String fileName, Key key) { try { FileOutputStream fos = new FileOutputStream(new File(fileName)); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(key); oos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } }
/** * Sends the specified file to the client. File must exist or client and server threads will hang * indefinitely. Generates a session key to encrypt the file over transfer; session key is * encrypted using the client's public (asymmetric) key. * * @param aFile The name or path of the file to send. * @throws IOException Error reading from socket. */ private void sendFile(String aFile) throws IOException { try { // get client public key ObjectInputStream clientPubIn = new ObjectInputStream(connectedSocket.getInputStream()); PublicKey clientPublicKey = (PublicKey) clientPubIn.readObject(); // generate key string and send to client using their public key encrypted with RSA // (asymmetric) String keyString = generateKeyString(); Cipher keyCipher = Cipher.getInstance("RSA"); keyCipher.init(Cipher.ENCRYPT_MODE, clientPublicKey); SealedObject sealedKeyString = new SealedObject(keyString, keyCipher); ObjectOutputStream testOut = new ObjectOutputStream(outToClient); testOut.writeObject(sealedKeyString); testOut.flush(); // generate key spec from keyString SecretKeySpec keySpec = new SecretKeySpec(keyString.getBytes(), "DES"); // set up encryption Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); CipherOutputStream cipherOut = new CipherOutputStream(outToClient, cipher); // send file byte[] fileBuffer = new byte[BUFFER_SIZE]; InputStream fileReader = new BufferedInputStream(new FileInputStream(aFile)); int bytesRead; while ((bytesRead = fileReader.read(fileBuffer)) != EOF) { cipherOut.write(fileBuffer, 0, bytesRead); } cipherOut.flush(); cipherOut.close(); disconnect(); } catch (NoSuchPaddingException nspe) { System.out.println("No such padding."); } catch (NoSuchAlgorithmException nsae) { System.out.println("Invalid algorithm entered"); } catch (ClassNotFoundException cnfe) { System.out.println("Class not found."); } catch (InvalidKeyException ike) { System.out.println("Invalid key used for file encryption."); } catch (FileNotFoundException fnfe) { System.out.println("Invalid file entered."); return; } catch (IllegalBlockSizeException ibse) { System.out.println("Illegal block size used for encryption."); } }
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; }