Created
February 3, 2013 06:47
-
-
Save Chase-san/4700773 to your computer and use it in GitHub Desktop.
An implementation of the Rabbit Stream Cipher.
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
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