Initial commit into GIT.

Signed-off-by: default avatard.miller@cablelabs.com <d.miller@CableLabs.com>
parents

Too many changes to show.

To preserve performance only 218 of 218+ files are displayed.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0034)http://www.cryptix.org/LICENSE.TXT --><HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=windows-1252">
<META content="MSHTML 6.00.2900.3132" name=GENERATOR></HEAD>
<BODY><PRE>Cryptix General License
Copyright (c) 1995-2005 The Cryptix Foundation Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND
CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</PRE></BODY></HTML>
package com.cablelabs.mmh;
import java.security.*;
import java.nio.ByteBuffer;
import java.math.BigInteger;
public class MMH {
static final protected int MSG_PAD_LENGTH = 2;
static final protected int KEY_PADDING = 6;
static final public int WORD_SIZE = 16;
static final public int INT_SIZE = (Integer.SIZE / 8);
// If the KEY_SIZE changes, KEY_ITERATIONS must also change
static final protected int INIT_KEY_SIZE = 2048;
static final protected int INIT_KEY_ITERATIONS = INIT_KEY_SIZE / WORD_SIZE;
static final public String SEED_1 = "CMTS-EMIC"; // also known as DELTA-1
static final public String SEED_2 = "CMTS-EMIC-PAD"; // "CMTS-EMIC-PAD"; // also known as DELTA-2
static final public int BLOCK_SIZE = 128;
static final public int MMH_SIZE = 8;
public static final int BYTE = 8;
public static final int CHAR_SIZE = (Character.SIZE / BYTE);
private byte [] sharedSecret = null;
private byte [] s1 = null;
private byte [] s2 = null;
private byte [] ssPrime = null;
private byte [] key = null;
private byte [] messageInBytes = null;
public MMH(String ss) throws IllegalArgumentException {
this.sharedSecret = ss.getBytes();
computeS1AndS2();
}
private static String asHex(byte [] buffer, int bytePerLine) {
StringBuffer iStr = new StringBuffer();
for(int i = 0; i < buffer.length; i++) {
if((buffer[i]&0xFF) <= 15) {
iStr.append("0");
}
if (bytePerLine != -1 && ((i % bytePerLine) == 0))
iStr.append("\n" + Integer.toHexString(buffer[i]&0xff).toLowerCase() + " ");
else
iStr.append(Integer.toHexString(buffer[i]&0xff).toLowerCase() + " ");
}
return iStr.toString();
}
private static String asHex(byte [] buffer) {
return asHex(buffer, -1);
}
private byte [] intToByteArray(int i) {
ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
bb.putInt(i);
return bb.array();
}
static public boolean compare(byte [] a1, byte [] a2) {
if (a1.length != a2.length)
return false;
for (int i = 0; i < a1.length; i++) {
if (a1[i] != a2[i])
return false;
}
return true;
}
private void computeS1AndS2() {
int ssLen = sharedSecret.length;
int s1Len = ssLen/2 + (ssLen % 2);
int s2Len = ssLen/2;
s1 = new byte [s1Len];
s2 = new byte [s2Len];
// Create S1 and S2
for(int i=0;i< sharedSecret.length; i++) {
if( (i%2) == 0) {
s1[i/2] += sharedSecret[i];
}
else
{
s2[(i-1)/2] += sharedSecret[i];
}
}
System.out.println("S1 = " + asHex(s1));
System.out.println("S2 = " + asHex(s2));
}
public byte [] digest(byte [] msg) throws IllegalArgumentException{
// First make sure that the message is a multiple of the WORD_SIZE
byte [] localMsg = null;
int msgLen = msg.length;
if((msgLen % 2) != 0) {
localMsg = new byte [msg.length+1];
System.arraycopy(msg, 0, localMsg, 0, msg.length);
localMsg[msg.length] = 0x00;
msgLen++;
}
else {
localMsg = msg;
}
int blockSize = (msgLen+6)/16;
if ((msgLen+6) %16 != 0)
blockSize++;
byte [] tempkey = new byte [(blockSize*WORD_SIZE)];
for(int i=1;i<=blockSize;i++) {
//F(sS1,sSeed_1,(unsigned char)i,sKeyStream);
byte [] k = F(s1,SEED_1.getBytes(),i);
if (k != null) {
System.arraycopy(k, 0, tempkey, ((i-1)*WORD_SIZE), k.length);
// System.out.println("adding k = " + asHex(k) + " to key.");
}
}
// if (key.length < (localMsg.length + KEY_PADDING)) {
// growKey(localMsg.length + KEY_PADDING);
// }
key = new byte [(msgLen+KEY_PADDING)];
if (tempkey.length >= (msgLen+KEY_PADDING)) {
System.arraycopy(tempkey, 0, key, 0, (msgLen+KEY_PADDING));
}
System.out.println("S1 = " + asHex(s1));
System.out.println("S2 = " + asHex(s2) + "\n");
System.out.println("Shared Secret in ASCII = " + new String(sharedSecret));
System.out.println("Shared Secret in Hex (padded) = " + asHex(sharedSecret, WORD_SIZE) + "]");
System.out.println("Message in ASCII = " + new String(localMsg));
System.out.println("Message in Hex (padded) =" + asHex(localMsg, WORD_SIZE) + "\n");
System.out.println("Key =\n" + asHex(key, WORD_SIZE) + "\n");
byte [] mmh = mmh64(localMsg);
System.out.println("MMH64 function output in Hex " + asHex(mmh,WORD_SIZE));
byte [] sA = new byte [mmh.length+s2.length];
System.arraycopy(mmh, 0, sA, 0, mmh.length);
System.arraycopy(s2, 0, sA, mmh.length, s2.length);
System.out.println("A + S2 =" + asHex(sA, WORD_SIZE) + "\n");
System.out.println("Seed2 =" + asHex(SEED_2.getBytes(), WORD_SIZE) + "\n");
byte [] padding = F(sA,SEED_2.getBytes(),1);
System.out.println("padding string\n" + asHex(padding) + "\n");
byte [] pad = new byte [MMH_SIZE];
System.arraycopy(padding,0, pad, 0, pad.length);
System.out.println("pad string\n" + asHex(pad) + "\n");
BigInteger x = new BigInteger(mmh);
BigInteger y = new BigInteger(pad);
BigInteger sum = x.add(y);
//System.out.println("Sum =" + sum.toString());
byte [] hmac64 = new byte[MMH_SIZE];
// We want only the low order eight bytes of the sum
byte [] sumArray = sum.toByteArray();
System.arraycopy(sumArray, sumArray.length-MMH_SIZE, hmac64, 0, MMH_SIZE);
// System.out.println("MMH MAC64 Output\n" + asHex(hmac64, WORD_SIZE));
return hmac64;
}
private byte [] F(byte [] secret, byte [] seed, int blockNum) {
int len = secret.length;
int rem = len % WORD_SIZE;
ssPrime = new byte [WORD_SIZE];
// Create shared secret prime
// XOR every 16 octets of the shared secret
for(int i=0; i < (len / 16);i++) {
for(int j=0; j<16; j++) {
// System.out.println("SSCalc block=" + blockNum + " i=" + i + " j="
// + j + " ss[" + (j+(i*16)) + "]="
// + asHex(secret[j+(i*16)]) + " ss'[" + j + "]="
// + asHex(ssPrime[j]));
ssPrime[j] ^= secret[j+(i*16)];
// System.out.println(" ss'[" + j + "]=" + asHex(ssPrime[j]) + "\n" );
}
}
// System.out.println("S' = " + asHex(ssPrime) + "\n");
// If the shared secret is not a multiple of 16 octets, XOR and add pad
if(rem > 0)
for(int j=0;j<16;j++)
if(j > (rem-1))
ssPrime[j] ^= 0x00;
else
ssPrime[j] ^= secret[(len/16)*16 + j];
// Set IV equal to seed truncated to 128 bits
System.out.println("S'(" + blockNum +")=" + asHex(ssPrime)+ "\n");
byte [] iv = new byte [WORD_SIZE];
int seedLen = seed.length;
if (seedLen > WORD_SIZE)
seedLen = WORD_SIZE;
System.arraycopy(seed, 0, iv, 0, seedLen);
// System.out.println("sSeed = " + asHex(seed)+ "\n");
// System.out.println("B4 IV =" + asHex(iv)+ "\n");
byte [] block = intToByteArray(blockNum);
for (int i=0; i< INT_SIZE; i++) {
iv[WORD_SIZE-(INT_SIZE-i)] ^= block[i];
}
System.out.println("IV(" + blockNum +")=" + asHex(iv)+ "\n");
//Rijndael aes = new Rijndael();
try {
Object sessionKey = Rijndael.makeKey(ssPrime);
byte [] k = Rijndael.blockEncrypt(iv, 0, sessionKey);
return k;
}
catch (InvalidKeyException ike) {
System.err.println("Error encountered making key.\n"
+ ike.getMessage() + "\n" + ike.getStackTrace());
}
return null;
}
public static short getShort(byte [] buffer, int offset) {
short preview = 0x0000;
if (buffer.length >= CHAR_SIZE &&
((buffer.length - offset) >= 1))
preview = (short)(((buffer[offset] & 0xFF) << 8) |
(buffer[offset+1]&0xFF));
return preview;
}
/**
* Compute and return the MMH 16 bit hash value of the message using the
* indicated key. The length of the key must be at least msgLen bytes.
*/
private byte [] mmh16(byte [] message, int keyOffset)
{
int sum = 0; // 32-bit accumulator
for (int i = 0; i < message.length; i += 2) {
// Build a 16-bit factor from the next two message octets
// int x = ((message[i] & 0xFF) << 8) | (message[i+1] & 0xFF);
short x = getShort(message, i);
// Build a 16-bit factor from the next two key octets
// int y = ((key[(i+keyOffset)] & 0xFF) << 8) | (key[(i+keyOffset+1)] & 0xFF);
short y = getShort(key, (i+keyOffset));
// Accumulate product of the factors into 32-bit sum
sum += ((int)x * (int)y);
// System.out.println("x= " + asHex(intToByteArray((int)x)));
// System.out.println("y= " + asHex(intToByteArray((int)y)));
// System.out.println("sum=" + asHex(intToByteArray(sum)));
}
// Reduce sum modulo F4 and truncate to 16 bits
int u = reduceModF4(sum);
byte [] result = intToByteArray(u);
return result;
}
/**
* Compute and return the MMH 64 bit hash value of the message using the
* indicated key. The length of the message is msgLen bytes; msgLen must be even.
* The length of the key must be at least (msgLen + 6) bytes.
*/
private byte [] mmh64(byte [] message) throws IllegalArgumentException {
// check lengths
if (key.length < (message.length + KEY_PADDING))
throw new IllegalArgumentException ("The key length(" + key.length
+ " is less than the message's length(" + (message.length + KEY_PADDING) + ").");
byte [] result = new byte [MMH_SIZE];
byte [] a = mmh16(message, 0);
byte [] b = mmh16(message, 2);
byte [] c = mmh16(message, 4);
byte [] d = mmh16(message, 6);
// Now take the two low order bytes from each of the operations to form the hash
result[0] = a[2];
result[1] = a[3];
result[2] = b[2];
result[3] = b[3];
result[4] = c[2];
result[5] = c[3];
result[6] = d[2];
result[7] = d[3];
System.out.println("Sum = " + asHex(result));
return result;
}
/**
* Routine to reduce an 32bit value modulo F4, where F4 = 0x10001.
* Result is therefore in range [0, 0x10000].
*/
private int reduceModF4(int x)
{
int rv = x; // holder for return value
// Range of x is [0x80000000, 0x7fffffff]
// If x is negative, add a multiple of F4 to make it non-negative.
// This loop executes no more than twice.
while (rv < 0)
rv += 0x7fff7fff;
// Subtract high 16 bits of rv from low 16 bits.
int xHi = rv >> 16;
int xLo = rv & 0xffff;
rv = xLo - xHi;
// If x is negative, add F4.
if (rv < 0)
rv += 0x10001;
// we are done
return rv;
}
static public final void main(String[] args) {
String ss1= "Shared secret #1 94476839";
String ss2 = "Shared secret #2 07782313";// "Shared secret #1 94476839";
String ss3 = "DOCSIS";
byte [] result1 = { 0x29, 0x70, (byte)0xf8, 0x0c, 0x67, (byte)0xa4, (byte)0xdd, (byte)0x80 };
byte [] result2 = { (byte)0x83, (byte)0xc9, (byte)0xf8, (byte)0x88, (byte)0xcf, 0x4c, (byte)0x8f, (byte)0x86};
byte [] result3 = { (byte)0x9c, (byte)0x59, (byte)0x53, (byte)0xce, (byte)0x94, (byte)0xba, (byte)0xf8, (byte)0x7a};
byte [] result4 = { (byte)0x22, (byte)0xa8, (byte)0x64, (byte)0x09, (byte)0xeb, (byte)0x21, (byte)0x51, (byte)0x23};
String msg1 = "DOCSIS 3.0, fulfilling the need for speed";
String msg2 = "The Magic Words are Squeamish Ossifrages";//"DOCSIS 3.0, fulfilling the need for speed";
byte [] msg3 = { 0x12, 0x01, 0x08 };
byte [] msg4 = { 0x12, 0x01, 0x08, (byte)0x1d, 0x01, 0x01 };
MMH mmh = new MMH(ss1);
byte [] mmhMAC = mmh.digest(msg1.getBytes());
if (MMH.compare(mmhMAC, result1))
System.out.println("MMH MAC64 Output Success!\n" + asHex(mmhMAC) + "\n\n");
else
System.err.println("MMH MAC64 Output doesn't match!\nExpected Result ="
+ asHex(result1, WORD_SIZE) + "\nCalc Result =" + asHex(mmhMAC, WORD_SIZE) + "\n\n");
MMH mmh2 = new MMH(ss2);
byte [] mmhMAC2 = mmh2.digest(msg2.getBytes());
if (MMH.compare(mmhMAC2, result2))
System.out.println("MMH MAC64 Output Success!\n" + asHex(mmhMAC2) + "\n\n");
else
System.err.println("MMH MAC64 Output doesn't match!\nExpected Result ="
+ asHex(result2, WORD_SIZE) + "\nCalc Result =" + asHex(mmhMAC2, WORD_SIZE) + "\n\n");
MMH mmh3 = new MMH(ss3);
byte [] mmhMAC3 = mmh3.digest(msg3);
if (MMH.compare(mmhMAC3, result3))
System.out.println("MMH MAC64 Output Success!\n" + asHex(mmhMAC3) + "\n\n");
else
System.err.println("MMH MAC64 Output doesn't match!\nExpected Result ="
+ asHex(result3, WORD_SIZE) + "\nCalc Result =" + asHex(mmhMAC3, WORD_SIZE) + "\n\n");
MMH mmh4 = new MMH(ss3);
byte [] mmhMAC4 = mmh4.digest(msg4);
if (MMH.compare(mmhMAC4, result4))
System.out.println("MMH MAC64 Output Success!\n" + asHex(mmhMAC4) + "\n\n");
else
System.err.println("MMH MAC64 Output doesn't match!\nExpected Result ="
+ asHex(result4, WORD_SIZE) + "\nCalc Result =" + asHex(mmhMAC4, WORD_SIZE) + "\n\n");
}
public byte[] getMessageInBytes() {
return messageInBytes;
}
public byte [] getmmh() {
byte [] mmhMAC = digest(getMessageInBytes());
return mmhMAC;
}
public void setMessageInBytes(byte[] messageInBytes) {
this.messageInBytes = new byte[messageInBytes.length];
System.arraycopy(messageInBytes, 0, this.messageInBytes, 0, messageInBytes.length);
}
static public void handleException(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
package com.cablelabs.mmh;
import java.security.InvalidKeyException;
/**
* Rijndael --pronounced Reindaal-- is a variable block-size (128-, 192- and
* 256-bit), variable key-size (128-, 192- and 256-bit) symmetric cipher.<p>
*
* Rijndael was written by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
* Rijmen</a> and <a href="mailto:Joan.Daemen@village.uunet.be">Joan Daemen</a>.<p>
*
* Portions of this code are <b>Copyright</b> &copy; 1997, 1998
* <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the
* <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>.
* <br>All rights reserved.<p>
*
* <b>$Revision: $</b>
* @author Raif S. Naffah
* @author Paulo S. L. M. Barreto
*
* Rijndael (pronounced Reindaal) is a block cipher, designed by Joan Daemen and Vincent Rijmen as a candidate algorithm for the AES.
* The cipher has a variable block length and key length. The authors currently specify how to use keys with a length
* of 128, 192, or 256 bits to encrypt blocks with al length of 128, 192 or 256 bits (all nine combinations of
* key length and block length are possible). Both block length and key length can be extended very easily to
* multiples of 32 bits.
* Rijndael can be implemented very efficiently on a wide range of processors and in hardware.
* This implementation is based on the Java Implementation used with the Cryptix toolkit found at:
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael.zip
* Java code authors: Raif S. Naffah, Paulo S. L. M. Barreto
*
* Revisions adaptation for DOCSIS made by:
* @author Garey Hassler
*/
public class Rijndael {
static final int BLOCK_SIZE = 16; // default block size in bytes
static final int[] alog = new int[256];
static final int[] log = new int[256];
static final byte[] S = new byte[256];
static final byte[] Si = new byte[256];
static final int[] T1 = new int[256];
static final int[] T2 = new int[256];
static final int[] T3 = new int[256];
static final int[] T4 = new int[256];
static final int[] T5 = new int[256];
static final int[] T6 = new int[256];
static final int[] T7 = new int[256];
static final int[] T8 = new int[256];
static final int[] U1 = new int[256];
static final int[] U2 = new int[256];
static final int[] U3 = new int[256];
static final int[] U4 = new int[256];
static final byte[] rcon = new byte[30];
static final int[][][] shifts = new int[][][] {
{ {0, 0}, {1, 3}, {2, 2}, {3, 1} },
{ {0, 0}, {1, 5}, {2, 4}, {3, 3} },
{ {0, 0}, {1, 7}, {3, 5}, {4, 4} }
};
private static final char[] HEX_DIGITS = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
static final boolean debug = false;
// Static code - to intialise S-boxes and T-boxes
// ...........................................................................
static {
long time = System.currentTimeMillis();
// System.out.println("Algorithm Name: Rijndael");
// System.out.println("Electronic Codebook (ECB) Mode");
// System.out.println();
int ROOT = 0x11B;
int i, j = 0;
//
// produce log and alog tables, needed for multiplying in the
// field GF(2^m) (generator = 3)
//
alog[0] = 1;
for (i = 1; i < 256; i++) {
j = (alog[i-1] << 1) ^ alog[i-1];
if ((j & 0x100) != 0) j ^= ROOT;
alog[i] = j;
}
for (i = 1; i < 255; i++) log[alog[i]] = i;
byte[][] A = new byte[][] {
{1, 1, 1, 1, 1, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 1, 1, 1},
{1, 1, 0, 0, 0, 1, 1, 1},
{1, 1, 1, 0, 0, 0, 1, 1},
{1, 1, 1, 1, 0, 0, 0, 1}
};
byte[] B = new byte[] { 0, 1, 1, 0, 0, 0, 1, 1};
//
// substitution box based on F^{-1}(x)
//
int t;
byte[][] box = new byte[256][8];
box[1][7] = 1;
for (i = 2; i < 256; i++) {
j = alog[255 - log[i]];
for (t = 0; t < 8; t++)
box[i][t] = (byte)((j >>> (7 - t)) & 0x01);
}
//
// affine transform: box[i] <- B + A*box[i]
//
byte[][] cox = new byte[256][8];
for (i = 0; i < 256; i++)
for (t = 0; t < 8; t++) {
cox[i][t] = B[t];
for (j = 0; j < 8; j++)
cox[i][t] ^= A[t][j] * box[i][j];
}
//
// S-boxes and inverse S-boxes
//
for (i = 0; i < 256; i++) {
S[i] = (byte)(cox[i][0] << 7);
for (t = 1; t < 8; t++)
S[i] ^= cox[i][t] << (7-t);
Si[S[i] & 0xFF] = (byte) i;
}
//
// T-boxes