Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
public interface IAlgorithm {
/**
* Allows the algorithm an opportunity to cleanup any resources.
* This method should always be called when the object will no longer be used.
*/
public void cleanup();
}//IAlgorithm//

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
public interface IAsymmetricAlgorithm extends IAlgorithm, java.io.Externalizable {
/**
* Decrypts data and strips all padding.
* @param data The encrypted data.
* @return The decrypted data.
*/
public byte[] decrypt(byte[] data);
/**
* Decrypts data and strips all padding.
* @param data The buffer containing encrypted data.
* @param dataOffset The index of the first encrypted byte.
* @param dataLength The number of encrypted data bytes.
* @return The decrypted data.
*/
public byte[] decrypt(byte[] data, int dataOffset, int dataLength);
/**
* Decrypts data and strips all padding.
* @param data The buffer containing encrypted data.
* @param dataOffset The index of the first encrypted byte.
* @param dataLength The number of encrypted data bytes.
* @param output A buffer to contain the decrypted data.
* @param outputOffset The location of the first decrypted byte in the output buffer.
* @return The number of bytes decrypted.
*/
public int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
/**
* Encrypts data.
* @param data The unencrypted data.
* @return The encrypted data.
*/
public byte[] encrypt(byte[] data);
/**
* Encrypts data.
* @param data The buffer containing unencrypted data.
* @param dataOffset The index of the first unencrypted byte.
* @param dataLength The number of unencrypted data bytes.
* @return The encrypted data.
*/
public byte[] encrypt(byte[] data, int dataOffset, int dataLength);
/**
* Encrypts data.
* @param data The buffer containing unencrypted data.
* @param dataOffset The index of the first unencrypted byte.
* @param dataLength The number of unencrypted data bytes.
* @param output A buffer to contain the encrypted data.
* @param outputOffset The location of the first encrypted byte in the output buffer.
* @return The number of encrypted bytes (includes formatting and padding).
*/
public int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
/**
* Gets the <strong>exact</strong> number of bytes of encrypted data for the given number of unencrypted bytes.
* @param unencryptedSize The number of unencrypted bytes of data.
* @return The encrypted size.
*/
public int getEncryptedSize(int unencryptedSize);
/**
* Gets the number of bytes in an optimal block of to-be-decrypted data. This allows for efficient streaming of data through the encryption algorithm.
* @return The optimal size of data to be decrypted.
*/
public int getOptimalDecryptionBlockSize();
/**
* Gets the number of bytes in an optimal block of to-be-encrypted data. This allows for efficient streaming of data through the encryption algorithm.
* @return The optimal size of data to be encrypted.
*/
public int getOptimalEncryptionBlockSize();
/**
* Gets the public algorithm used to encrypt data.
* @return The public algorithm which can be used for encrypting.
*/
public IAsymmetricAlgorithm getPublicAsymmetricAlgorithm();
/**
* Gets the public key for this asymmetric algorithm.
* @return The public key which can be used for encrypting.
*/
public Object getPublicKey();
/**
* Gets the public key as a stream of bytes for this asymmetric algorithm.
* @return The public key bytes which can be converted and used for encrypting.
*/
public byte[] getPublicKeyBytes();
/**
* Gets the private key as a stream of bytes for this asymmetric algorithm.
* @return The private key bytes which can be converted and used for encrypting, or null if the algorithm doesn't have a private key.
*/
public byte[] getPrivateKeyBytes();
/**
* Gets the maximum number of bytes of unencrypted data for the given number of encrypted bytes.
* @param unencryptedSize The number of encrypted bytes of data.
* @return The maximum unencrypted size.
*/
public int getUnencryptedSize(int encryptedSize);
}//IAsymmetricAlgorithm//

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
import java.io.IOException;
import com.common.io.IWriter;
/**
* Defines a general hashing algorithm. Derived algorithms are not intended to be thread safe.
*/
public interface IHashAlgorithm extends IAlgorithm, java.io.Externalizable, IWriter {
/**
* Adds the source to the hash.
* @param b The byte to add.
*/
public void add(byte b);
/**
* Adds the source to the hash.
* @param buffer The buffer to pull source from.
*/
public void add(byte[] buffer);
/**
* Adds the source to the hash.
* @param buffer The buffer to pull source from.
* @param bufferOffset The index of the first source byte.
* @param bufferLength The number of source bytes.
*/
public void add(byte[] buffer, int bufferOffset, int bufferLength);
/**
* Adds the source to the hash.
* @param in The input stream containing the source.
*/
public void add(java.io.InputStream in) throws IOException;
/**
* Adds the source to the hash.
* @param source The string to be added to the hash.
*/
public void add(String source);
/**
* Adds the source to the hash.
* @param source The string to be added to the hash.
*/
public void add(char[] source);
/**
* Gets the size of the generated hash.
* @return The number of bytes in every hash.
*/
public int getHashSize();
/**
* Generates a digest for previously provided source.
* @return The digest bytes.
* @see includeSource(byte[])
* @see includeSource(byte[], int, int)
* @see includeSource(java.io.InputStream)
* @see includeSource(String)
*/
public byte[] hash();
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @param sourceOffset The index of the first source byte.
* @param sourceLength The number of source bytes.
* @param hashBuffer The buffer that the hash will be placed in.
* @param hashBufferOffset The index of the first byte of the hash in the buffer.
*/
public void hash(byte[] source, int sourceOffset, int sourceLength, byte[] hashBuffer, int hashBufferOffset);
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @return The hash bytes.
*/
public byte[] hash(String source);
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @param hashBuffer The buffer that the hash will be placed in.
* @param hashBufferOffset The index of the first byte of the hash in the buffer.
*/
public void hash(String source, byte[] hashBuffer, int hashBufferOffset);
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @return The hash bytes.
*/
public byte[] hash(char[] source);
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @param hashBuffer The buffer that the hash will be placed in.
* @param hashBufferOffset The index of the first byte of the hash in the buffer.
*/
public void hash(char[] source, byte[] hashBuffer, int hashBufferOffset);
/**
* Creates a hash string using UTF16 encoding given some source.
* @return The hash bytes in the form of a string (UTF16 encoding).
*/
public String hashToString();
/**
* Creates a hash string using UTF16 encoding given some source.
* @param source The last source to add before hashing.
* @return The hash bytes in the form of a string (UTF16 encoding).
*/
public String hashToString(String source);
/**
* Creates a hash string using UTF16 encoding given some source.
* @param source The last source to add before hashing.
* @return The hash bytes in the form of a string (UTF16 encoding).
*/
public String hashToString(char[] source);
/**
* Creates a hash value given some source.
* @return The hash bytes in the form of a string.
*/
public String hashToHex();
/**
* Creates a hash value given some source.
* @param source The last source to add before hashing.
* @return The hash bytes in the form of a string.
*/
public String hashToHex(String source);
/**
* Resets the algorithm so that it may be used again.
*/
public void reset();
}//IHashAlgorithm//

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
public interface ISignatureAlgorithm extends IAlgorithm, java.io.Externalizable {
/**
* Gets the number of bytes in an optimal block of to-be-signed data. This allows for efficient streaming of data through the signature algorithm.
* @return The optimal size of data to be signed.
*/
public int getOptimalSignatureBlockSize();
/**
* Gets the number of bytes in an optimal block of to-be-verified data. This allows for efficient streaming of data through the signature algorithm.
* @return The optimal size of data to be verified.
*/
public int getOptimalVerificationBlockSize();
/**
* Gets the public algorithm used to verify data.
* @return The public algorithm which can be used for verification.
*/
public ISignatureAlgorithm getPublicSignatureAlgorithm();
/**
* Gets the <strong>exact</strong> number of signed bytes for the given unsigned message size.
* @param unsignedSize The number of unsigned bytes.
* @return The number of signed bytes.
*/
public int getSignedSize(int unsignedSize);
/**
* Gets the maximum number of unsigned bytes for the given signed message size.
* @param unsignedSize The number of signed bytes.
* @return The maximum number of unsigned bytes.
*/
public int getUnsignedSize(int signedSize);
/**
* Gets the public algorithm used for signature verification.
* @return The algorithm used to verify the signatures. This is a publicly accessable algorithm.
*/
public ISignatureAlgorithm getVerifyAlgorithm();
/**
* Gets the public key used for signature verification.
* @return The key used to verify the signatures. This is a publicly accessable key.
*/
public Object getVerifyKey();
/**
* Signs an array of bytes by encrypting them with the private key.
* @param data The input bytes.
* @return The signed (encrypted) data.
* @see #getBlockSize()
*/
public byte[] sign(byte[] data);
/**
* Signs an array of bytes by encrypting them with the private key.
* @param data The input bytes.
* @param dataOffset The offset in the data array to begin encrypting bytes.
* @param dataLength The number of bytes in the data array to encrypt.
* @return The signed (encrypted) data.
* @see #getBlockSize()
*/
public byte[] sign(byte[] data, int dataOffset, int dataLength);
/**
* Signs an array of bytes by encrypting them with the private key and placing them in the supplied buffer.
* <p>Warning: The encrypted byte length will most likely be larger than the unencrypted size.</p>
* @param data The input bytes.
* @param dataOffset The offset in the data array to begin encrypting bytes.
* @param dataLength The number of bytes in the data array to encrypt.
* @param buffer The output bytes.
* @param bufferOffset The offset in the buffer array where the output bytes will begin.
* @return The number of encrypted (signed) bytes placed in the output buffer (includes formatting and padding).
* @see #getBlockSize()
*/
public int sign(byte[] data, int dataOffset, int dataLength, byte[] buffer, int bufferOffset);
/**
* Decrypts an array of bytes using the public key and stores the decrypted bytes in the buffer.
* The output will not include any padding used during encryption.
* <p>NOTE: The number of encrypted data bytes supplied MUST be a multiple of the Block Size (as outputed by the sign method).</p>
* @param data The signed input (encrypted) bytes.
* @return The verify (unencrypted) bytes.
* @see #getBlockSize()
*/
public byte[] verify(byte[] data);
/**
* Decrypts an array of bytes using the public key and stores the decrypted bytes in the buffer.
* The output will not include any padding used during encryption.
* <p>NOTE: The number of encrypted data bytes supplied MUST be a multiple of the Block Size (as outputed by the sign method).</p>
* @param data The signed input (encrypted) bytes.
* @param dataOffset The offset in the data array to begin decrypting bytes.
* @param dataLength The number of bytes in the data array to decrypt.
* @return The verify (unencrypted) bytes.
* @see #getBlockSize()
*/
public byte[] verify(byte[] data, int dataOffset, int dataLength);
/**
* Decrypts an array of bytes using the public key and stores the decrypted bytes in the buffer.
* The output will not include any padding used during encryption.
* <p>NOTE: The number of encrypted data bytes supplied MUST be a multiple of the Block Size (as outputed by the sign method).</p>
* @param data The signed input (encrypted) bytes.
* @param dataOffset The offset in the data array to begin decrypting bytes.
* @param dataLength The number of bytes in the data array to decrypt.
* @param buffer The decrypted output bytes. (This will be filled.)
* @param bufferOffset The offset in the buffer array where the output bytes will begin.
* @return The number of bytes placed in the output buffer.
* @see #getBlockSize()
*/
public int verify(byte[] data, int dataOffset, int dataLength, byte[] buffer, int bufferOffset);
}//ISignatureAlgorithm//

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
public interface ISymmetricAlgorithm extends IAlgorithm, java.io.Externalizable {
/**
* Decrypts the data.
* @param data The input (encrypted) bytes.
* @param dataOffset The offset in the data array to begin decrypting bytes.
* @param dataLength The number of bytes in the data array to decrypt.
* @param output The decrypted output bytes. (This will be filled.)
* @param outputOffset The offset in the buffer array where the output bytes will begin.
* @return The number of bytes written to the output array.
* @see #getBlockSize()
*/
public int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
/**
* Encrypts an array of bytes into the supplied buffer.
* <p>NOTE: The number of data bytes supplied MUST be a multiple of the Block Size. Use random padding to achieve this.
* @param data The input bytes.
* @param dataOffset The offset in the data array to begin encrypting bytes.
* @param dataLength The number of bytes in the data array to encrypt.
* @param output The output bytes.
* @param outputOffset The offset in the buffer array where the output bytes will begin.
* @return The number of bytes written to the output array.
* @see #getBlockSize()
*/
public int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
/**
* Gets the <strong>exact</strong> number of bytes of encrypted data for the given number of unencrypted bytes.
* @param unencryptedSize The number of unencrypted bytes of data.
* @return The encrypted size.
*/
public int getEncryptedSize(int unencryptedSize);
/**
* Gets the size of the symmetric key (in bytes).
* @return The number of bytes in the algorithm's symmetric key.
*/
public int getKeySize();
/**
* Gets the smallest optimal block size for decrypted data.
* @return The maximum size of a single block of decrypted data.
*/
public int getOptimalDecryptionBlockSize();
/**
* Gets the smallest optimal block size for encrypted data.
* @return The maximum size of a single block of encrypted data.
*/
public int getOptimalEncryptionBlockSize();
/**
* Gets the maximum number of bytes of unencrypted data for the given number of encrypted bytes.
* @param unencryptedSize The number of encrypted bytes of data.
* @return The maximum unencrypted size.
*/
public int getUnencryptedSize(int encryptedSize);
}//ISymmetricAlgorithm//

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2002,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
/**
* Encapsulates the generation of simple random numbers.
*/
public class Random extends java.security.SecureRandom {
/**
* Random constructor.
*/
public Random() {
super();
}//Random()//
/**
* Random constructor.
* @param seed The seed for the generator.
*/
public Random(byte[] seed) {
super(seed);
}//Random()//
/**
* Random constructor.
* @param seed The seed for the generator.
*/
public Random(long seed) {
super();
setSeed(seed);
}//Random()//
/**
* Generates the next random byte.
* @return The next byte in the random sequence.
*/
public byte nextByte() {
return (byte) next(8);
}//nextByte()//
/**
* Generates random bytes and places them in a buffer.
* @param buffer The buffer that will contain the random bytes.
* @param offset The offset in the buffer where the random bytes will begin.
* @param length The number of random bytes placed in the buffer.
*/
public synchronized void nextBytes(byte[] buffer, int offset, int length) {
int end = length + offset - 1;
for(int index = offset; index <= end; index++) {
buffer[index] = nextByte();
}//for//
}//nextBytes()//
/**
* Gets the next random digit between 0 & 9.
* @return The next random digit in the sequence.
*/
synchronized public char nextDigit() {
int b;
do {
b = next(4);
} while(b > 9);
return (char) (b + '0');
}//nextDigit()//
/**
* Creates a number along a given interval.
* @param low The lowest allowed value.
* @param high The highest allowed value.
* @return The number on the given interval.
*/
public int nextInt(int low, int high) {
int interval = high - low;
int retVal = 0;
if(interval > 0) {
long random = nextLong();
retVal = (int) Math.abs(random % interval);
retVal += low;
}//if//
else if(interval == 0) {
retVal = low;
}//else if//
else {
throw new RuntimeException("Invalid interval: [" + high + "," + low + "]");
}//else//
return retVal;
}//nextInt()//
}//Random//

View File

@@ -0,0 +1,202 @@
package com.common.security;
import com.common.exception.MethodNotSupportedException;
/**
* This is a Digesting Random Number Generator.
* The original code comes from the BouncyCastle's DigestRandomGenerator, and was modified to use the Sha512 digest only.
* The intent is to use this for generating a random sequence off of a password where the sequence is always the same for the same input.
* The built in SecureRandom class in the JDK is broken on the Mac since it ignores any seed input and won't generate the same sequence for the same seed input.
*/
public class Random2 extends Random {
private static long CYCLE_COUNT = 10;
private long stateCounter;
private long seedCounter;
private Sha512 digest;
private byte[] state;
private byte[] seed;
boolean isInitialized = false;
public Random2() {
this.digest = new Sha512();
this.seed = new byte[digest.getHashSize()];
this.seedCounter = 1;
this.state = new byte[digest.getHashSize()];
this.stateCounter = 1;
}//Random2()//
public void addSeedMaterial(byte[] inSeed) {
synchronized(this) {
if(isInitialized) {
digestUpdate(inSeed);
digestUpdate(seed);
digestDoFinal(seed);
}//if//
}//synchronized//
}//addSeedMaterial()//
public void addSeedMaterial(long rSeed) {
synchronized(this) {
if(isInitialized) {
digestAddCounter(rSeed);
digestUpdate(seed);
digestDoFinal(seed);
}//if//
}//synchronized//
}//addSeedMaterial()//
/* (non-Javadoc)
* @see java.security.SecureRandom#nextBytes(byte[])
*/
public void nextBytes(byte[] bytes) {
nextBytes(bytes, 0, bytes.length);
}//nextBytes()//
/* (non-Javadoc)
* @see com.common.security.Random#nextBytes(byte[], int, int)
*/
public void nextBytes(byte[] bytes, int start, int len) {
synchronized(this) {
int stateOff = 0;
int end;
generateState();
end = start + len;
for(int i = start; i != end; i++) {
if(stateOff == state.length) {
generateState();
stateOff = 0;
}//if//
bytes[i] = state[stateOff++];
}//for//
}//synchronized//
}//nextBytes()//
/* (non-Javadoc)
* @see com.common.security.Random#nextByte()
*/
public byte nextByte() {
synchronized(this) {
generateState();
return state[0];
}//synchronized//
}//nextByte()//
/* (non-Javadoc)
* @see java.security.SecureRandom#generateSeed(int)
*/
public byte[] generateSeed(int numBytes) {
byte[] result = new byte[numBytes];
nextBytes(result, 0, result.length);
return result;
}//generateSeed()//
/* (non-Javadoc)
* @see java.security.SecureRandom#getAlgorithm()
*/
public String getAlgorithm() {
return "DigestRandom/SHA512";
}//getAlgorithm()//
/* (non-Javadoc)
* @see java.security.SecureRandom#setSeed(byte[])
*/
public void setSeed(byte[] seed) {
addSeedMaterial(seed);
}//setSeed()//
/* (non-Javadoc)
* @see java.security.SecureRandom#setSeed(long)
*/
public void setSeed(long seed) {
addSeedMaterial(seed);
}//setSeed()//
/* (non-Javadoc)
* @see java.util.Random#nextBoolean()
*/
public boolean nextBoolean() {
synchronized(this) {
generateState();
return (state[0] & 0x1) > 0;
}//synchronized//
}//nextBoolean()//
/* (non-Javadoc)
* @see java.util.Random#nextDouble()
*/
public double nextDouble() {
throw new MethodNotSupportedException();
}//nextDouble()//
/* (non-Javadoc)
* @see java.util.Random#nextFloat()
*/
public float nextFloat() {
throw new MethodNotSupportedException();
}//nextFloat()//
/* (non-Javadoc)
* @see java.util.Random#nextGaussian()
*/
public synchronized double nextGaussian() {
throw new MethodNotSupportedException();
}//nextGaussian()//
/* (non-Javadoc)
* @see java.util.Random#nextInt()
*/
public int nextInt() {
int result;
synchronized(this) {
generateState();
result = (((int) state[0]) << 24) | (((int) state[0]) << 16) | (((int) state[0]) << 8) | ((int) state[0]);
}//synchronized//
return result;
}//nextInt()//
/* (non-Javadoc)
* @see java.util.Random#nextInt(int)
*/
public int nextInt(int n) {
throw new MethodNotSupportedException();
}//nextInt()//
/* (non-Javadoc)
* @see java.util.Random#nextLong()
*/
public long nextLong() {
long result;
synchronized(this) {
generateState();
result = (((long) state[0]) << 56) | (((long) state[0]) << 56) | (((long) state[0]) << 48) | (((long) state[0]) << 40) | (((long) state[0]) << 32) | (((long) state[0]) << 24) | (((long) state[0]) << 16) | (((long) state[0]) << 8) | ((long) state[0]);
}//synchronized//
return result;
}//nextLong()//
private void cycleSeed() {
digestUpdate(seed);
digestAddCounter(seedCounter++);
digestDoFinal(seed);
}//cycleSeed()//
private void generateState() {
digestAddCounter(stateCounter++);
digestUpdate(state);
digestUpdate(seed);
digestDoFinal(state);
if((stateCounter % CYCLE_COUNT) == 0) {
cycleSeed();
}
}//generateState()//
private void digestAddCounter(long seed) {
for(int i = 0; i != 8; i++) {
digest.add((byte) seed);
seed >>>= 8;
}
}//digestAddCounter()//
private void digestUpdate(byte[] inSeed) {
digest.add(inSeed, 0, inSeed.length);
}//digestUpdate()//
private void digestDoFinal(byte[] result) {
digest.finish(result, 0);
}//digestDoFinal()//
}//Random2//

View File

@@ -0,0 +1,862 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
/*
* TODO: Determine original source.
*/
package com.common.security;
import com.common.debug.*;
import com.common.util.StringSupport;
/*
* An implementation of the Rijndael algorithm for symmetric block encryption.
*/
public class Rijndael implements ISymmetricAlgorithm {
public static final int DEFAULT_KEY_SIZE = 32;
public static final int DEFAULT_BLOCK_SIZE = 16;
private static final int DEFAULT_VIRTUAL_BLOCK_SIZE = 128;
private static final int MINIMUM_PADDING = DEFAULT_VIRTUAL_BLOCK_SIZE / DEFAULT_BLOCK_SIZE + 2; //Includes data size.//
//Static variables to assist in the de/encryption.//
//private 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 int[] T1 = new int[256];
private static final int[] T2 = new int[256];
private static final int[] T3 = new int[256];
private static final int[] T4 = new int[256];
private static final int[] T5 = new int[256];
private static final int[] T6 = new int[256];
private static final int[] T7 = new int[256];
private static final int[] T8 = new int[256];
private static final int[] U1 = new int[256];
private static final int[] U2 = new int[256];
private static final int[] U3 = new int[256];
private static final int[] U4 = new int[256];
private static final int[] alog = new int[256];
private static final int[] log = new int[256];
private static final byte[] S = new byte[256];
private static final byte[] Si = new byte[256];
private static final byte[] rcon = new byte[30];
private Object[] key = null;
private Random random = null;
private byte[] tempBuffer = null;
private int keySize = DEFAULT_KEY_SIZE; //The size (in bits) of the key.//
private int blockSize = DEFAULT_BLOCK_SIZE; //The size (in bytes) of a block of de/encrypted data. This currently cannot be changed.//
//private int virtualBlockSize = DEFAULT_VIRTUAL_BLOCK_SIZE; //The size (in bytes) of a virtual block of data. This is the externally visible block size (minus required padding).//
private int randomByteCounter = 0;
/**
* Setup the static variables.
*/
static {
staticInitialize();
}//static//
/**
* Rijndael constructor.
* The caller must setup a key before using this algorithm.
*/
public Rijndael() {
super();
initialize();
}//Rijndael()//
/**
* Rijndael constructor.
* @param keySize One of the available key sizes.
* @param random The random number generator for the key input. <b>Warning: The mac random number generator (SecureRandom - maybe also Random) does not properly accept the seed value as of jdk 1.6.</b>
*/
public Rijndael(java.util.Random random) {
super();
setupKey(DEFAULT_KEY_SIZE, random);
initialize();
}//Rijndael()//
/**
* Rijndael constructor.
* @param keySize One of the available key sizes.
* @param random The random number generator for the key input. <b>Warning: The mac random number generator (SecureRandom - maybe also Random) does not properly accept the seed value as of jdk 1.6.</b>
*/
public Rijndael(int keySize, java.util.Random random) {
super();
setupKey(keySize, random);
initialize();
}//Rijndael()//
/**
* Rijndael constructor.
* @param keyData The key data used to setup the key. This must be exactly sized to the key size (length == keySize). The only valid lengths are: 16, 24, or 32.
*/
public Rijndael(byte[] keyData) {
super();
setupKey(keyData, 0, keyData.length);
initialize();
}//Rijndael()//
/**
* Rijndael constructor.
* @param keyData The key data used to setup the key.
* @param offset The offset of the first byte of data in the keyData array.
* @param length The number of key data bytes that should be used. This must be exactly sized to the key size (length == keySize). The only valid lengths are: 16, 24, or 32.
*/
public Rijndael(byte[] keyData, int offset, int length) {
super();
setupKey(keyData, offset, length);
initialize();
}//Rijndael()//
/**
* Rijndael constructor.
* <p>Warning: This code fails on the mac - the seed is not properly set on a mac as of Java 1.6.</p>
* @param keyData The key data used to setup the key.
*/
public Rijndael(String keyData) {
super();
setupKey(keyData);
initialize();
}//Rijndael()//
/* (non-Javadoc)
* @see com.common.security.IAlgorithm#cleanup()
*/
public void cleanup() {
}//cleanup()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#decrypt(byte[], int, int, byte[], int)
*/
public int decrypt(byte[] data, int dataOffset, int dataLength, byte[] buffer, int bufferOffset) {
byte[] b = tempBuffer;
int contentSize;
int size;
int bytesWritten = 0;
while(dataLength > 0) {
//Copy the first block of encrypted content.//
System.arraycopy(data, dataOffset, b, 0, b.length);
//Decrypt the first block.//
internalDecrypt(b, b, 0);
//Read the size of the virtual block of content.//
contentSize = (int) (com.common.io.StreamSupport.readShort(b, 0) & 0xFFFF);
//Calculate the size of the block's content.//
size = Math.min(contentSize, b.length - 3);
//Copy the plaintext content to the output buffer.//
System.arraycopy(b, 3, buffer, bufferOffset, size);
bytesWritten += size;
bufferOffset += size;
contentSize -= size;
dataOffset += b.length;
dataLength -= b.length;
//Run through the decryption rounds until all the data has been accounted for.//
while(contentSize > 0) {
//Copy the next block of encrypted content.//
System.arraycopy(data, dataOffset, b, 0, b.length);
//Decrypt the next block.//
internalDecrypt(b, b, 0);
//Calculate the size of the block's content.//
size = Math.min(contentSize, b.length - 1);
//Copy the plaintext content to the output buffer.//
System.arraycopy(b, 1, buffer, bufferOffset, size);
bytesWritten += size;
bufferOffset += size;
contentSize -= size;
dataOffset += b.length;
dataLength -= b.length;
}//while//
}//while//
return bytesWritten;
}//decrypt()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#encrypt(byte[], int, int, byte[], int)
*/
public int encrypt(byte[] inputBuffer, int inputBufferOffset, int inputBufferLength, byte[] outputBuffer, int outputBufferOffset) {
int bytesWritten = 0;
while(inputBufferLength > 0) {
byte[] b = tempBuffer;
int size = Math.min(b.length - 3, inputBufferLength);
short contentSize = (short) Math.min(inputBufferLength, DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING);
//Perform the first encryption round.//
//Transfer the plain text content to the block buffer.//
System.arraycopy(inputBuffer, inputBufferOffset, b, 3, size);
//Write the size of the content (up to the virutal block size).//
com.common.io.StreamSupport.writeShort(contentSize, b, 0);
//Add a random byte.//
b[2] = getRandomByte();
//Pad the buffer with random data.//
for(int i = size + 3; i < b.length; i++) {
b[i] = getRandomByte();
}//for//
//Encrypt the block.//
internalEncrypt(b, outputBuffer, outputBufferOffset);
//Update the indicies.//
outputBufferOffset += b.length;
inputBufferOffset += size;
inputBufferLength -= size;
contentSize -= size;
bytesWritten += b.length;
//Perform following rounds.//
while(contentSize > 0) {
size = Math.min(inputBufferLength, b.length - 1);
//Transfer the plain text content to the block buffer.//
System.arraycopy(inputBuffer, inputBufferOffset, b, 1, size);
//Pad the first byte with random data.//
b[0] = getRandomByte();
//Pad the buffer with random data.//
for(int i = size + 1; i < b.length; i++) {
b[i] = getRandomByte();
}//for//
//Encrypt the block.//
internalEncrypt(b, outputBuffer, outputBufferOffset);
//Update the indicies.//
outputBufferOffset += b.length;
inputBufferOffset += size;
inputBufferLength -= size;
contentSize -= size;
bytesWritten += b.length;
}//while//
}//for//
return bytesWritten;
}//encrypt()//
/**
* Expand a user-supplied key material into a session key.
* <p>WARNING: The keyData length must be 16, 24, or 32 bytes long!
* @param keyData The 128/192/256-bit user-key to use.
*/
private void generateKey(byte[] keyData, int offset, int length) {
int keySize = length;
int ROUNDS = getRounds(keySize, blockSize);
int BC = blockSize / 4;
int[][] Ke = new int[ROUNDS + 1][BC]; //Encryption round keys.//
int[][] Kd = new int[ROUNDS + 1][BC]; //Decryption round keys.//
int ROUND_KEY_COUNT = (ROUNDS + 1) * BC;
int KC = length / 4;
int[] tk = new int[KC];
int i, j;
//Copy user material bytes into temporary ints.//
for(i = 0, j = offset; i < KC;) {
tk[i++] = (keyData[j++] & 0xFF) << 24 | (keyData[j++] & 0xFF) << 16 | (keyData[j++] & 0xFF) << 8 | (keyData[j++] & 0xFF);
}//for//
//Copy values into round key arrays.//
int t = 0;
for(j = 0;(j < KC) && (t < ROUND_KEY_COUNT); j++, t++) {
Ke[t / BC][t % BC] = tk[j];
Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
}//for//
int tt;
int rconpointer = 0;
while(t < ROUND_KEY_COUNT) {
//Extrapolate using phi (the round key evolution function).//
tt = tk[KC - 1];
tk[0] ^= (S[ (tt >>> 16) & 0xFF] & 0xFF) << 24 ^ (S[ (tt >>> 8) & 0xFF] & 0xFF) << 16 ^ (S[tt & 0xFF] & 0xFF) << 8 ^ (S[ (tt >>> 24) & 0xFF] & 0xFF) ^ (rcon[rconpointer++] & 0xFF) << 24;
if(KC != 8) {
for(i = 1, j = 0; i < KC;) {
tk[i++] ^= tk[j++];
}//for//
}//if//
else {
for(i = 1, j = 0; i < KC / 2;) {
tk[i++] ^= tk[j++];
}//for//
tt = tk[KC / 2 - 1];
tk[KC / 2] ^= (S[tt & 0xFF] & 0xFF) ^ (S[ (tt >>> 8) & 0xFF] & 0xFF) << 8 ^ (S[ (tt >>> 16) & 0xFF] & 0xFF) << 16 ^ (S[ (tt >>> 24) & 0xFF] & 0xFF) << 24;
for(j = KC / 2, i = j + 1; i < KC;) {
tk[i++] ^= tk[j++];
}//for//
}//else//
//Copy values into round key arrays.//
for(j = 0;(j < KC) && (t < ROUND_KEY_COUNT); j++, t++) {
Ke[t / BC][t % BC] = tk[j];
Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
}//for//
}//while//
for(int r = 1; r < ROUNDS; r++) {
//Inverse MixColumn where needed.//
for(j = 0; j < BC; j++) {
tt = Kd[r][j];
Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^ U2[(tt >>> 16) & 0xFF] ^ U3[(tt >>> 8) & 0xFF] ^ U4[tt & 0xFF];
}//for//
}//for//
//Assemble the encryption (Ke) and decryption (Kd) round keys into one sessionKey object.//
key = new Object[] {Ke, Kd};
}//generateKey()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#getEncryptedSize(int)
*/
public int getEncryptedSize(int unencryptedSize) {
int virtualBlockCount = ((int) Math.ceil(unencryptedSize / ((float) (DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING))));
int remainingPlainText = unencryptedSize - ((DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING) * (virtualBlockCount - 1));
int blockCount = ((virtualBlockCount - 1) * (DEFAULT_VIRTUAL_BLOCK_SIZE / blockSize)) + ((int) Math.ceil((remainingPlainText + 2) / ((double) (blockSize - 1))));
return blockCount * blockSize;
//return ((int) Math.ceil(unencryptedSize / ((float) (DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING)))) * (DEFAULT_VIRTUAL_BLOCK_SIZE);
}//getEncryptedSize()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#getKeySize()
*/
public int getKeySize() {
return keySize;
}//getKeySize()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#getOptimalDecryptionBlockSize()
*/
public int getOptimalDecryptionBlockSize() {
return DEFAULT_VIRTUAL_BLOCK_SIZE;
}//getOptimalDecryptionBlockSize()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#getOptimalEncryptionBlockSize()
*/
public int getOptimalEncryptionBlockSize() {
return DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING;
}//getOptimalEncryptionBlockSize()//
/**
* Gets the number of rounds for a key and block size combination.
* <p>Wynne::This will be 10, 12, or 14 if the blockSize is 16. The user could also have 24 or 32 byte blocks which would increase the rounds by 2 or 4, not to exceed 14 though. I don't know exactly which combinations are allowed, but I assume they are all allowed.
* @param keySize The size of the user key material in bytes.
* @param blockSize The desired block size in bytes.
* @return The number of rounds that must be performed.
*/
private int getRounds(int keySize, int blockSize) {
switch(keySize) {
case 16 :
return blockSize == 16 ? 10 : (blockSize == 24 ? 12 : 14);
case 24 :
return blockSize != 32 ? 12 : 14;
default : //32 bytes = 256 bits.//
return 14;
}//switch//
}//getRounds()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#getUnencryptedSize(int)
*/
public int getUnencryptedSize(int encryptedSize) {
return (int) Math.ceil(((encryptedSize / (double) DEFAULT_VIRTUAL_BLOCK_SIZE) * (DEFAULT_VIRTUAL_BLOCK_SIZE - MINIMUM_PADDING)) - .5d);
}//getUnencryptedSize()//
/**
* Initializes the Rijndael static variables.
* These variables support the encrypting & decrypting algorithums.
*/
protected void initialize() {
if(tempBuffer == null) {
tempBuffer = new byte[blockSize];
}//if//
if(random == null) {
random = createRandom();
}//if//
}//initialize()//
/**
* Creates a new random number generator.
* @return The random number generator.
*/
protected Random createRandom() {
return new Random();
}//createRandom()//
/**
* Gets a single random byte.
* @return The random byte.
*/
protected byte getRandomByte() {
//Regenerate the random sequence every thousand bytes.//
if(random == null || randomByteCounter++ > 1000) {
random = createRandom();
}//if//
return random.nextByte();
}//getRandomByte()//
/* (non-Javadoc)
* @see com.common.security.ISymmetricAlgorithm#decrypt(byte[], int, int, byte[], int)
*/
private void internalDecrypt(byte[] inputBuffer, byte[] outputBuffer, int outputBufferOffset) {
int[][] kd = (int[][]) key[1]; //Extract decryption round keys.//
int rounds = kd.length - 1;
int[] kdr;
int t0;
int t1;
int t2;
int t3;
int a0;
int a1;
int a2;
int a3;
int tt;
byte[] b = inputBuffer;
byte[] o = outputBuffer;
int s = outputBufferOffset;
kdr = kd[0];
//Combine key data with input data.//
t0 = ((b[0] & 0xFF) << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF)) ^ kdr[0];
t1 = ((b[4] & 0xFF) << 24 | (b[5] & 0xFF) << 16 | (b[6] & 0xFF) << 8 | (b[7] & 0xFF)) ^ kdr[1];
t2 = ((b[8] & 0xFF) << 24 | (b[9] & 0xFF) << 16 | (b[10] & 0xFF) << 8 | (b[11] & 0xFF)) ^ kdr[2];
t3 = ((b[12] & 0xFF) << 24 | (b[13] & 0xFF) << 16 | (b[14] & 0xFF) << 8 | (b[15] & 0xFF)) ^ kdr[3];
//Round transforms.//
for(int round = 1; round < rounds; round++) {
kdr = kd[round];
a0 = (T5[(t0 >>> 24) & 0xFF] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[t1 & 0xFF]) ^ kdr[0];
a1 = (T5[(t1 >>> 24) & 0xFF] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[t2 & 0xFF]) ^ kdr[1];
a2 = (T5[(t2 >>> 24) & 0xFF] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[t3 & 0xFF]) ^ kdr[2];
a3 = (T5[(t3 >>> 24) & 0xFF] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[t0 & 0xFF]) ^ kdr[3];
t0 = a0;
t1 = a1;
t2 = a2;
t3 = a3;
}//for//
//Apply the last round.//
kdr = kd[rounds];
tt = kdr[0];
o[s++] = (byte) (Si[(t0 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (Si[t1 & 0xFF] ^ tt);
tt = kdr[1];
o[s++] = (byte) (Si[(t1 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (Si[t2 & 0xFF] ^ tt);
tt = kdr[2];
o[s++] = (byte) (Si[(t2 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (Si[t3 & 0xFF] ^ tt);
tt = kdr[3];
o[s++] = (byte) (Si[(t3 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (Si[t0 & 0xFF] ^ tt);
}//internalDecrypt()//
/**
* Encrypts one block of data and places it in the supplied output buffer.
* This method currently only accepts a single 16 byte block of input data.
*/
private void internalEncrypt(byte[] inputBuffer, byte[] outputBuffer, int outputBufferOffset) {
int[][] ke = (int[][]) key[0]; //Extract encryption round keys.//
int rounds = ke.length - 1;
int[] ker;
int t0;
int t1;
int t2;
int t3;
int a0;
int a1;
int a2;
int a3;
byte[] b = inputBuffer;
byte[] o = outputBuffer;
int s = outputBufferOffset;
//Initialize the variables.//
ker = ke[0];
//Plaintext to ints + key.//
t0 = ((b[0] & 0xFF) << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF)) ^ ker[0];
t1 = ((b[4] & 0xFF) << 24 | (b[5] & 0xFF) << 16 | (b[6] & 0xFF) << 8 | (b[7] & 0xFF)) ^ ker[1];
t2 = ((b[8] & 0xFF) << 24 | (b[9] & 0xFF) << 16 | (b[10] & 0xFF) << 8 | (b[11] & 0xFF)) ^ ker[2];
t3 = ((b[12] & 0xFF) << 24 | (b[13] & 0xFF) << 16 | (b[14] & 0xFF) << 8 | (b[15] & 0xFF)) ^ ker[3];
//Apply round transforms.//
for(int round = 1; round < rounds; round++) {
ker = ke[round];
a0 = (T1[(t0 >>> 24) & 0xFF] ^ T2[(t1 >>> 16) & 0xFF] ^ T3[(t2 >>> 8) & 0xFF] ^ T4[t3 & 0xFF]) ^ ker[0];
a1 = (T1[(t1 >>> 24) & 0xFF] ^ T2[(t2 >>> 16) & 0xFF] ^ T3[(t3 >>> 8) & 0xFF] ^ T4[t0 & 0xFF]) ^ ker[1];
a2 = (T1[(t2 >>> 24) & 0xFF] ^ T2[(t3 >>> 16) & 0xFF] ^ T3[(t0 >>> 8) & 0xFF] ^ T4[t1 & 0xFF]) ^ ker[2];
a3 = (T1[(t3 >>> 24) & 0xFF] ^ T2[(t0 >>> 16) & 0xFF] ^ T3[(t1 >>> 8) & 0xFF] ^ T4[t2 & 0xFF]) ^ ker[3];
t0 = a0;
t1 = a1;
t2 = a2;
t3 = a3;
}//for//
//Last round is special.//
ker = ke[rounds];
int tt = ker[0];
o[s++] = (byte) (S[(t0 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (S[t3 & 0xFF] ^ tt);
tt = ker[1];
o[s++] = (byte) (S[(t1 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (S[t0 & 0xFF] ^ tt);
tt = ker[2];
o[s++] = (byte) (S[(t2 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (S[t1 & 0xFF] ^ tt);
tt = ker[3];
o[s++] = (byte) (S[(t3 >>> 24) & 0xFF] ^ (tt >>> 24));
o[s++] = (byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
o[s++] = (byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
o[s++] = (byte) (S[t2 & 0xFF] ^ tt);
}//internalEncrypt()//
/**
* A simple test main.
* <p>TODO: Move this into a test suite.</p>
* @param args None required.
*/
public static void main(String[] args) {
Rijndael algorithm = new Rijndael("test");
try {
String text = "The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon. The quick brown fox jumped over the moon.";
byte[] source = text.getBytes("utf8");
//byte[] source = new byte[20];
byte[] encrypted = new byte[algorithm.getEncryptedSize(source.length)];
byte[] decrypted = new byte[source.length];
//Random random = createRandom();
int encryptedSize = 0;
//random.nextBytes(source);
encryptedSize = algorithm.encrypt(source, 0, source.length, encrypted, 0);
algorithm.decrypt(encrypted, 0, encryptedSize, decrypted, 0);
Debug.log("Input: " + text);
Debug.log("Output: " + new String(decrypted, "utf8"));
//Debug.log("1");
}
catch(Throwable e) {
Debug.log(e);
}
{
byte[] source = new byte[] {0, 118, -65, -1, 10, 0, 0, 0, 32, 99, 111, 109, 46, 99, 111, 109};
byte[] encrypted = new byte[source.length];
byte[] decrypted = new byte[source.length];
algorithm.internalEncrypt(source, encrypted, 0);
algorithm.internalDecrypt(encrypted, decrypted, 0);
Debug.log("2");
}
{
byte[] encrypted = new byte[] {16, -82, 10, 87, 6, -112, 46, -64, -39, -72, -23, 114, -12, 31, -49, 106};
byte[] decrypted = new byte[encrypted.length];
algorithm.internalDecrypt(encrypted, decrypted, 0);
Debug.log("3");
}
System.exit(0);
}//main()//
//A really simple main for basic testing.
//public static void main(String[] args) {
// Rijndael alg = new Rijndael(new byte[] {1, 2, 3, 4});
// byte[] b = new byte[16];
// byte[] out = new byte[128];
//
// b[0] = 0;
// b[1] = 118;
// b[2] = 2;
// b[3] = 0;
// b[4] = 0;
// b[5] = 0;
// b[6] = 1;
// b[7] = 0;
// b[8] = 0;
// b[9] = 0;
// b[10] = 45;
// b[11] = 80;
// b[12] = 97;
// b[13] = 114;
// b[14] = 107;
// b[15] = 105;
//
// byte[] orig = new byte[16];
// System.arraycopy(b, 0, orig, 0, 16);
//
// alg.internalEncrypt(b, b, 0);
// alg.internalDecrypt(b, b, 0);
//
// for(int index = 0; index < orig.length; index++) {
// if(b[index] != orig[index]) {
// Debug.log("Error in stream.");
// }
// }
//}
/**
* Multiply two elements of GF(2^m).
* @param a
* @param b
* @return
*/
private static final int mul(int a, int b) {
return (a != 0 && b != 0) ? alog[(log[a & 0xFF] + log[b & 0xFF]) % 255] : 0;
}//mul()//
/**
* Convenience method used in generating Transposition boxes.
* @param a
* @param b
* @return
*/
private static final int mul4(int a, byte[] b) {
if(a == 0) {
return 0;
}//if//
a = log[a & 0xFF];
int a0 = (b[0] != 0) ? alog[(a + log[b[0] & 0xFF]) % 255] & 0xFF : 0;
int a1 = (b[1] != 0) ? alog[(a + log[b[1] & 0xFF]) % 255] & 0xFF : 0;
int a2 = (b[2] != 0) ? alog[(a + log[b[2] & 0xFF]) % 255] & 0xFF : 0;
int a3 = (b[3] != 0) ? alog[(a + log[b[3] & 0xFF]) % 255] & 0xFF : 0;
return a0 << 24 | a1 << 16 | a2 << 8 | a3;
}//mul4()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
key = (Object[]) in.readObject();
blockSize = in.readInt();
keySize = in.readInt();
initialize();
}//readExternal()//
/**
* Sets up the algorithm's key using the supplied data and key size.
* @param buffer The data used to generate a key, or if it is the correct length it will be used as the key.
* @param offset The offset of the first data byte in the buffer.
* @param length The number of data bytes in the buffer. This must be exactly sized to the key size (length == keySize). The only valid lengths are: 16, 24, or 32.
*/
public void setupKey(byte[] buffer, int offset, int length) {
switch(length) {
case 16:
case 24:
case 32:
break;
default:
throw new RuntimeException("Incorrect key length in Rijndael.setupKey(byte[])");
}//switch//
generateKey(buffer, offset, length);
}//setupKey()//
/**
* Creates a session key using the supplied key data.
* @param buffer The data used as the key. This must be exactly sized to the key size (length == keySize). The only valid lengths are: 16, 24, or 32.
*/
public void setupKey(byte[] buffer) {
setupKey(buffer, 0, buffer.length);
}//setupKey()//
/**
* Creates a session key using the supplied key size.
* @param keySize The size of the Rijndael key. The only valid values are: 16, 24, or 32.
* @param random An optional random number generator that will be used by the algorithm.
*/
public void setupKey(int keySize, java.util.Random random) {
byte[] keyData = null;
if(random == null) {
random = createRandom();
}//if//
switch(keySize) {
case 16:
case 24:
case 32:
break;
default:
throw new RuntimeException("Rijndael: Invalid key size.");
}//switch//
keyData = new byte[keySize];
random.nextBytes(keyData);
generateKey(keyData, 0, keyData.length);
}//setupKey()//
/**
* Creates a session key using the supplied key data and key size.
* <p>Warning: This code fails on the mac - the seed is not properly set on a mac as of Java 1.6.</p>
* @param data The data used to generate a key.
* @param keySize The size of the Rijndael key. The only valid values are: 16, 24, or 32.
*/
public void setupKey(String data, int keySize) {
byte[] buffer = new byte[keySize];
Random r = new Random(data.getBytes()); //Note: This doesn't work on the mac. The mac fails to use the input to set the seed.
r.nextBytes(buffer);
setupKey(buffer, 0, buffer.length);
}//setupKey()//
/**
* Creates a session key using the supplied key data and the default key size.
* <p>Warning: This code fails on the mac - the seed is not properly set on a mac as of Java 1.6.</p>
* @param data The data used to generate a key.
*/
public void setupKey(String keyData) {
setupKey(keyData, DEFAULT_KEY_SIZE);
}//setupKey()//
/**
* Initializes the Rijndael static variables.
* These variables support the encrypting & decrypting algorithums.
*/
protected static void staticInitialize() {
int ROOT = 0x11B;
int i = 0;
int j = 0;
int r = 1;
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};
int t;
byte[][] box = new byte[256][8]; //Substitution Box (based on F^{-1}(x))//
byte[][] cox = new byte[256][8]; //Affine Transform (box[i] <- B + A*box[i])//
byte[][] G = new byte[][] {{2, 1, 1, 3}, {3, 2, 1, 1}, {1, 3, 2, 1}, {1, 1, 3, 2}}; //T-boxes.//
byte[][] AA = new byte[4][8]; //T-boxes.//
byte pivot;
byte tmp;
byte[][] iG = new byte[4][4];
alog[0] = 1;
for(i = 1; i < 256; i++) {
j = (alog[i - 1] << 1) ^ alog[i - 1];
if((j & 0x100) != 0) {
j ^= ROOT;
}//if//
alog[i] = j;
}//for//
for(i = 1; i < 255; i++) {
log[alog[i]] = i;
}//for//
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);
}//for//
}//for//
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];
}//for//
}//for//
}//for//
for(i = 0; i < 256; i++) {
S[i] = (byte) (cox[i][0] << 7); //S-boxes.//
for (t = 1; t < 8; t++) {
S[i] ^= cox[i][t] << (7 - t); //S-boxes.//
}//for//
Si[S[i] & 0xFF] = (byte) i; //Inverse S-boxes.//
}//for//
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
AA[i][j] = G[i][j];
}//for//
AA[i][i + 4] = 1;
}//for//
for(i = 0; i < 4; i++) {
pivot = AA[i][i];
if(pivot == 0) {
t = i + 1;
while((AA[t][i] == 0) && (t < 4)) {
t++;
}//while//
if(t == 4) {
throw new RuntimeException("G matrix is not invertible");
}//if//
else {
for(j = 0; j < 8; j++) {
tmp = AA[i][j];
AA[i][j] = AA[t][j];
AA[t][j] = (byte) tmp;
}//for//
pivot = AA[i][i];
}//else//
}//if//
for(j = 0; j < 8; j++) {
if(AA[i][j] != 0) {
AA[i][j] = (byte) alog[ (255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
}//if//
}//for//
for(t = 0; t < 4; t++) {
if(i != t) {
for(j = i + 1; j < 8; j++) {
AA[t][j] ^= mul(AA[i][j], AA[t][i]);
}//for//
AA[t][i] = 0;
}//if//
}//for//
}//for//
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
iG[i][j] = AA[i][j + 4];
}//for//
}//for//
for(t = 0; t < 256; t++) {
int s = S[t];
T1[t] = mul4(s, G[0]);
T2[t] = mul4(s, G[1]);
T3[t] = mul4(s, G[2]);
T4[t] = mul4(s, G[3]);
s = Si[t];
T5[t] = mul4(s, iG[0]);
T6[t] = mul4(s, iG[1]);
T7[t] = mul4(s, iG[2]);
T8[t] = mul4(s, iG[3]);
U1[t] = mul4(t, iG[0]);
U2[t] = mul4(t, iG[1]);
U3[t] = mul4(t, iG[2]);
U4[t] = mul4(t, iG[3]);
}//for//
rcon[0] = 1;
for(t = 1; t < 30;) {
rcon[t++] = (byte) (r = mul(2, r)); //Round constants.//
}//for//
}//staticInitialize()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
out.writeObject(key);
out.writeInt(blockSize);
out.writeInt(keySize);
}//writeExternal()//
}//Rijndael//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
import java.io.IOException;
import java.io.InputStream;
import com.common.util.StringSupport;
/**
* TODO: Determine original source.
*/
public class Sha1 implements IHashAlgorithm {
/** The size of a hash in bytes. */
private static final int HASH_SIZE = 20;
/** The size of a hash in ints. */
private static final int INT_HASH_SIZE = HASH_SIZE >> 2;
/** The size of a block of source to be hashed (in bytes). */
private static final int BLOCK_SIZE = 64;
/** The size of a block of source to be hashed (in ints). */
private static final int INT_BLOCK_SIZE = BLOCK_SIZE >> 2;
/** The total source size. */
private long sourceSize;
/**
* A buffer containing the bytes yet to be added to the digest.
* This buffer will always be DATA_LENGTH in size and the digest will be updated when it is filled (so that this buffer can be emptied and reused).
*/
private byte[] sourceBuffer;
private int sourceBufferLength;
/**
* The digest integers as an array.
* This is where the digest actually gets stored until the hash has completely finished and the digest bytes are given to the user.
*/
private int[] hashBuffer;
private int[] internalHashBuffer;
private int[] internalBuffer;
/**
* Constructs SHA-1 algorithm used to generate digests from source data.
*/
public Sha1() {
initialize();
}//Sha1)//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte)
*/
public void write(byte b) {
add(b);
}//write()//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte[], int, int)
*/
public void write(byte[] bytes, int offset, int length) {
add(bytes, offset, length);
}//write()//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte[])
*/
public void write(byte[] bytes) {
add(bytes);
}//write()//
/**
* Sha1 copy constructor.
* @param algorithm The algorithm to be copied.
*/
private Sha1(Sha1 algorithm) {
sourceSize = algorithm.sourceSize;
sourceBufferLength = algorithm.sourceBufferLength;
sourceBuffer = (byte[]) algorithm.sourceBuffer.clone();
internalHashBuffer = (int[]) algorithm.internalHashBuffer.clone();
hashBuffer = (int[]) algorithm.hashBuffer.clone();
internalBuffer = (int[]) algorithm.internalBuffer.clone();
}//Sha1()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte)
*/
public void add(byte b) {
sourceSize++;
sourceBuffer[sourceBufferLength++] = b;
if(sourceBufferLength == BLOCK_SIZE) {
//Transform the bytes into integers.//
convert(sourceBuffer, 0, internalHashBuffer, 0, INT_BLOCK_SIZE);
//Update the hash.//
transform(internalHashBuffer);
sourceBufferLength = 0;
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte[])
*/
public void add(byte[] buffer) {
if(buffer != null && buffer.length > 0) {
add(buffer, 0, buffer.length);
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte[], int, int)
*/
public void add(byte[] buffer, int bufferOffset, int bufferLength) {
if(bufferLength > 0) {
int size = 0;
sourceSize += bufferLength;
//Hash the source in blocks.//
while((size = BLOCK_SIZE - sourceBufferLength) <= bufferLength) {
//Fill the source buffer.//
System.arraycopy(buffer, bufferOffset, sourceBuffer, sourceBufferLength, size);
//Transform the bytes into integers.//
convert(sourceBuffer, 0, internalHashBuffer, 0, INT_BLOCK_SIZE);
//Update the hash.//
transform(internalHashBuffer);
bufferLength -= size;
bufferOffset += size;
sourceBufferLength = 0;
}//while//
if(bufferLength > 0) {
//Save partial source in the source buffer.//
System.arraycopy(buffer, bufferOffset, sourceBuffer, sourceBufferLength, bufferLength);
sourceBufferLength += bufferLength;
}//if//
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(java.io.InputStream)
*/
public void add(InputStream in) throws IOException {
byte[] buffer = new byte[10000];
int readCount = 0;
while(readCount >= 0) {
readCount = in.read(buffer);
if(readCount > 0) {
add(buffer, 0, readCount);
}//if//
}//while//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(String)
*/
public void add(String source) {
if(source != null && source.length() > 0) {
add(StringSupport.toUtf8Bytes(source));
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(char[])
*/
public void add(char[] source) {
if(source != null && source.length > 0) {
add(StringSupport.toUtf8Bytes(source));
}//if//
}//add()//
/**
* Adds the last of the source to the hash. At the very least this adds the source size to the hash.
*/
private void addFinal() {
int position = sourceBufferLength;
long bitCount;
sourceBuffer[position++] = (byte) 0x80;
//Add remaining source to the hash.//
if(position > BLOCK_SIZE - 8) {
//Add trailing zeros.//
while(position < BLOCK_SIZE) {
sourceBuffer[position++] = 0;
}//while//
convert(sourceBuffer, 0, internalHashBuffer, 0, INT_BLOCK_SIZE);
transform(internalHashBuffer);
position = 0;
}//if//
//Clear the end of the source buffer.//
for(int i = position; i < BLOCK_SIZE - 8; i ++) {
sourceBuffer[i] = 0;
}//for//
convert(sourceBuffer, 0, internalHashBuffer, 0, INT_BLOCK_SIZE);
//Add the message size to the hash.//
bitCount = sourceSize << 3;
internalHashBuffer[INT_BLOCK_SIZE - 2] = (int) (bitCount >>> 32);
internalHashBuffer[INT_BLOCK_SIZE - 1] = (int) bitCount;
transform(internalHashBuffer);
}//addFinal()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#cleanup()
*/
public void cleanup() {
}//cleanup()//
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
public Object clone() {
return new Sha1(this);
}//clone()//
/**
* Converts bytes into integers.
*/
private void convert(byte[] source, int sourceOffset, int[] destination, int destinationOffset, int destinationLength) {
while(destinationLength-- > 0) {
//Big Endian//
destination[destinationOffset++] = (source[sourceOffset++] << 24) | ((source[sourceOffset++] & 0xFF) << 16) | ((source[sourceOffset++] & 0xFF) << 8) | (source[sourceOffset++] & 0xFF);
}//while//
}//convert()//
/**
* Transform 1.
*/
private int f1(int a, int b, int c) {
return (c ^ (a & (b ^ c))) + 0x5A827999;
}//f1()//
/**
* Transform 2.
*/
private int f2(int a, int b, int c) {
return (a ^ b ^ c) + 0x6ED9EBA1;
}//f2()//
/**
* Transform 3.
*/
private int f3(int a, int b, int c) {
return ((a & b) | (c & (a | b))) + 0x8F1BBCDC;
}//f3()//
/**
* Transform 4.
*/
private int f4(int a, int b, int c) {
return (a ^ b ^ c) + 0xCA62C1D6;
}//f4()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#getHashSize()
*/
public int getHashSize() {
return HASH_SIZE;
}//getHashSize()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash()
*/
public byte[] hash() {
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(byte[], int, int)
*/
public byte[] hash(byte[] source, int sourceOffset, int sourceLength) {
add(source, sourceOffset, sourceLength);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(byte[], int, int, byte[], int)
*/
public void hash(byte[] source, int sourceOffset, int sourceLength, byte[] hashBuffer, int hashBufferOffset) {
add(source, sourceOffset, sourceLength);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(String)
*/
public byte[] hash(String source) {
add(source);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(String, byte[], int)
*/
public void hash(String source, byte[] hashBuffer, int hashBufferOffset) {
add(source);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(char[])
*/
public byte[] hash(char[] source) {
add(source);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(char[], byte[], int)
*/
public void hash(char[] source, byte[] hashBuffer, int hashBufferOffset) {
add(source);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString()
*/
public String hashToString() {
return hashToString((String) null);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString(String)
*/
public String hashToString(String source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.fromUnicode16Bytes(hashBuffer, 0, hashBuffer.length);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString(char[])
*/
public String hashToString(char[] source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.fromUnicode16Bytes(hashBuffer, 0, hashBuffer.length);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToHex()
*/
public String hashToHex() {
return hashToHex(null);
}//hashToHex()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToHex(String)
*/
public String hashToHex(String source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.toHexString(hashBuffer, 0, hashBuffer.length);
}//hashToHex()//
/**
* Initializes the hash algorithm.
*/
private void initialize() {
//Initialize the buffers.//
sourceBuffer = new byte[BLOCK_SIZE];
hashBuffer = new int[INT_HASH_SIZE];
internalHashBuffer = new int[INT_BLOCK_SIZE];
internalBuffer = new int[80];
reset(); //Prepare the algorithm for its first hash.//
}//initialize()//
/**
* Creates a hash of the previously supplied source.
* @return The hash bytes.
*/
protected byte[] internalHash() {
byte[] buffer = new byte[HASH_SIZE];
internalHash(buffer, 0);
return buffer;
}//internalHash()//
/**
* Creates a hash of the previously supplied source.
* @param hashBuffer The buffer to place the hash in.
* @param hashBufferOffset The index of the first hash byte.
*/
protected void internalHash(byte[] hashBuffer, int hashBufferOffset) {
//Add any final source into the mix.//
addFinal();
//Copy the hash into the result buffer in Big Endian format.//
for(int i = 0; i < INT_HASH_SIZE; ++i) {
int value = this.hashBuffer[i];
hashBuffer[hashBufferOffset++] = (byte) (value >>> 24);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 16);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 8);
hashBuffer[hashBufferOffset++] = (byte) value;
}//for//
//Reset the algorithm.//
reset();
}//internalHash()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#reset()
*/
public void reset() {
sourceBufferLength = 0;
sourceSize = 0;
hashBuffer[0] = 0x67452301;
hashBuffer[1] = 0xEFCDAB89;
hashBuffer[2] = 0x98BADCFE;
hashBuffer[3] = 0x10325476;
hashBuffer[4] = 0xC3D2E1F0;
}//reset()//
/**
* The SHA-1 transform method which maintains the current hashBuffer by adding/transforming blocks of source data.
* @param data The integers containing the source data to be added to the current hashBuffer.
*/
private void transform(int[] data) {
int a = hashBuffer[0];
int b = hashBuffer[1];
int c = hashBuffer[2];
int d = hashBuffer[3];
int e = hashBuffer[4];
int[] w = internalBuffer;
for (int i = 0; i < 16; i++) {
w[i] = data[i];
}//for//
for(int i = 16; i < 80; i++) {
int j = w[i - 16] ^ w[i - 14] ^ w[i - 8] ^ w[i - 3];
w[i] = j;
w[i] = (j << 1) | (j >>> -1);
}//for//
e += ((a << 5) | (a >>> -5)) + f1(b, c, d) + w[0];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f1(a, b, c) + w[1];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f1(e, a, b) + w[2];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f1(d, e, a) + w[3];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f1(c, d, e) + w[4];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f1(b, c, d) + w[5];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f1(a, b, c) + w[6];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f1(e, a, b) + w[7];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f1(d, e, a) + w[8];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f1(c, d, e) + w[9];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f1(b, c, d) + w[10];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f1(a, b, c) + w[11];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f1(e, a, b) + w[12];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f1(d, e, a) + w[13];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f1(c, d, e) + w[14];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f1(b, c, d) + w[15];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f1(a, b, c) + w[16];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f1(e, a, b) + w[17];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f1(d, e, a) + w[18];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f1(c, d, e) + w[19];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f2(b, c, d) + w[20];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f2(a, b, c) + w[21];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f2(e, a, b) + w[22];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f2(d, e, a) + w[23];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f2(c, d, e) + w[24];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f2(b, c, d) + w[25];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f2(a, b, c) + w[26];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f2(e, a, b) + w[27];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f2(d, e, a) + w[28];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f2(c, d, e) + w[29];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f2(b, c, d) + w[30];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f2(a, b, c) + w[31];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f2(e, a, b) + w[32];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f2(d, e, a) + w[33];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f2(c, d, e) + w[34];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f2(b, c, d) + w[35];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f2(a, b, c) + w[36];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f2(e, a, b) + w[37];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f2(d, e, a) + w[38];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f2(c, d, e) + w[39];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f3(b, c, d) + w[40];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f3(a, b, c) + w[41];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f3(e, a, b) + w[42];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f3(d, e, a) + w[43];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f3(c, d, e) + w[44];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f3(b, c, d) + w[45];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f3(a, b, c) + w[46];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f3(e, a, b) + w[47];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f3(d, e, a) + w[48];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f3(c, d, e) + w[49];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f3(b, c, d) + w[50];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f3(a, b, c) + w[51];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f3(e, a, b) + w[52];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f3(d, e, a) + w[53];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f3(c, d, e) + w[54];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f3(b, c, d) + w[55];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f3(a, b, c) + w[56];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f3(e, a, b) + w[57];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f3(d, e, a) + w[58];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f3(c, d, e) + w[59];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f4(b, c, d) + w[60];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f4(a, b, c) + w[61];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f4(e, a, b) + w[62];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f4(d, e, a) + w[63];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f4(c, d, e) + w[64];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f4(b, c, d) + w[65];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f4(a, b, c) + w[66];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f4(e, a, b) + w[67];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f4(d, e, a) + w[68];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f4(c, d, e) + w[69];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f4(b, c, d) + w[70];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f4(a, b, c) + w[71];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f4(e, a, b) + w[72];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f4(d, e, a) + w[73];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f4(c, d, e) + w[74];
c = ((c << 30) | (c >>> -30));
e += ((a << 5) | (a >>> -5)) + f4(b, c, d) + w[75];
b = ((b << 30) | (b >>> -30));
d += ((e << 5) | (e >>> -5)) + f4(a, b, c) + w[76];
a = ((a << 30) | (a >>> -30));
c += ((d << 5) | (d >>> -5)) + f4(e, a, b) + w[77];
e = ((e << 30) | (e >>> -30));
b += ((c << 5) | (c >>> -5)) + f4(d, e, a) + w[78];
d = ((d << 30) | (d >>> -30));
a += ((b << 5) | (b >>> -5)) + f4(c, d, e) + w[79];
c = ((c << 30) | (c >>> -30));
hashBuffer[0] += a;
hashBuffer[1] += b;
hashBuffer[2] += c;
hashBuffer[3] += d;
hashBuffer[4] += e;
}//transform()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//Sha1//

View File

@@ -0,0 +1,530 @@
/*
* Copyright (c) 2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.security;
import java.io.IOException;
import java.io.InputStream;
import com.common.util.StringSupport;
/*
* Used the SHA512 specs and the Bouncy Castle LongDigest implementation as guides.
* <p>The point of having this in the framework isn't to be different, but rather to cut out all the dependancies and make the hash super easy to be used in application code without extra lines in the classpath or consideration to licensing.</p>
*/
public class Sha512 implements IHashAlgorithm {
/** Constants */
private static final long K[] = {
0x428A2F98D728AE22L, 0x7137449123EF65CDL, 0xB5C0FBCFEC4D3B2FL, 0xE9B5DBA58189DBBCL,
0x3956C25BF348B538L, 0x59F111F1B605D019L, 0x923F82A4AF194F9BL, 0xAB1C5ED5DA6D8118L,
0xD807AA98A3030242L, 0x12835B0145706FBEL, 0x243185BE4EE4B28CL, 0x550C7DC3D5FFB4E2L,
0x72BE5D74F27B896FL, 0x80DEB1FE3B1696B1L, 0x9BDC06A725C71235L, 0xC19BF174CF692694L,
0xE49B69C19EF14AD2L, 0xEFBE4786384F25E3L, 0x0FC19DC68B8CD5B5L, 0x240CA1CC77AC9C65L,
0x2DE92C6F592B0275L, 0x4A7484AA6EA6E483L, 0x5CB0A9DCBD41FBD4L, 0x76F988DA831153B5L,
0x983E5152EE66DFABL, 0xA831C66D2DB43210L, 0xB00327C898FB213FL, 0xBF597FC7BEEF0EE4L,
0xC6E00BF33DA88FC2L, 0xD5A79147930AA725L, 0x06CA6351E003826FL, 0x142929670A0E6E70L,
0x27B70A8546D22FFCL, 0x2E1B21385C26C926L, 0x4D2C6DFC5AC42AEDL, 0x53380D139D95B3DFL,
0x650A73548BAF63DEL, 0x766A0ABB3C77B2A8L, 0x81C2C92E47EDAEE6L, 0x92722C851482353BL,
0xA2BFE8A14CF10364L, 0xA81A664BBC423001L, 0xC24B8B70D0F89791L, 0xC76C51A30654BE30L,
0xD192E819D6EF5218L, 0xD69906245565A910L, 0xF40E35855771202AL, 0x106AA07032BBD1B8L,
0x19A4C116B8D2D0C8L, 0x1E376C085141AB53L, 0x2748774CDF8EEB99L, 0x34B0BCB5E19B48A8L,
0x391C0CB3C5C95A63L, 0x4ED8AA4AE3418ACBL, 0x5B9CCA4F7763E373L, 0x682E6FF3D6B2B8A3L,
0x748F82EE5DEFB2FCL, 0x78A5636F43172F60L, 0x84C87814A1F0AB72L, 0x8CC702081A6439ECL,
0x90BEFFFA23631E28L, 0xA4506CEBDE82BDE9L, 0xBEF9A3F7B2C67915L, 0xC67178F2E372532BL,
0xCA273ECEEA26619CL, 0xD186B8C721C0C207L, 0xEADA7DD6CDE0EB1EL, 0xF57D4F7FEE6ED178L,
0x06F067AA72176FBAL, 0x0A637DC5A2C898A6L, 0x113F9804BEF90DAEL, 0x1B710B35131C471BL,
0x28DB77F523047D84L, 0x32CAAB7B40C72493L, 0x3C9EBE0A15C9BEBCL, 0x431D67C49C100D4CL,
0x4CC5D4BECB3E42B6L, 0x597F299CFC657E2AL, 0x5FCB6FAB3AD6FAECL, 0x6C44198C4A475817L
};
/** The size of a resulting hash in bytes (8 longs used to store the hash * 8 bytes per long). */
private static final int HASH_SIZE = 64;
/** The size of a block of source to be hashed (in bytes). (16 longs store a block of unhashed data, 8 bytes per long.) */
private static final int BLOCK_SIZE = 128;
/** The source size. */
private long sourceSize;
/** The overflow source size. */
private long sourceSize2;
/**
* A buffer containing the bytes yet to be added to the digest.
* This buffer will always be DATA_LENGTH in size and the digest will be updated when it is filled (so that this buffer can be emptied and reused).
*/
private byte[] sourceBuffer;
private int sourceBufferLength;
/**
* The digest integers as an array.
* This is where the digest actually gets stored until the hash has completely finished and the digest bytes are given to the user.
*/
private long[] hashBuffer;
private long[] internalHashBuffer;
private long[] internalBuffer;
/**
* Constructs SHA-512 algorithm used to generate digests from source data.
*/
public Sha512() {
initialize();
}//Sha512()//
/**
* Sha512 copy constructor.
* @param algorithm The algorithm to be copied.
*/
private Sha512(Sha512 algorithm) {
sourceSize = algorithm.sourceSize;
sourceSize2 = algorithm.sourceSize2;
sourceBufferLength = algorithm.sourceBufferLength;
sourceBuffer = (byte[]) algorithm.sourceBuffer.clone();
internalHashBuffer = (long[]) algorithm.internalHashBuffer.clone();
hashBuffer = (long[]) algorithm.hashBuffer.clone();
internalBuffer = (long[]) algorithm.internalBuffer.clone();
}//Sha512()//
/**
* Initializes the hash algorithm.
*/
private void initialize() {
//Initialize the buffers.//
sourceBuffer = new byte[BLOCK_SIZE];
hashBuffer = new long[8];
internalHashBuffer = new long[BLOCK_SIZE/8];
internalBuffer = new long[80];
reset(); //Prepare the algorithm for its first hash.//
}//initialize()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#reset()
*/
public void reset() {
sourceBufferLength = 0;
sourceSize = 0;
sourceSize2 = 0;
hashBuffer[0] = 0x6A09E667F3BCC908L;
hashBuffer[1] = 0xBB67AE8584CAA73BL;
hashBuffer[2] = 0x3C6EF372FE94F82BL;
hashBuffer[3] = 0xA54FF53A5F1D36F1L;
hashBuffer[4] = 0x510E527FADE682D1L;
hashBuffer[5] = 0x9B05688C2B3E6C1FL;
hashBuffer[6] = 0x1F83D9ABFB41BD6BL;
hashBuffer[7] = 0x5BE0CD19137E2179L;
}//reset()//
/**
* Manages overflowing the source size into a second long value.
*/
private void updateSourceSize() {
//Check if we have to use the overflow source size.//
//Note: We always clear the last 3 bits because we will multiply the source size by 8 to get a bit count when finishing the hash.//
if(sourceSize > 0x1FFFFFFFFFFFFFFFL) {
//Add the top 3 bits to the overflow source size.//
sourceSize2 += (sourceSize >>> 61);
//Clear the top 3 bits of the source size.//
sourceSize &= 0x1FFFFFFFFFFFFFFFL;
}//if//
}//updateSourceSize()//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte)
*/
public void write(byte b) {
add(b);
}//write()//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte[], int, int)
*/
public void write(byte[] bytes, int offset, int length) {
add(bytes, offset, length);
}//write()//
/* (non-Javadoc)
* @see com.common.io.IWriter#write(byte[])
*/
public void write(byte[] bytes) {
add(bytes);
}//write()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte)
*/
public void add(byte b) {
sourceSize++;
sourceBuffer[sourceBufferLength++] = b;
if(sourceBufferLength == BLOCK_SIZE) {
//Transform the bytes into longs.//
convert(sourceBuffer, 0, internalHashBuffer);
//Update the hash.//
transform(internalHashBuffer);
sourceBufferLength = 0;
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte[])
*/
public void add(byte[] buffer) {
if(buffer != null && buffer.length > 0) {
add(buffer, 0, buffer.length);
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(byte[], int, int)
*/
public void add(byte[] buffer, int bufferOffset, int bufferLength) {
if(bufferLength > 0) {
int size = 0;
sourceSize += bufferLength;
//Hash the source in blocks.//
while((size = BLOCK_SIZE - sourceBufferLength) <= bufferLength) {
//Fill the source buffer.//
System.arraycopy(buffer, bufferOffset, sourceBuffer, sourceBufferLength, size);
//Transform the bytes into longs.//
convert(sourceBuffer, 0, internalHashBuffer);
//Update the hash.//
transform(internalHashBuffer);
bufferLength -= size;
bufferOffset += size;
sourceBufferLength = 0;
}//while//
if(bufferLength > 0) {
//Save partial source in the source buffer.//
System.arraycopy(buffer, bufferOffset, sourceBuffer, sourceBufferLength, bufferLength);
sourceBufferLength += bufferLength;
}//if//
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(java.io.InputStream)
*/
public void add(InputStream in) throws IOException {
byte[] buffer = new byte[10000];
int readCount = 0;
while(readCount >= 0) {
readCount = in.read(buffer);
if(readCount > 0) {
add(buffer, 0, readCount);
}//if//
}//while//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(String)
*/
public void add(String source) {
if(source != null && source.length() > 0) {
add(StringSupport.toUtf8Bytes(source));
}//if//
}//add()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#add(char[])
*/
public void add(char[] source) {
if(source != null && source.length > 0) {
add(StringSupport.toUtf8Bytes(source));
}//if//
}//add()//
/**
* Adds the last of the source to the hash. At the very least this adds the source size to the hash.
*/
private void addFinal() {
int position = sourceBufferLength;
sourceBuffer[position++] = (byte) 0x80;
//If there isn't room for two more longs (the message size in # of bits), then process the source block with zero's padding the end.//
if(position > BLOCK_SIZE - 16) {
//Add trailing zeros.//
while(position < BLOCK_SIZE) {
sourceBuffer[position++] = 0;
}//while//
convert(sourceBuffer, 0, internalHashBuffer);
transform(internalHashBuffer);
position = 0;
}//if//
//Pad all but the last 2 long values of the buffers.//
for(int i = position; i < BLOCK_SIZE - 16; i ++) {
sourceBuffer[i] = 0;
}//for//
//Convert the source bytes to longs.//
convert(sourceBuffer, 0, internalHashBuffer);
updateSourceSize();
//Add the message size to the longs.//
internalHashBuffer[internalHashBuffer.length - 2] = sourceSize2;
internalHashBuffer[internalHashBuffer.length - 1] = sourceSize << 3;
//Run the final transform.//
transform(internalHashBuffer);
}//addFinal()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#cleanup()
*/
public void cleanup() {
}//cleanup()//
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
public Object clone() {
return new Sha512(this);
}//clone()//
/**
* Convers bytes into longs.
*/
private void convert(byte[] source, int sourceOffset, long[] destination) {
int destinationOffset = 0;
int destinationLength = destination.length;
while(destinationLength-- > 0) {
//Big Endian//
destination[destinationOffset++] = ((long) (source[sourceOffset++] & 0xFF) << 56) | ((long) (source[sourceOffset++] & 0xFF) << 48) | ((long) (source[sourceOffset++] & 0xFF) << 40) | ((long) (source[sourceOffset++] & 0xFF) << 32) | ((long) (source[sourceOffset++] & 0xFF) << 24) | ((long) (source[sourceOffset++] & 0xFF) << 16) | ((long) (source[sourceOffset++] & 0xFF) << 8) | (source[sourceOffset++] & 0xFF);
}//while//
}//convert()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#getHashSize()
*/
public int getHashSize() {
return HASH_SIZE;
}//getHashSize()//
/**
* Performs the final hash using a custom buffer. This is the same as the hash() methods, but allows reuse of the buffer.
* @param hash The buffer to place the hash in. Must have space for the hash size.
* @param offset The offset in the hash array where the first hash byte will be placed.
*/
public void finish(byte[] hash, int offset) {
if(hash.length - offset < HASH_SIZE) {
throw new IllegalArgumentException();
}//if//
internalHash(hash, 0);
}//finish()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash()
*/
public byte[] hash() {
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(byte[], int, int)
*/
public byte[] hash(byte[] source, int sourceOffset, int sourceLength) {
add(source, sourceOffset, sourceLength);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(byte[], int, int, byte[], int)
*/
public void hash(byte[] source, int sourceOffset, int sourceLength, byte[] hashBuffer, int hashBufferOffset) {
add(source, sourceOffset, sourceLength);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(String)
*/
public byte[] hash(String source) {
add(source);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(String, byte[], int)
*/
public void hash(String source, byte[] hashBuffer, int hashBufferOffset) {
add(source);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(char[])
*/
public byte[] hash(char[] source) {
add(source);
return internalHash();
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hash(char[], byte[], int)
*/
public void hash(char[] source, byte[] hashBuffer, int hashBufferOffset) {
add(source);
internalHash(hashBuffer, hashBufferOffset);
}//hash()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString()
*/
public String hashToString() {
return hashToString((String) null);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString(String)
*/
public String hashToString(String source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.fromUnicode16Bytes(hashBuffer, 0, hashBuffer.length);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToString(char[])
*/
public String hashToString(char[] source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.fromUnicode16Bytes(hashBuffer, 0, hashBuffer.length);
}//hashToString()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToHex()
*/
public String hashToHex() {
return hashToHex(null);
}//hashToHex()//
/* (non-Javadoc)
* @see com.common.security.IHashAlgorithm#hashToHex(String)
*/
public String hashToHex(String source) {
byte[] hashBuffer = source != null ? hash(source) : hash();
return StringSupport.toHexString(hashBuffer, 0, hashBuffer.length);
}//hashToHex()//
/**
* Creates a hash of the previously supplied source.
* @return The hash bytes.
*/
protected byte[] internalHash() {
byte[] buffer = new byte[HASH_SIZE];
internalHash(buffer, 0);
return buffer;
}//internalHash()//
/**
* Creates a hash of the previously supplied source.
* @param hashBuffer The buffer to place the hash in.
* @param hashBufferOffset The index of the first hash byte.
*/
protected void internalHash(byte[] hashBuffer, int hashBufferOffset) {
//Add any final source into the mix.//
addFinal();
//Copy the hash into the result buffer in Big Endian format.//
for(int i = 0; i < this.hashBuffer.length; ++i) {
long value = this.hashBuffer[i];
hashBuffer[hashBufferOffset++] = (byte) (value >>> 56);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 48);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 40);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 32);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 24);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 16);
hashBuffer[hashBufferOffset++] = (byte) (value >>> 8);
hashBuffer[hashBufferOffset++] = (byte) value;
}//for//
//Reset the algorithm.//
reset();
}//internalHash()//
/**
* The SHA-512 transform method which maintains the current hashBuffer by adding/transforming blocks of source data.
* @param data The 8 longs containing the source data to be added to the current hashBuffer.
*/
private void transform(long[] data) {
long a = hashBuffer[0];
long b = hashBuffer[1];
long c = hashBuffer[2];
long d = hashBuffer[3];
long e = hashBuffer[4];
long f = hashBuffer[5];
long g = hashBuffer[6];
long h = hashBuffer[7];
long[] w = internalBuffer;
updateSourceSize();
//Copy the data buffer into the first 16 positions in the working buffer.//
for(int i = 0; i < 16; i++) {
w[i] = data[i];
}//for//
//Expand the data into the remaining working longs.//
for(int i = 16; i < 80; i++) {
long v1 = (w[i - 2] << 45 | w[i - 2] >>> 19) ^ (w[i - 2] << 3 | w[i - 2] >>> 61) ^ (w[i - 2] >>> 6);
long v2 = (w[i - 15] << 63 | w[i - 15] >>> 1) ^ (w[i - 15] << 56 | w[i - 15] >>> 8) ^ (w[i - 15] >>> 7);
w[i] = v1 + w[i - 7] + v2 + w[i - 16];
}//for//
//Mix it all up.//
for(int i = 0, t = 0; i < 10; i++) {
h += f4(e) + f1(e, f, g) + K[t] + w[t++];
d += h;
h += f3(a) + f2(a, b, c);
g += f4(d) + f1(d, e, f) + K[t] + w[t++];
c += g;
g += f3(h) + f2(h, a, b);
f += f4(c) + f1(c, d, e) + K[t] + w[t++];
b += f;
f += f3(g) + f2(g, h, a);
e += f4(b) + f1(b, c, d) + K[t] + w[t++];
a += e;
e += f3(f) + f2(f, g, h);
d += f4(a) + f1(a, b, c) + K[t] + w[t++];
h += d;
d += f3(e) + f2(e, f, g);
c += f4(h) + f1(h, a, b) + K[t] + w[t++];
g += c;
c += f3(d) + f2(d, e, f);
b += f4(g) + f1(g, h, a) + K[t] + w[t++];
f += b;
b += f3(c) + f2(c, d, e);
a += f4(f) + f1(f, g, h) + K[t] + w[t++];
e += a;
a += f3(b) + f2(b, c, d);
}//for//
hashBuffer[0] += a;
hashBuffer[1] += b;
hashBuffer[2] += c;
hashBuffer[3] += d;
hashBuffer[4] += e;
hashBuffer[5] += f;
hashBuffer[6] += g;
hashBuffer[7] += h;
}//transform()//
/**
* Transform 1.
*/
private long f1(long x, long y, long z) {
return ((x & y) ^ ((~x) & z));
}//f1()//
/**
* Transform 2.
*/
private long f2(long x, long y, long z) {
return ((x & y) ^ (x & z) ^ (y & z));
}//f2()//
/**
* Transform 3.
*/
private long f3(long x) {
return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
}//f3()//
/**
* Transform 4.
*/
private long f4(long x) {
return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
}//f4()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//Sha1//