Skip to content

Instantly share code, notes, and snippets.

@Chase-san
Created February 3, 2013 06:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chase-san/4700773 to your computer and use it in GitHub Desktop.
Save Chase-san/4700773 to your computer and use it in GitHub Desktop.
An implementation of the Rabbit Stream Cipher.
package org.csdgn.crypt;
import java.util.Arrays;
/**
* Tested against the actual RFC.
* This implementation is optimized for code length.
* Please do not use this version in production, use the much faster unrolled version here: https://gist.github.com/2814851
* @author Robert Maupin
* @see {@link http://tools.ietf.org/rfc/rfc4503.txt}
*/
public class Rabbit {
static int rtl(int v, int k) {
return (k &= 31) == 0 ? v : (v << k) | (v >>> (32 - k));
}
private static final int[] A = new int[8], X = new int[8], C = new int[8];
private byte b;
static {
A[0] = A[3] = A[6] = 0x4D34D34D;
A[1] = A[4] = A[7] = 0xD34D34D3;
A[2] = A[5] = 0x34D34D34;
}
private void s() {
long t;
int i;
for(i = 0; i < 8; ++i) {
t = (C[i] & 0xFFFFFFFFL) + (A[i] & 0xFFFFFFFFL) + b;
b = (byte) (t >>> 32);
C[i] = (int) (t & 0xFFFFFFFF);
}
// g function, small as I can get, 32 bits only would be nice though.
int G[] = new int[8];
for(i = 0; i < 8; ++i) {
t = (X[i] + C[i]) & 0xFFFFFFFFL;
G[i] = (int) ((t *= t) ^ (t >>> 32));
}
for(i = 0; i < 8; ++i) {
X[i] = G[i] + rtl(G[(i + 7) % 8], (i + 1 & 1) + 1 << 3) + ((i & 1) == 0 ? rtl(G[(i + 6) % 8], 16) : G[(i + 6) % 8]);
}
}
/**
* Should be fed an array with a length that is a multiple of 16 for proper key sequencing.
*/
public void crypt(byte[] message) {
int index = 0;
while (index < message.length) {
byte[] keystream = ks();
for (int i = 0; i < 16 && index < message.length; ++i) {
message[index++] ^= keystream[i];
}
}
}
private byte[] ks() {
byte[] s = new byte[16];
s();
for(int i = 0; i < 16; ++i)
s[i] = (byte) ((X[(3 - (i >> 2) << 1)] ^ (X[(3 + (i >> 2) * 6) % 8] >>> 16) ^ (X[(1 + (i >> 2) * 6) % 8] << 16)) >> (24 - ((i << 3) % 32)));
return s;
}
public void reset() {
b = 0;
Arrays.fill(X, 0);
Arrays.fill(C, 0);
}
/**
* @param K array of 8 short values
*/
public void key(short[] K) {
for(int i = 0; i < 8; ++i) {
//look ma' no ternary!
X[i] = (K[1 + (i * 5) % 8 & 7] << 16) | (K[(i * 5) % 8 & 7] & 0xFFFF);
C[i] = (K[4 + (i * 5) % 8 & 7] << 16) | (K[5 + (i * 5) % 8 & 7] & 0xFFFF);
}
s();
s();
s();
s();
for(int i = 0; i < 8; ++i)
C[i] ^= X[(i + 4) % 8];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment