我希望使用ChaCha加密一些文件,所以我想知道使用Chacha20Poly1305是否合适。这个类似乎是为TLS设计的,这是否意味着它不是为文件加密而设计的呢?内部的方法(例如,encodePlaintext()和decodeCiphertext() )似乎处理的是文本而不是二进制文件。
如果是这样的话,有人知道如何使用BC的ChaCha实现进行文件加密吗?
发布于 2015-09-20 15:13:48
你可以试试这句话:
public void doChaCha(boolean encrypt, InputStream is, OutputStream os,
byte[] key, byte[] iv) throws IOException {
CipherParameters cp = new KeyParameter(key);
ParametersWithIV params = new ParametersWithIV(cp, iv);
StreamCipher engine = new ChaChaEngine();
engine.init(encrypt, params);
byte in[] = new byte[8192];
byte out[] = new byte[8192];
int len = 0;
while(-1 != (len = is.read(in))) {
len = engine.processBytes(in, 0 , len, out, 0);
os.write(out, 0, len);
}
}
public void encChaCha(InputStream is, OutputStream os, byte[] key,
byte[] iv) throws IOException {
doChaCha(true, is, os, key, iv);
}
public void decChaCha(InputStream is, OutputStream os, byte[] key,
byte[] iv) throws IOException {
doChaCha(false, is, os, key, iv);
}注意,ChaChaEngine只支持长度为128或256位的密钥,IV为64位。
以下是一些测试:
@Test
public void chachaText() throws IOException, NoSuchAlgorithmException {
String text = "chacha.txt";
Files.write(Paths.get(text), "Hello, World!".getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE);
chacha(text);
}
@Test
public void chachaBin() throws IOException, NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] data = new byte[1024*1024*4];
sr.nextBytes(data);
String bin = "chacha.bin";
Files.write(Paths.get(bin), data, StandardOpenOption.CREATE);
chacha(bin);
}
private void chacha(String file) throws NoSuchAlgorithmException, IOException {
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] key = new byte[32]; // 32 for 256 bit key or 16 for 128 bit
byte[] iv = new byte[8]; // 64 bit IV required by ChaCha20
sr.nextBytes(key);
sr.nextBytes(iv);
String dat = String.format("%s.dat", file);
try(InputStream is = new FileInputStream(file);
OutputStream os = new FileOutputStream(dat)) {
encChaCha(is, os, key, iv);
}
try(InputStream is = new FileInputStream(dat);
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
decChaCha(is, os, key, iv);
byte[] actual = os.toByteArray();
byte[] expected = Files.readAllBytes(Paths.get(file));
Assert.assertArrayEquals(expected, actual);
}
}编辑:编码/解码字符串
@Test
public void chachaString() throws IOException, NoSuchAlgorithmException
{
String test = "Hello, World!";
try (InputStream isEnc = new ByteArrayInputStream(test.getBytes(StandardCharsets.UTF_8));
ByteArrayOutputStream osEnc = new ByteArrayOutputStream())
{
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] key = new byte[32]; // 32 for 256 bit key or 16 for 128 bit
byte[] iv = new byte[8]; // 64 bit IV required by ChaCha20
sr.nextBytes(key);
sr.nextBytes(iv);
encChaCha(isEnc, osEnc, key, iv);
byte[] encoded = osEnc.toByteArray();
try (InputStream isDec = new ByteArrayInputStream(encoded);
ByteArrayOutputStream osDec = new ByteArrayOutputStream())
{
decChaCha(isDec, osDec, key, iv);
byte[] decoded = osDec.toByteArray();
String actual = new String(decoded, StandardCharsets.UTF_8);
Assert.assertEquals(test, actual);
}
}
}发布于 2015-09-20 19:56:43
您可以简单地使用由ChaChaEngine类引用的Chacha20Poly1305类。Engine类包含各种密码类的实现。
除此之外,JCA还提供了一个更高级别的API来处理各种密码。因此,您还可以使用:
Security.addProvider(new BouncyCastleProvider());
Cipher c = Cipher.getInstance("ChaCha");之后,正常的Java CipherInputStream和CipherOutputStream就可以使用了。
注意,使用Poly1305确实提供了额外的身份验证。这通常不是文件加密的要求,但它确实提供了额外的安全性层。如果您想要经过身份验证的加密,但您无法解决如何,那么请问一个单独的问题。
发布于 2019-09-24 13:16:32
Java 11添加了一个"ChaCha20-Poly1305/None/NoPadding“密码现在可以不用BouncyCastle或其他魔法->
这是一个参考Implementation
package chaCha20Poly1305Encryption;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
public class ChaCha20Poly1305 {
public static byte[] encrypt(byte[] data, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
if(key == null) throw new InvalidKeyException("SecretKey must NOT be NULL");
byte[] nonceBytes = new byte[12];
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// Create IvParamterSpec
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "ChaCha20");
// Initialize Cipher for ENCRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
// Perform Encryption
return cipher.doFinal(data);
}
public static byte[] decrypt(byte[] cipherText, SecretKey key) throws Exception {
if(key == null) throw new InvalidKeyException("SecretKey must NOT be NULL");
byte[] nonceBytes = new byte[12];
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// Create IvParamterSpec
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "ChaCha20");
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
// Perform Decryption
return cipher.doFinal(cipherText);
}
public static void main(String[] args) throws Exception {
SecretKey key = ChaCha20Poly1305KeyGenerator.generateKey();
String testMessage = "hallo!";
byte[] encryptedBytes = encrypt(testMessage.getBytes(), key);
String decryptedMessage = new String(decrypt(encryptedBytes,key));
System.out.println("testMessage: " + testMessage);
System.out.println(key.getAlgorithm() + " SecretKey: " + Base64.getEncoder().encodeToString(key.getEncoded()));
System.out.println("encryptedBytes: " + Base64.getEncoder().encodeToString(encryptedBytes));
System.out.println("decryptedMessage: "+ decryptedMessage);
}
}以及相应的密钥生成器:
package chaCha20Poly1305Encryption;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class ChaCha20Poly1305KeyGenerator {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("ChaCha20");
//Keysize MUST be 256 bit - as of Java11 only 256Bit is supported
keyGenerator.init(256);
return keyGenerator.generateKey();
}
public static void main(String[] args) throws NoSuchAlgorithmException {
SecretKey key = generateKey();
System.out.println(key.getAlgorithm() + " SecretKey: " + Base64.getEncoder().encodeToString(key.getEncoded()));
}
}GIST:https://gist.github.com/eXspir3/7a0821a6cfdb0495ccc3e69b475a61b9中使用的代码
https://stackoverflow.com/questions/32672241
复制相似问题