blob: 4b0a5edd46e99b0bfd06dafe850828c87b1d20a8 [file] [log] [blame]
package org.bouncycastle.crypto.engines;
import org.bouncycastle.util.Pack;
/**
* Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce.
* <p>
* XSalsa20 requires a 256 bit key, and a 192 bit nonce.
*/
public class XSalsa20Engine extends Salsa20Engine
{
public String getAlgorithmName()
{
return "XSalsa20";
}
protected int getNonceSize()
{
return 24;
}
/**
* XSalsa20 key generation: process 256 bit input key and 128 bits of the input nonce
* using a core Salsa20 function without input addition to produce 256 bit working key
* and use that with the remaining 64 bits of nonce to initialize a standard Salsa20 engine state.
*/
protected void setKey(byte[] keyBytes, byte[] ivBytes)
{
if (keyBytes == null)
{
throw new IllegalArgumentException(getAlgorithmName() + " doesn't support re-init with null key");
}
if (keyBytes.length != 32)
{
throw new IllegalArgumentException(getAlgorithmName() + " requires a 256 bit key");
}
// Set key for HSalsa20
super.setKey(keyBytes, ivBytes);
// Pack next 64 bits of IV into engine state instead of counter
Pack.littleEndianToInt(ivBytes, 8, engineState, 8, 2);
// Process engine state to generate Salsa20 key
int[] hsalsa20Out = new int[engineState.length];
salsaCore(20, engineState, hsalsa20Out);
// Set new key, removing addition in last round of salsaCore
engineState[1] = hsalsa20Out[0] - engineState[0];
engineState[2] = hsalsa20Out[5] - engineState[5];
engineState[3] = hsalsa20Out[10] - engineState[10];
engineState[4] = hsalsa20Out[15] - engineState[15];
engineState[11] = hsalsa20Out[6] - engineState[6];
engineState[12] = hsalsa20Out[7] - engineState[7];
engineState[13] = hsalsa20Out[8] - engineState[8];
engineState[14] = hsalsa20Out[9] - engineState[9];
// Last 64 bits of input IV
Pack.littleEndianToInt(ivBytes, 16, engineState, 6, 2);
}
}