使用RSA解密AES密钥和消息解密时的问题。

huangapple 未分类评论50阅读模式
英文:

Problem with decryption of AES key with RSA and message decryption

问题

我正在开发一个安全的聊天应用程序。我有用于加密/解密消息的AES密钥,用户拥有自己的用于加密/解密AES密钥的公钥/私钥RSA密钥对。我的代码出现了以下错误:

> javax.crypto.BadPaddingException: 解密错误
	at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:383)
	at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:294)
	at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
	at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
	at javax.crypto.Cipher.doFinal(Cipher.java:2164)
	at org.fastchat.User.decryptAESKey(User.java:183)
	at org.fastchat.User.readMessage(User.java:210)
	at org.fastchat.WatchInbox.startWatch(WatchInbox.java:59)
	at org.fastchat.WatchInbox.run(WatchInbox.java:32)

错误出现在使用RSA私钥解密AES密钥的函数中。我发现问题可能与密钥错误(密钥存储在序列化中,每个用户在配置文件对象中生成一次密钥)或编码/解码问题有关。我决定将加密的AES密钥存储在某个文件中,并在解密AES密钥时读取该文件。是否有更好的方法来存储加密的AES密钥?我的编码/解码方式是否正确?欢迎任何帮助,我现在没有任何想法。我的代码在此处,整个过程的每个部分都在不同的函数中。

public SecretKey generateAESkey() throws NoSuchAlgorithmException {
    // 生成AES密钥的代码...
}

public byte[] encryptAESKey(SecretKey key, PublicKey pubKey) throws Exception {
    // 加密AES密钥的代码...
}

public byte[] encryptMessage(String message, SecretKey aeSecretKey) throws Exception {
    // 加密消息的代码...
}

public void checkerUpdate(User receiver) throws IOException {
    // 更新检查器的代码...
}

public void sendMessage(String message, User receiver) throws Exception {
    // 发送消息的代码...
}

// 解密函数

public byte[] decryptAESKey(byte[] aesEnc) throws Exception {
    // 解密AES密钥的代码...
}

public String decryptMessage(byte[] msg, SecretKeySpec aeskey) throws Exception {
    // 解密消息的代码...
}

public String readMessage(User sender) throws Exception {
    // 读取消息的代码...
}
英文:

I am working on secure chat application. I have AES key for ecrypt/decrypt message and users have own public/private RS keys for encrypt/decrypt AES key. My code give me error like this:

> javax.crypto.BadPaddingException: Decryption error
	at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:383)
	at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:294)
	at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
	at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
	at javax.crypto.Cipher.doFinal(Cipher.java:2164)
	at org.fastchat.User.decryptAESKey(User.java:183)
	at org.fastchat.User.readMessage(User.java:210)
	at org.fastchat.WatchInbox.startWatch(WatchInbox.java:59)
	at org.fastchat.WatchInbox.run(WatchInbox.java:32)

Error is in function for decrypting AES key with RSA private key. I found that problem could be with wrong key (keys stored in serialization, every user have once generated keys in profile object) or encode/decode problems. I decide to store encrypted AES key in some file and read that file for decrypt AES key. Is there some better way for store encypted AES key? Am I doing encode/decode in right way? Any help is welcome, I dont have any ideas now. My code is here and every part of proccess is in different function.

public SecretKey generateAESkey() throws NoSuchAlgorithmException {
	System.out.println("Generating AES key...\n");
	SecureRandom random = new SecureRandom();
	KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
	keyGenerator.init(128, random);
	SecretKey aeSecretKey = keyGenerator.generateKey();
	System.out.println("AES1 KEY " + new String(Base64.getEncoder().encodeToString(aeSecretKey.getEncoded())));
	System.out.println("===========================\n");
	return aeSecretKey;
	// return keyGenerator.generateKey();
}

public byte[] encryptAESKey(SecretKey key, PublicKey pubKey) throws Exception {
	System.out.println("Encrypt AES key...\n");

	String aesKey = new String(Base64.getEncoder().encodeToString(key.getEncoded()));
	Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
	cipher.init(Cipher.ENCRYPT_MODE, pubKey);
	byte[] aesEnc = cipher.doFinal(aesKey.getBytes());
	System.out.println("AES ENCRYPTED: " + aesEnc);
	System.out.println("==========================\n");
	return aesEnc;
	// return cipher.doFinal(aesToEnc);
}

public byte[] encryptMessage(String message, SecretKey aeSecretKey) throws Exception {
	System.out.println("Encrypt message...\n");
	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	cipher.init(Cipher.ENCRYPT_MODE, aeSecretKey);
	byte[] msgBytes = message.getBytes(); // This will be encrypted
	byte[] msgEnc = cipher.doFinal(msgBytes);
	System.out.println("=============================\n");
	return msgEnc;
	// return cipher.doFinal(msgBytes); //This will be in .txt file
}

public void checkerUpdate(User receiver) throws IOException {
	BufferedWriter check = new BufferedWriter(new FileWriter(receiver.getCheck() + "/" + getUsername() + ".txt"));
	Random random = new Random();
	Integer num = random.nextInt(100);
	check.write(num);
	check.close();
}

public void sendMessage(String message, User receiver) throws Exception {

	// First generate AES key
	SecretKey aesSecretKey = generateAESkey(); // keysize = 128

	// Encrypt message with AES key, will be in file
	byte[] encMsg = encryptMessage(message, aesSecretKey);

	// Encrypt AES key, put in file
	byte[] aesEnc = encryptAESKey(aesSecretKey, receiver.getPub());

	// Send message and key to receiver
	FileOutputStream msgWrite = new FileOutputStream(receiver.getInbox() + "/" + getUsername() + ".msg", true);
	FileOutputStream keyWrite = new FileOutputStream(receiver.getInbox() + "/" + getUsername() + ".kgn", true);
	keyWrite.write(Base64.getEncoder().encode(aesEnc));
	msgWrite.write(Base64.getEncoder().encode(encMsg));
	keyWrite.close();
	msgWrite.close();

	// Add file to CHECKER, temp operations for WatchInbox service
	checkerUpdate(receiver);
}

// FUNCTIONS FOR DECRYPTION

public byte[] decryptAESKey(byte[] aesEnc) throws Exception {
	System.out.println("Decrypt AES key...\n");
	byte[] aesEncString = Base64.getDecoder().decode(aesEnc);
	Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
	cipher.init(Cipher.DECRYPT_MODE, getPriv());
	byte[] decAes = cipher.doFinal(aesEncString);
	System.out.println("===========================\n");
	return decAes;
	// return cipher.doFinal(Base64.getDecoder().decode(aesEnc));
}

public String decryptMessage(byte[] msg, SecretKeySpec aeskey) throws Exception {
	System.out.println("Decrypt message...\n");
	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	cipher.init(Cipher.DECRYPT_MODE, aeskey);
	String msgDec = cipher.doFinal(Base64.getDecoder().decode(msg)).toString();
	System.out.println("============================\n");
	return msgDec;
	// return cipher.doFinal(Base64.getDecoder().decode(msg)).toString();
}

public String readMessage(User sender) throws Exception {
	// Read file in inbox
	File msgtoRead = new File(getInbox() + "/" + sender.getUsername() + ".msg");
	FileInputStream keytoRead = new FileInputStream(getInbox() + "/" + sender.getUsername() + ".kgn");
	// Read 128bits from filetoRead. That is encrypted key.
	byte[] aesEnc = new byte[128];
	keytoRead.read(aesEnc);

	// Decrypted aes key for decode
	byte[] aesDec = decryptAESKey(aesEnc);
	SecretKeySpec aesKey = new SecretKeySpec(aesDec, "AES/CBC/PKCS5Padding");

	// Read message
	byte[] message = Files.readAllBytes(msgtoRead.toPath());
	keytoRead.close();

	// Decrypt message with loaded AES key (aesKey), return this
	return new String(decryptMessage(message, aesKey));
}

huangapple
  • 本文由 发表于 2020年4月7日 03:47:13
  • 转载请务必保留本文链接:https://java.coder-hub.com/61067790.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定