Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I was quite interested in that article, so I implemented the code in Java. may be of use</p> <pre><code>import java.util.Locale; import java.util.Set; import java.util.TreeSet; public class KeyValidator { private static final byte[][] params = new byte[][] { { 24, 4, 127 }, { 10, 0, 56 }, { 1, 2, 91 }, { 7, 1, 100 } }; private static final Set&lt;String&gt; blacklist = new TreeSet&lt;String&gt;(); static { blacklist.add("11111111"); } private static byte PKV_GetKeyByte(final int seed, final byte a, final byte b, final byte c) { final int a1 = a % 25; final int b1 = b % 3; if (a1 % 2 == 0) { return (byte) (((seed &gt;&gt; a1) &amp; 0x000000FF) ^ ((seed &gt;&gt; b1) | c)); } else { return (byte) (((seed &gt;&gt; a1) &amp; 0x000000FF) ^ ((seed &gt;&gt; b1) &amp; c)); } } private static String PKV_GetChecksum(final String s) { int left = 0x0056; int right = 0x00AF; for (byte b : s.getBytes()) { right += b; if (right &gt; 0x00FF) { right -= 0x00FF; } left += right; if (left &gt; 0x00FF) { left -= 0x00FF; } } int sum = (left &lt;&lt; 8) + right; return intToHex(sum, 4); } public static String PKV_MakeKey(final int seed) { // Fill KeyBytes with values derived from Seed. // The parameters used here must be exactly the same // as the ones used in the PKV_CheckKey function. // A real key system should use more than four bytes. final byte[] keyBytes = new byte[4]; keyBytes[0] = PKV_GetKeyByte(seed, params[0][0], params[0][1], params[0][2]); keyBytes[1] = PKV_GetKeyByte(seed, params[1][0], params[1][1], params[1][2]); keyBytes[2] = PKV_GetKeyByte(seed, params[2][0], params[2][1], params[2][2]); keyBytes[3] = PKV_GetKeyByte(seed, params[3][0], params[3][1], params[3][2]); // the key string begins with a hexadecimal string of the seed final StringBuilder result = new StringBuilder(intToHex(seed, 8)); // then is followed by hexadecimal strings of each byte in the key for (byte b : keyBytes) { result.append(intToHex(b, 2)); } // add checksum to key string result.append(PKV_GetChecksum(result.toString())); final String key = result.toString(); return key.substring(0, 4) + "-" + key.substring(4, 8) + "-" + key.substring(8, 12) + "-" + key.substring(12, 16) + "-" + key.substring(16, 20); } private static boolean PKV_CheckKeyChecksum(final String key) { // remove cosmetic hyphens and normalise case final String comp = key.replaceAll("-", "").toLowerCase(Locale.UK); if (comp.length() != 20) { return false; // Our keys are always 20 characters long } // last four characters are the checksum final String checksum = comp.substring(16); return checksum.equals(PKV_GetChecksum(comp.substring(0, 16))); } public static Status PKV_CheckKey(final String key) { if (!PKV_CheckKeyChecksum(key)) { return Status.KEY_INVALID; // bad checksum or wrong number of // characters } // remove cosmetic hyphens and normalise case final String comp = key.replaceAll("-", "").toLowerCase(Locale.UK); // test against blacklist for (String bl : blacklist) { if (comp.startsWith(bl)) { return Status.KEY_BLACKLISTED; } } // At this point, the key is either valid or forged, // because a forged key can have a valid checksum. // We now test the "bytes" of the key to determine if it is // actually valid. // When building your release application, use conditional defines // or comment out most of the byte checks! This is the heart // of the partial key verification system. By not compiling in // each check, there is no way for someone to build a keygen that // will produce valid keys. If an invalid keygen is released, you // simply change which byte checks are compiled in, and any serial // number built with the fake keygen no longer works. // Note that the parameters used for PKV_GetKeyByte calls MUST // MATCH the values that PKV_MakeKey uses to make the key in the // first place! // extract the Seed from the supplied key string final int seed; try { seed = Integer.valueOf(comp.substring(0, 8), 16); } catch (NumberFormatException e) { return Status.KEY_PHONY; } // test key 0 final String kb0 = comp.substring(8, 10); final byte b0 = PKV_GetKeyByte(seed, params[0][0], params[0][1], params[0][2]); if (!kb0.equals(intToHex(b0, 2))) { return Status.KEY_PHONY; } // test key1 final String kb1 = comp.substring(10, 12); final byte b1 = PKV_GetKeyByte(seed, params[1][0], params[1][1], params[1][2]); if (!kb1.equals(intToHex(b1, 2))) { return Status.KEY_PHONY; } // test key2 final String kb2 = comp.substring(12, 14); final byte b2 = PKV_GetKeyByte(seed, params[2][0], params[2][1], params[2][2]); if (!kb2.equals(intToHex(b2, 2))) { return Status.KEY_PHONY; } // test key3 final String kb3 = comp.substring(14, 16); final byte b3 = PKV_GetKeyByte(seed, params[3][0], params[3][1], params[3][2]); if (!kb3.equals(intToHex(b3, 2))) { return Status.KEY_PHONY; } // If we get this far, then it means the key is either good, or was made // with a keygen derived from "this" release. return Status.KEY_GOOD; } protected static String intToHex(final Number n, final int chars) { return String.format("%0" + chars + "x", n); } public enum Status { KEY_GOOD, KEY_INVALID, KEY_BLACKLISTED, KEY_PHONY } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload