当前位置: 代码迷 >> java >> 使用AES 256发送加密的文件(服务器)和接收解密的文件(客户端)
  详细解决方案

使用AES 256发送加密的文件(服务器)和接收解密的文件(客户端)

热度:117   发布时间:2023-08-04 09:30:26.0

我从服务器向客户端发送文件,但我需要使用AES 256发送加密文件,并接收原始文件供不同计算机中的客户端使用。 我想使用2个字符串生成SHA256,例如:“ fruit”和“ car29”。 生成此密钥后,我想将此密钥用作密钥以使用AES256进行加密。客户端和服务器知道这两个字符串。

我的服务器代码:

public final static int SOCKET_PORT = 4444;
public final static String FILE_TO_SEND = "C:\\file.txt";

public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    FileInputStream fis = null;
    BufferedInputStream bis = null;
    OutputStream os = null;
    ServerSocket servsock = null;
    Socket sock = null;
    try {
        servsock = new ServerSocket(SOCKET_PORT);
        while (true) {
            System.out.println("Waiting...");
            try {
                sock = servsock.accept();
                System.out.println("Accepted connection : " + sock);
                // send file
                File myFile = new File(FILE_TO_SEND);
                byte[] mybytearray = new byte[(int) myFile.length()];
                fis = new FileInputStream(myFile);
                bis = new BufferedInputStream(fis);
                bis.read(mybytearray, 0, mybytearray.length);
                os = sock.getOutputStream();
                System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
                os.write(mybytearray, 0, mybytearray.length);
                os.flush();
                System.out.println("Done.");
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (os != null) {
                    os.close();
                }
                if (sock != null) {
                    sock.close();
                }
            }
        }
    } finally {
        if (servsock != null) {
            servsock.close();
        }
    }
}

我的客户代码:

public final static int SOCKET_PORT = 4444;
public final static String SERVER = "127.0.0.1";
public final static String FILE_TO_RECEIVED = "C:\\file.txt";
public final static int FILE_SIZE = 6022386;
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
      sock = new Socket(SERVER, SOCKET_PORT);
      System.out.println("Connecting...");
      // receive file
      byte [] mybytearray  = new byte [FILE_SIZE];
      InputStream is = sock.getInputStream();
      fos = new FileOutputStream(FILE_TO_RECEIVED);
      bos = new BufferedOutputStream(fos);
      bytesRead = is.read(mybytearray,0,mybytearray.length);
      current = bytesRead;
      do {
         bytesRead =
            is.read(mybytearray, current, (mybytearray.length-current));
         if(bytesRead >= 0) current += bytesRead;
      } while(bytesRead > -1);
      bos.write(mybytearray, 0 , current);
      bos.flush();
      System.out.println("File " + FILE_TO_RECEIVED
          + " downloaded (" + current + " bytes read)");
    }
    finally {
      if (fos != null) fos.close();
      if (bos != null) bos.close();
      if (sock != null) sock.close();
    }
  }

提前致谢!

我为您编写了一些功能,请查看。

用于生成哈希/摘要

public byte[] generateHASH(byte[] message) throws Exception {
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    byte[] hash = messageDigest.digest(message);
    return hash;
}

对于加密

public byte[] encrypt(byte[] msg, byte[] key, byte[] iv) throws Exception {
    //prepare key
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    //prepare cipher
    String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm 
    Cipher cipher = Cipher.getInstance(cipherALG);
    String string = cipher.getAlgorithm();

    //as iv (Initial Vector) is only required for CBC mode
    if (string.contains("CBC")) {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);      
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    } else {
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    }

    byte[] encMessage = cipher.doFinal(msg);        
    return encMessage;
}

对于解密

public byte[] decrypt(byte[] encMsgtoDec, byte[] key, byte[] iv) throws Exception {
    //prepare key
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    //prepare cipher
    String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm 
    Cipher cipher = Cipher.getInstance(cipherALG);
    String string = cipher.getAlgorithm();

    //as iv (Initial Vector) is only required for CBC mode
    if (string.contains("CBC")) {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);      
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    } else {
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    }

    byte[] decMsg = cipher.doFinal(encMsgtoDec);        
    return decMsg;
}

注意事项

  • 如果使用CBC模式,则encrypt()decrypt()使用相同的iv ,否则不需要iv ,当然两者的key相同。

  • 您的密钥生成过程很幼稚。 您最好将RSA公钥加密用于密钥交换,或者将方法用于秘密密钥传输。

我建议您使用SSL。 默认情况下会进行数据加密。 SSL握手负责生成和交换加密密钥,然后加密来自源的数据,并在接收端对其进行解密。 所有这些都发生在传输层,并且应用程序不必进行任何麻烦或做任何明确的事情,只需将其配置为使用SSL。

  相关解决方案