com.github.isaichkindanila.crypt.lib.cipher.ChaCha Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of crypt-lib Show documentation
Show all versions of crypt-lib Show documentation
Simple Java library for stream ciphers based encryption
The newest version!
package com.github.isaichkindanila.crypt.lib.cipher;
import com.github.isaichkindanila.crypt.lib.util.ConversionUtils;
/*
Reference:
1. https://cr.yp.to/snuffle/salsafamily-20071225.pdf
2. https://cr.yp.to/chacha/chacha-20080128.pdf
*/
class ChaCha extends StreamCipher {
/*
con con con con | 0 1 2 3
key key key key | 4 5 6 7
key key key key | 8 9 10 11
ctr ctr iv iv | 12 13 14 15
*/
private final int[] input = new int[16];
private final int[] hashed = new int[16];
private final byte[] block = new byte[64];
private final int roundCount;
private int initialCtr12Value;
ChaCha(int roundCount) {
this.roundCount = roundCount;
}
@Override
protected void init0(byte[] key, byte[] iv) {
input[0] = 0x61707865;
input[1] = 0x3320646e;
input[2] = 0x79622d32;
input[3] = 0x6b206574;
for (int i = 0; i < 8; i++) {
input[i + 4] = ConversionUtils.bytesToInt(key, i * 4);
}
for (int i = 0; i < 4; i++) {
input[i + 12] = ConversionUtils.bytesToInt(iv, i * 4);
}
initialCtr12Value = input[12];
}
private void quarterRound(int a, int b, int c, int d) {
hashed[a] += hashed[b];
hashed[d] ^= hashed[a];
hashed[d] = Integer.rotateLeft(hashed[d], 16);
hashed[c] += hashed[d];
hashed[b] ^= hashed[c];
hashed[b] = Integer.rotateLeft(hashed[b], 12);
hashed[a] += hashed[b];
hashed[d] ^= hashed[a];
hashed[d] = Integer.rotateLeft(hashed[d], 8);
hashed[c] += hashed[d];
hashed[b] ^= hashed[c];
hashed[d] = Integer.rotateLeft(hashed[b], 7);
}
@Override
protected byte[] nextBlock() {
// increase counter by 1
if (++input[12] == initialCtr12Value) {
input[13]++;
}
// initialize hashed array
System.arraycopy(input, 0, hashed, 0, 16);
// modify hashed array
for (int i = 0; i < roundCount; i++) {
quarterRound(0, 4, 8, 12); // 1st column
quarterRound(1, 5, 9, 13); // 2nd column
quarterRound(2, 6, 10, 14); // 3rd column
quarterRound(3, 7, 11, 15); // 4th column
quarterRound(0, 5, 10, 15); // 1st diagonal (main diagonal)
quarterRound(1, 6, 11, 12); // 2nd diagonal ("above" 1st)
quarterRound(2, 7, 8, 13); // 3rd diagonal ("above" 2nd)
quarterRound(3, 4, 9, 14); // 4th diagonal ("above" 3rd)
}
// add input array to hashed array
for (int i = 0; i < 16; i++) {
hashed[i] += input[i];
}
// extract hashed array to block output
for (int i = 0; i < 16; i++) {
System.arraycopy(ConversionUtils.intToBytes(hashed[i]), 0, block, i * 4, 4);
}
return block;
}
}