package org.bouncycastle.crypto.engines;

import org.bouncycastle.util.Pack;

Implementation of Daniel J. Bernstein's ChaCha stream cipher.
/** * Implementation of Daniel J. Bernstein's ChaCha stream cipher. */
public class ChaCha7539Engine extends Salsa20Engine {
Creates a 20 rounds ChaCha engine.
/** * Creates a 20 rounds ChaCha engine. */
public ChaCha7539Engine() { super(); } public String getAlgorithmName() { return "ChaCha7539-" + rounds; } protected int getNonceSize() { return 12; } protected void advanceCounter(long diff) { int hi = (int)(diff >>> 32); int lo = (int)diff; if (hi > 0) { throw new IllegalStateException("attempt to increase counter past 2^32."); } int oldState = engineState[12]; engineState[12] += lo; if (oldState != 0 && engineState[12] < oldState) { throw new IllegalStateException("attempt to increase counter past 2^32."); } } protected void advanceCounter() { if (++engineState[12] == 0) { throw new IllegalStateException("attempt to increase counter past 2^32."); } } protected void retreatCounter(long diff) { int hi = (int)(diff >>> 32); int lo = (int)diff; if (hi != 0) { throw new IllegalStateException("attempt to reduce counter past zero."); } if ((engineState[12] & 0xffffffffL) >= (lo & 0xffffffffL)) { engineState[12] -= lo; } else { throw new IllegalStateException("attempt to reduce counter past zero."); } } protected void retreatCounter() { if (engineState[12] == 0) { throw new IllegalStateException("attempt to reduce counter past zero."); } --engineState[12]; } protected long getCounter() { return engineState[12] & 0xffffffffL; } protected void resetCounter() { engineState[12] = 0; } protected void setKey(byte[] keyBytes, byte[] ivBytes) { if (keyBytes != null) { if (keyBytes.length != 32) { throw new IllegalArgumentException(getAlgorithmName() + " requires 256 bit key"); } packTauOrSigma(keyBytes.length, engineState, 0); // Key Pack.littleEndianToInt(keyBytes, 0, engineState, 4, 8); } // IV Pack.littleEndianToInt(ivBytes, 0, engineState, 13, 3); } protected void generateKeyStream(byte[] output) { ChaChaEngine.chachaCore(rounds, engineState, x); Pack.intToLittleEndian(x, output, 0); } }