- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个服务器,让套接字连接到它以通过输入流发送数据,该数据在名为 Cryptoographer 的类中使用 AES/GCM/NoPadding 进行加密。服务器具有保存连接客户端功能的线程,每个线程都在 ConnectionThread 类中表示,该类保存对在服务器类中初始化的密码器类的引用。
问题:
当我发送第一个命令时,它工作得很好,没有任何问题。但不知何故,当我发送第二个命令时,如果给出以下堆栈跟踪:
javax.crypto.AEADBadTagException: Tag mismatch!
at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:595)
at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1116)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1053)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208)
at com.company.security.Cryptographer.decrypt(Cryptographer.java:53)
at com.company.client.Reader.run(Reader.java:45)
at java.base/java.lang.Thread.run(Thread.java:835)
Exception in thread "Thread-3" java.lang.NullPointerException
at java.base/java.lang.String.<init>(String.java:623)
at com.company.client.Reader.run(Reader.java:47)
at java.base/java.lang.Thread.run(Thread.java:835)
这些是堆栈跟踪中提到的类
密码学家
package com.company.security;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Cryptographer {
private Key secretKey;
private GCMParameterSpec gcmParameterSpec;
public Cryptographer() {
byte[] secret = new byte[16]; // 128 bit is 16 bytes, and AES accepts 16 bytes, and a few others.
byte[] secretBytes = "secret".getBytes();
byte[] IV = new byte[12];
gcmParameterSpec = new GCMParameterSpec(16 * 8, IV);
System.arraycopy(secretBytes, 0, secret, 0, secretBytes.length);
secretKey = new SecretKeySpec(secret, "AES");
}
/**
* Encrypt data.
* @param data to encrypt
* @return encrypted data
*/
public byte[] encrypt(byte[] data) {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);
byte[] encrypted = cipher.doFinal(data);
return encrypted;
} catch (InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | NoSuchPaddingException
| NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
return null;
}
}
/**
* Decrypt data.
* @param data to decrypt
* @return decrypted data
*/
public byte[] decrypt(byte[] data) {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec);
return cipher.doFinal(data);
} catch (InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | NoSuchPaddingException
| NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
return null;
}
}
}
阅读器
package com.company.client;
import com.company.FileLoader;
import com.company.client.helpers.ClientFileHelper;
import com.company.client.workers.MessageSender;
import com.company.security.Cryptographer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
public class Reader implements Runnable {
private InputStream inputStream;
private ClientFileHelper fileHelper;
private Cryptographer cryptographer;
private FileLoader fileLoader;
private BufferedReader bufferedReader;
private MessageSender messageSender;
private boolean isActive = true;
private boolean isReceivingFile = false;
public Reader(BufferedReader bufferedReader, MessageSender messageSender, InputStream inputStream) {
this.bufferedReader = bufferedReader;
this.messageSender = messageSender;
this.inputStream = inputStream;
cryptographer = new Cryptographer();
}
@Override
public void run() {
while (isActive) {
try {
int count;
byte[] buffer;
if(!isReceivingFile) {
buffer = new byte[inputStream.available()];
} else {
buffer = new byte[inputStream.available()];
}
while ((count = inputStream.read(buffer)) > 0)
{
byte[] decrypted = cryptographer.decrypt(buffer);
if(!isReceivingFile) {
handleInput(new String(decrypted));
} else {
if(fileHelper.getFileBytes().length == 0) {
fileHelper.setFileBytes(decrypted);
} else {
fileHelper.saveFile();
isReceivingFile = false;
}
}
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/**
* Handle the user input form the console.
* @param input user input from console
*/
private void handleInput(String input) {
try {
if (input.equals("PING")) { // If we get a PING message we send back a PONG message.
messageSender.send("PONG");
} else if (input.contains("FILE")) {
setupFileAccept(input);
isReceivingFile = true;
} else {
System.out.println(input);
}
} catch (Exception ex) {
isActive = false;
}
}
/**
* Setup the file helper for the client that's going to receive a file.
* @param line command
*/
private void setupFileAccept(String line) {
String[] args = line.split(" ");
if(args[0].equals("FILE")) {
fileHelper = new ClientFileHelper(args[1], Integer.valueOf(args[2]));
}
}
}
ConnectionThread 也有类似的读取功能,如下所示:
while (isActive) {
try {
int count;
byte[] buffer;
if(!isReceivingFile) {
buffer = new byte[inputStream.available()];
} else {
buffer = fileHelper.getFileBytes();
}
while ((count = inputStream.read(buffer)) > 0)
{
byte[] decrypted = server.cryptographer.decrypt(buffer);
if(!isReceivingFile) {
getInput(new String(decrypted));
} else {
fileHelper.setFileBytes(decrypted);
// bytes received, now we can send the file!
if(fileHelper.sendToReceiver()) {
writeToClient(fileHelper.getReceiverName()
+ " received " + fileHelper.getFilename());
fileHelper = null;
}
}
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
在这种情况下,只需假设 Server 类具有正确初始化的 cryptoographer 属性,情况总是如此。
我的猜测是某个值在某个地方做错了事情,但我不确定。我对应该做什么来解决这个问题一无所知。有人可以帮我指出错误并提出可能的解决方案来解决这个问题吗?我的java版本是12.0.1
最佳答案
我鼓励考虑使用 SSL/TLS 或 DTLS,而不是尝试重新实现其中的一部分。
我不确定它是否会导致您的错误,但如果我对 Java documentation 的解释是否如此是正确的,您应该更改每条消息的 GCMParameterSpec:
after each encryption operation using GCM mode, callers shouldre-initialize the cipher objects with GCM parameters which has adifferent IV value
和:
GCM mode has a uniqueness requirement on IVs used in encryption with a given key. When IVs are repeated for GCM encryption, such usages are subject to forgery attacks.
此外,您没有使用 updateAAD(附加身份验证数据),尽管根据 https://www.rfc-editor.org/rfc/rfc5084 这是可选的从错误消息来看,这似乎是它导致了错误,但它可能只是一个误导性的错误消息。
更新:
我为 Cryptoographer 类编写了大量单元测试,只有在再次解密之前开始对密文进行随机更改时,我经常会遇到相同的错误。因为我们可以信任 TCP/IP 在连接的另一端重现完全相同的字节,所以我们可能会遇到此类问题:
不,我还没有编写和测试我自己的实现,但是有一些例子,比如 this example , nicely explained by the author here来自the code was found by this search
关于java - AEADBadTagException 标签与套接字数据不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60822488/
我有一个服务器,让套接字连接到它以通过输入流发送数据,该数据在名为 Cryptoographer 的类中使用 AES/GCM/NoPadding 进行加密。服务器具有保存连接客户端功能的线程,每个线程
我目前在尝试解密我已加密的文件时收到 AEADBadTagException。我几乎在 stackoverflow 上到处搜索但找不到解决方案,希望我犯了一个小错误或与编码等有关,因为 GCM 无法验
我正在编写一个有很多安全限制的应用程序:它需要安全加密地存储文件,并且必须能够解密它们。此外,运算符(operator)需要能够在没有应用程序的情况下解密文件。 为了存档此内容,我在 PC 上生成了一
我正在尝试使用 AES/GCM/NoPadding 在 Java8 中进行加密。但我无法弄清楚为什么在解密时出现 AEADBadTagException。 这是我的代码: private final
我为我的 Android 应用程序编写了一个简单的加密和解密助手类来安全地加密和存储字符串。 它包含一个用于加密的静态公共(public)方法,然后它调用一个私有(private)静态方法来解密加密的
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
初始化 vector 和盐与加密数据一起存储,因此您只需要提供密码。我需要它来分发我的私有(private)代码签名 key ,以便我可以从我正在使用的任何计算机进行访问以解密和签署任何编辑。目标是迁
我不明白为什么我总是收到以下代码的异常: public class AES { /*Some private vars (not shown)*/ public AES(String
在第一次尝试实现 AES-GCM 时,我们在生成 AuthenticationTag、加密密码和 GCM mac 检查时遇到了问题,最终失败了。对于当前的实现,正在填充 tag[] 但 byte[]
Java:Oracle jre1.8.0_45 提供商:BC,BouncyCaSTLe v1.52 密码:AES 256 位 key (已安装安全策略) AEAD 模式:GCM 算法:AES/GCM/
我实现了一个简单的 Java 实用程序类来使用 AES/GCM/NoPadding 进行加密和解密。我使用这段代码: public byte[] encrypt(byte[] input, byte[
我使用了在线的 AES-GCM 示例 java 代码。UDP 客户端必须使用 AES-GCM 模式加密数据并将其发送到服务器。UDP 服务器必须接收并解密它。当我这样做时有两个问题 1.我向服务器发送
我用 Java 编写了这个加密和解密的最小示例,使用 Bouncy CaSTLe、PBKDF2WithHmacSHA256 从密码中派生 key ,并使用 AES/GCM/NoPadding 来加密/
我是一名优秀的程序员,十分优秀!