Back to Dave's planet

So there are like a billion free opensource version control products out there and the ONLY plugin I can find for InteliJ to use a Subversion repository is TMate, and they want over $50 for the privilage.

Just for kicks and educational experience I take a quick look at how the good folks at TMate implement security. They actually do a much better job than most products do and they are an excellent subject for educational review. Let us proceed:

So I download the plugin, it arrives in a jar
C:\IntelliJ-IDEA-4.5\config\plugins\tmate-idea\lib\tmate.jar Pop that bad boy open and quickly discover that the folks at TMate have used a code obsfucator. That sucks, but it's not too hard to figure out that the license is handled through org\tmatesoft\tmate\A\D.class
It's reading from a file named "tmate10.key". I found an old ticket on the web that mentioned that these geniuses used to check this file once per second, a little retentive if you ask me.
private static M A() obviously initiates the checking, it reads in two variables:
s = bufferedreader.readLine();
s1 = bufferedreader.readLine();
The rest of the code is pretty messed up, and there are about 600 class files. The rest of the routine looks like this:

        M m;
        m = M.A(s, s1);
        m.B = s1;
          goto _L5
        Throwable throwable;
        throwable;
        null;
        obj;
        JVM INSTR monitorexit ;
        return;
_L5:
        if(s.equals(m.K)) goto _L7; else goto _L6
_L6:
        null;
        obj;
        JVM INSTR monitorexit ;
        return;
_L7:
        C = m;
        m;
        obj;
        JVM INSTR monitorexit ;
        return;
        Exception exception1;
        exception1;
        throw exception1;
    }
    
so I'm guessing I have to figure out which class is M. Takes me about a minute to figure out this is
org\tmatesoft\tmate\A\M.class and that method A that takes two strings, your name and key, calls another method also named A that just takes the key as a string and does some messed up math on each section of the key to turn it into a number (0 = 0, 9 = 9, A = 10, B = 11, etc...passing the right hand segment in first and processing it's characters from left to right multiply the output variable by 36 and add the next digits number). Find the result of each segment of the key, multiply that result by 0x39aa400L (60466176 decimal) and add them all together for the internal representation of your key. My temp 60 day key is
ULU49-BVUFB-9T5A8-XIWPA-MD8F3
so for each segment from right to left we get
37568991
56309518
16476416
19961543
51407289
then we multiply each one by 60466176 and sum them up for some really big number that is the internal representaion of my key. Whoo hoo. Ok, so we are in the method A and we have a really big number, next we call a nifty little Java math utility that actually performs RSA encryption/decryption in one fell swoop, the modPow function (take a really big number (my key, s1), raises it to a really big power, and take modulus of another really big number)
public static M A(String s, String s1) { BigInteger biginteger = A(s1); BigInteger biginteger1 = biginteger.modPow(Q, H); return new M(s, biginteger1); } For a nice simple description of the RSA algoritm I highly recomend http://pajhome.org.uk/crypt/rsa/rsa.html, turns out the hard part is generating the keys, encryption/decryption in Java is as simple as modPow. In this case there are a few constants declared in M:
static final BigInteger H = new BigInteger("C8C18CC6BDCA0D8D308EA74E107C5E01", 16);
private static final BigInteger Q = new BigInteger("82CE1C08DF8581A640DA839F1F409A5", 16);
Ouch, these people are absolutly retentive!!! Look at the size of those keys. Notice how they load the value to be decrypted, s1 (your key), into biginteger and then perform the modPow on it to get the decrypted number. Then they go going through a whole lot of work to return a BigInteger based on bit manipulation of 8 different parameters. Here is an explanation about what the 8 parameters mean, that was helpful:

    public String toString()
    {
        StringBuffer stringbuffer = new StringBuffer();
        stringbuffer.append("\n");
        stringbuffer.append("user name:" + K + "\n");
        stringbuffer.append("customer id:" + N + "\n");
        stringbuffer.append("product id:" + E + "\n");
        stringbuffer.append("license type:" + F + "\n");
        stringbuffer.append("major version:" + D + "\n");
        stringbuffer.append("minor version:" + L + "\n");
        stringbuffer.append("generationDate:" + new Date((long)A * 1000L) + "\n");
        stringbuffer.append("days issued:" + M + "\n");
        return stringbuffer.toString();
    }
    
    
Each of these 8 pieces of information were pulled from pieces of my decrypted key. Also in my decrypted key was my user name. Notice how that original chunk of code said:
if(s.equals(m.K)) ...
it's checking to see if s (my user name from the key file) matches K (my user name decrypted from the key). Somewhere else it's got to be checking to see if the version number, license type, generation date, and days issued are still valid

All in all, a halfway decent job of coding a security module. The key is certainly strong enough to avoid any frontal assult with a decryption routine, though it's kind of like having a massive vault door guarding the entrance to your tent. It might take all the computers on earth an amount of time equal to the age of the univers to break the encryption, but how long would it take someone to recompile the M.class. Probably the easiest way would be to manipulate the bytecode directly.

Back to Dave's planet

Locations of visitors to this page Even if you don't run a business security cameras may be useful for you. There is a peace of mind in having security cameras for some people, who want more security in their home, but you may also get a discount on home insurance for having security products installed in your home.