forked from bcgit/bc-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/xsalsa20' of git://github.com/timw/bc-java into…
… timw-feature/xsalsa20 Conflicts: core/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java prov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
- Loading branch information
Showing
12 changed files
with
1,000 additions
and
100 deletions.
There are no files selected for viewing
186 changes: 186 additions & 0 deletions
186
core/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package org.bouncycastle.crypto.engines; | ||
|
||
import org.bouncycastle.crypto.util.Pack; | ||
|
||
/** | ||
* Implementation of Daniel J. Bernstein's ChaCha stream cipher. | ||
*/ | ||
public class ChaChaEngine extends Salsa20Engine | ||
{ | ||
|
||
/** | ||
* Creates a 20 rounds ChaCha engine. | ||
*/ | ||
public ChaChaEngine() | ||
{ | ||
super(); | ||
} | ||
|
||
/** | ||
* Creates a ChaCha engine with a specific number of rounds. | ||
* @param rounds the number of rounds (must be an even number). | ||
*/ | ||
public ChaChaEngine(int rounds) | ||
{ | ||
super(rounds); | ||
} | ||
|
||
public String getAlgorithmName() | ||
{ | ||
return "ChaCha" + rounds; | ||
} | ||
|
||
protected void advanceCounter() | ||
{ | ||
if (++engineState[12] == 0) | ||
{ | ||
++engineState[13]; | ||
} | ||
} | ||
|
||
protected void resetCounter() | ||
{ | ||
engineState[12] = engineState[13] = 0; | ||
} | ||
|
||
protected void setKey(byte[] keyBytes, byte[] ivBytes) | ||
{ | ||
if ((keyBytes.length != 16) && (keyBytes.length != 32)) | ||
{ | ||
throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key"); | ||
} | ||
|
||
int offset = 0; | ||
byte[] constants; | ||
|
||
// Key | ||
engineState[4] = Pack.littleEndianToInt(keyBytes, 0); | ||
engineState[5] = Pack.littleEndianToInt(keyBytes, 4); | ||
engineState[6] = Pack.littleEndianToInt(keyBytes, 8); | ||
engineState[7] = Pack.littleEndianToInt(keyBytes, 12); | ||
|
||
if (keyBytes.length == 32) | ||
{ | ||
constants = sigma; | ||
offset = 16; | ||
} else | ||
{ | ||
constants = tau; | ||
} | ||
|
||
engineState[8] = Pack.littleEndianToInt(keyBytes, offset); | ||
engineState[9] = Pack.littleEndianToInt(keyBytes, offset + 4); | ||
engineState[10] = Pack.littleEndianToInt(keyBytes, offset + 8); | ||
engineState[11] = Pack.littleEndianToInt(keyBytes, offset + 12); | ||
|
||
engineState[0] = Pack.littleEndianToInt(constants, 0); | ||
engineState[1] = Pack.littleEndianToInt(constants, 4); | ||
engineState[2] = Pack.littleEndianToInt(constants, 8); | ||
engineState[3] = Pack.littleEndianToInt(constants, 12); | ||
|
||
// Counter | ||
engineState[12] = engineState[13] = 0; | ||
|
||
// IV | ||
engineState[14] = Pack.littleEndianToInt(ivBytes, 0); | ||
engineState[15] = Pack.littleEndianToInt(ivBytes, 4); | ||
} | ||
|
||
protected void generateKeyStream(byte[] output) | ||
{ | ||
chachaCore(rounds, engineState, x); | ||
Pack.intToLittleEndian(x, output, 0); | ||
} | ||
|
||
/** | ||
* ChacCha function | ||
* | ||
* @param input input data | ||
* | ||
* @return keystream | ||
*/ | ||
public static void chachaCore(int rounds, int[] input, int[] x) | ||
{ | ||
if (input.length != 16) { | ||
throw new IllegalArgumentException(); | ||
} | ||
if (x.length != 16) { | ||
throw new IllegalArgumentException(); | ||
} | ||
if (rounds % 2 != 0) { | ||
throw new IllegalArgumentException("Number of rounds must be even"); | ||
} | ||
|
||
int x00 = input[ 0]; | ||
int x01 = input[ 1]; | ||
int x02 = input[ 2]; | ||
int x03 = input[ 3]; | ||
int x04 = input[ 4]; | ||
int x05 = input[ 5]; | ||
int x06 = input[ 6]; | ||
int x07 = input[ 7]; | ||
int x08 = input[ 8]; | ||
int x09 = input[ 9]; | ||
int x10 = input[10]; | ||
int x11 = input[11]; | ||
int x12 = input[12]; | ||
int x13 = input[13]; | ||
int x14 = input[14]; | ||
int x15 = input[15]; | ||
|
||
for (int i = rounds; i > 0; i -= 2) | ||
{ | ||
x00 += x04; x12 = rotl(x12 ^ x00, 16); | ||
x08 += x12; x04 = rotl(x04 ^ x08, 12); | ||
x00 += x04; x12 = rotl(x12 ^ x00, 8); | ||
x08 += x12; x04 = rotl(x04 ^ x08, 7); | ||
x01 += x05; x13 = rotl(x13 ^ x01, 16); | ||
x09 += x13; x05 = rotl(x05 ^ x09, 12); | ||
x01 += x05; x13 = rotl(x13 ^ x01, 8); | ||
x09 += x13; x05 = rotl(x05 ^ x09, 7); | ||
x02 += x06; x14 = rotl(x14 ^ x02, 16); | ||
x10 += x14; x06 = rotl(x06 ^ x10, 12); | ||
x02 += x06; x14 = rotl(x14 ^ x02, 8); | ||
x10 += x14; x06 = rotl(x06 ^ x10, 7); | ||
x03 += x07; x15 = rotl(x15 ^ x03, 16); | ||
x11 += x15; x07 = rotl(x07 ^ x11, 12); | ||
x03 += x07; x15 = rotl(x15 ^ x03, 8); | ||
x11 += x15; x07 = rotl(x07 ^ x11, 7); | ||
x00 += x05; x15 = rotl(x15 ^ x00, 16); | ||
x10 += x15; x05 = rotl(x05 ^ x10, 12); | ||
x00 += x05; x15 = rotl(x15 ^ x00, 8); | ||
x10 += x15; x05 = rotl(x05 ^ x10, 7); | ||
x01 += x06; x12 = rotl(x12 ^ x01, 16); | ||
x11 += x12; x06 = rotl(x06 ^ x11, 12); | ||
x01 += x06; x12 = rotl(x12 ^ x01, 8); | ||
x11 += x12; x06 = rotl(x06 ^ x11, 7); | ||
x02 += x07; x13 = rotl(x13 ^ x02, 16); | ||
x08 += x13; x07 = rotl(x07 ^ x08, 12); | ||
x02 += x07; x13 = rotl(x13 ^ x02, 8); | ||
x08 += x13; x07 = rotl(x07 ^ x08, 7); | ||
x03 += x04; x14 = rotl(x14 ^ x03, 16); | ||
x09 += x14; x04 = rotl(x04 ^ x09, 12); | ||
x03 += x04; x14 = rotl(x14 ^ x03, 8); | ||
x09 += x14; x04 = rotl(x04 ^ x09, 7); | ||
|
||
} | ||
|
||
x[ 0] = x00 + input[ 0]; | ||
x[ 1] = x01 + input[ 1]; | ||
x[ 2] = x02 + input[ 2]; | ||
x[ 3] = x03 + input[ 3]; | ||
x[ 4] = x04 + input[ 4]; | ||
x[ 5] = x05 + input[ 5]; | ||
x[ 6] = x06 + input[ 6]; | ||
x[ 7] = x07 + input[ 7]; | ||
x[ 8] = x08 + input[ 8]; | ||
x[ 9] = x09 + input[ 9]; | ||
x[10] = x10 + input[10]; | ||
x[11] = x11 + input[11]; | ||
x[12] = x12 + input[12]; | ||
x[13] = x13 + input[13]; | ||
x[14] = x14 + input[14]; | ||
x[15] = x15 + input[15]; | ||
} | ||
|
||
} |
Oops, something went wrong.