/**
* $Id: SCKeyDecode.java 1608 2008-09-12 17:35:39Z scotta $
*/
/*
* CDKeyDecode.java
*
* Created on March 17, 2004, 8:14 AM
*/
package org.jbls.Hashing;
import org.jbls.util.Buffer;
/**
* This decodes a standard numeric CDKey (Starcraft's) for sending to
* battle.net.
* @author iago
*/
public class SCKeyDecode {
/** The decoded cdkey. */
protected String cdkey;
/** Does nothing - required for subclasses. */
public SCKeyDecode() {
}
/**
* Sets up the decoder with the specified key and goes ahead and decodes it.
*
* @param cdkey
* The CDKey to hash.
* @throws HashException
* If the cdkey is invalid.
*/
public SCKeyDecode(String cdkey) throws HashException {
this.cdkey = cdkey;
if (cdkey == null)
throw new HashException("CDKey missing.");
if (cdkey.length() != 13)
throw new HashException("CDKey is invalid length");
if (verify() == false)
throw new HashException("CDKey is invalid.");
getFinalValue();
}
/**
* Hashes the CDKey based on the client and server token, and returns the
* 5-byte hash.
*
* @param clientToken
* The client token to hash it with.
* @param serverToken
* The server token to hash it with.
* @return The 20-byte hash (5 ints).
*/
public int[] getKeyHash(int clientToken, int serverToken) {
Buffer hashData = new Buffer();
hashData.addDWord(clientToken);
hashData.addDWord(serverToken);
hashData.addDWord(getProduct());
hashData.addDWord(getVal1());
hashData.addDWord(0);
hashData.addDWord(getVal2());
return BrokenSHA1.calcHashBuffer(hashData.getBuffer());
}
public int[] getOldKeyHash(int clientToken, int serverToken) {
Buffer hashData = new Buffer();
hashData.addDWord(clientToken);
hashData.addDWord(serverToken);
hashData.addDWord(getProduct());
hashData.addDWord(getVal1());
hashData.addDWord(getVal2());
return BrokenSHA1.calcHashBuffer(hashData.getBuffer());
}
/**
* Verifies that the CDKey is valid.
*
* @return true if the CDKey is valid. false if the CDKey is invalid.
*/
protected boolean verify() {
int accum = 3;
cdkey = cdkey.toLowerCase();
for (int i = 0; i < (cdkey.length() - 1); i++)
accum += ((cdkey.charAt(i) - '0') ^ (accum * 2));
return ((accum % 10) == (cdkey.charAt(12) - '0'));
}
/** Gets the final CDKey values. */
protected void getFinalValue() {
int c;
int hashkey = 0x13AC9741;
int seq[] = { 6, 0, 2, 9, 3, 11, 1, 7, 5, 4, 10, 8 };
char[] key = new char[12];
for (short i = 11; i >= 0; i--) {
c = cdkey.charAt(seq[i]);
if (c <= '7') {
c ^= (byte) (hashkey & 7);
hashkey >>>= 3;
} else
c ^= (byte) (i & 1);
key[i] = (char) c;
}
cdkey = new String(key);
}
/**
* Gets the game's product.
*
* @return The game's product.
*/
public int getProduct() {
return Integer.parseInt(cdkey.substring(0, 2));
}
/**
* Gets the second CDKey value.
*
* @return The second CDKey value.
*/
public int getVal2() {
return Integer.parseInt(cdkey.substring(9, 12));
}
/**
* Gets the first CDKey value.
*
* @return The first CDKey value.
*/
public int getVal1() {
return Integer.parseInt(cdkey.substring(2, 9));
}
}