我试图在Android上使用javax.crypto.cipher使用AES-GCM对数据流进行块加密。据我所知,对于一个多部分的加密操作,可以使用cipher.update多次,并使用cipher.doFinal完成。但是,当使用aes/gcm/nopadding转换时,cipher.update拒绝将数据输出到提供的缓冲区,并返回0个写入字节。缓冲区在密码中建立,直到我调用。doFinal。这似乎也发生在CCM(我假设其他经过身份验证的模式)中,但适用于其他模式,如CBC。
我认为GCM可以在加密时计算身份验证标记,所以我不知道为什么不允许我使用密码中的缓冲区。
val secretKey = KeyGenerator.getInstance("AES").run {
init(256)
generateKey()
}
val iv = ByteArray(12)
SecureRandom().nextBytes(iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iv))
// Pretend this is some file I want to read and encrypt
val inputBuffer = Random.nextBytes(1024000)
val outputBuffer = ByteArray(cipher.getOutputSize(512))
val read = cipher.update(inputBuffer, 0, 512, outputBuffer, 0)
// ^ at this point, read = 0 and outputBuffer is [0, 0, 0, ...]
// Future calls to cipher.update and cipher.getOutputSize indicate that
// the internal buffer is growing. But I would like to consume it through
// outputBuffer
// ...
cipher.doFinal(outputBuffer, 0)
// Now outputBuffer is populated
我想做的是从磁盘流式传输一个大文件,加密它并通过网络一个块一个块地发送它,而不必将整个文件数据加载到内存中。我尝试使用CipherInputStream,但它遇到了同样的问题。
用AES/GCM可以吗?
这是由Android默认使用的Conscrypt提供程序中的一个限制造成的。下面是一个代码示例,我不是在Android上运行的,而是在我的Mac上运行的,它显式地使用Conscrypt提供程序,然后使用Bouncycastle(BC)提供程序来显示不同之处。因此,一个解决办法是将BC提供者添加到您的Android项目中,并在调用cipher.getinstance()
时显式地指定它。当然,这是有权衡的。虽然BC提供者会在每次调用update()
时向您返回密文,但总体吞吐量可能会大大降低,因为Conscrypt使用本机库,而BC是纯Java。
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.conscrypt.Conscrypt;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
public class ConscryptIssue1 {
private final static Provider CONSCRYPT = Conscrypt.newProvider();
private final static Provider BC = new BouncyCastleProvider();
public static void main(String[] args) throws GeneralSecurityException {
Security.addProvider(CONSCRYPT);
doExample();
}
private static void doExample() throws GeneralSecurityException {
final SecureRandom secureRandom = new SecureRandom();
{
// first, try with Conscrypt
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256, secureRandom);
SecretKey aesKey = keyGenerator.generateKey();
byte[] plaintext = new byte[10000]; // plaintext is all zeros
byte[] nonce = new byte[12];
secureRandom.nextBytes(nonce);
Cipher c = Cipher.getInstance("AES/GCM/NoPadding", CONSCRYPT);// specify the provider explicitly
GCMParameterSpec spec = new GCMParameterSpec(128, nonce);// tag length is specified in bits.
c.init(Cipher.ENCRYPT_MODE, aesKey, spec);
byte[] outBuf = new byte[c.getOutputSize(512)];
int numProduced = c.update(plaintext, 0, 512, outBuf, 0);
System.out.println(numProduced);
final int finalProduced = c.doFinal(outBuf, numProduced);
System.out.println(finalProduced);
}
{
// Next, try with Bouncycastle
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256, secureRandom);
SecretKey aesKey = keyGenerator.generateKey();
byte[] plaintext = new byte[10000]; // plaintext is all zeros
byte[] nonce = new byte[12];
secureRandom.nextBytes(nonce);
Cipher c = Cipher.getInstance("AES/GCM/NoPadding", BC);// specify the provider explicitly
GCMParameterSpec spec = new GCMParameterSpec(128, nonce);// tag length is specified in bits.
c.init(Cipher.ENCRYPT_MODE, aesKey, spec);
byte[] outBuf = new byte[c.getOutputSize(512)];
int numProduced = c.update(plaintext, 0, 512, outBuf, 0);
System.out.println(numProduced);
final int finalProduced = c.doFinal(outBuf, numProduced);
System.out.println(finalProduced);
}
}
}
Java:Oracle JRE1.8.0_45 提供商:BC,BouncyCastle v1.52 我只是像这样做篡改,在byte[]已经包含加密数据和身份验证标记的16个额外字节之后,我覆盖它的第一个字节。 当我在模拟篡改时更改指定的值时,得到的解密文本在第一个字符处发生更改。它以非线性的方式变化。0x65生成“C”,0x67生成“?”诸如此类。普通消息的其余部分保持正确,只有解密输出的第一个字
下面的代码尝试使用缓冲区将WAV文件的头写入流,然后将其写入可写流。 出于某种原因,文件的前8个字节是错误的: 第一行应该是: 这条线路有故障: 它需要:
我正在尝试向arduino的串行监视器发送一些数据,并使led亮起,但我还无法获取它。我的代码中有什么问题请检查这里是arduino代码 下面是java代码
问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或
我正在使用C#在客户机/服务器应用程序中执行一些加密方法。NET框架和PHP。加密方法是AES-256-GCM,在PHP中非常简单。这个NET代码,我从这里复制了一些修改。这个NET版本产生了不同的值。 在PHP版本中,我可以这样写 在C#中,我试图使其保持一致 编辑: 所有方法都包括在内。 这个问题不是重复的
上一章讲的东西比较多,完全理解会有点难,所以这一章来点容易的。我们已经学习了如何定义本地缓冲区的映射和设置选项,现在以同样的方式来学习本地缓冲区的缩写。 打开你的foo和bar这两个文件,切换到foo,然后执行下面的命令: :::vim :iabbrev <buffer> --- — 在文件foo下进入插入模式输入下面的文本: :::text Hello --- world. Vi