你可以试试这个:
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);
}
}
}