Sunday, November 8, 2015

Using Python passlib in Java applications

Some of my readers might ask why would python developer need to do something in java? I've never thought I would need to code in java too. But if you saw my last post, I was talking about how to implement SSO with django website. And one of its main components is java based application, which I wanted to customize.

So here is the problem: I needed to verify password hashes in java application (java 7), but those hashes were generated with python passlib library (pbkdf2_sha512). First I even tried to implement password verification in java, but then I gave up and decided to do it easy way.

How to use Python passlib in Java? Use Jython!

Jython is java implementation of python, which allows to execute almost any python code from java application. So let's try to verify passlib hashes with Jython.

1. Download and install jython:
cd ~
wget -O jython-installer-2.7.0.jar http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.0/jython-installer-2.7.0.jar
java -jar jython-installer-2.7.0.jar --console
answer some questions:
installation type: standard
install additional parts ? No
exclude parts from the installation? No
target directory: /home/test/jython

2. Install passlib:
~/jython/bin/pip install passlib

3. Create java file PasslibHash.java:
import org.python.util.PythonInterpreter;
import org.python.core.*;

public class PasslibHash
{
        private static Boolean verify_pbkdf2_sha512(String pw, String hash) {

                PythonInterpreter python = new PythonInterpreter();

                python.exec("from passlib.hash import pbkdf2_sha512");

                python.set("pw", new PyString(pw));
                python.set("hash", new PyString(hash));

                python.exec("valid = 1 if pbkdf2_sha512.identify(hash) and pbkdf2_sha512.verify(pw, hash) else 0");

                Boolean valid = ((PyInteger)python.get("valid")).asInt()==1;

                return (Boolean)valid;
        }

        private static String generate_pbkdf2_sha512(String pw) {
                PythonInterpreter python = new PythonInterpreter();

                python.exec("from passlib.hash import pbkdf2_sha512");

                python.set("pw", new PyString(pw));

                python.exec("hash = pbkdf2_sha512.encrypt(pw)");

                return ((PyString)python.get("hash")).asString();
        }

        public static void main(String[] args)
        {
                String pw = "123";
                String hash = generate_pbkdf2_sha512(pw);

                System.out.println("generated hash for '" + pw + "':");
                System.out.println(hash);

                Boolean valid = verify_pbkdf2_sha512(pw,hash);
                System.out.println("is hash valid:");
                System.out.println(valid);
        }
}

4. Compile PasslibHash.jar file:
javac -cp /home/test/jython/jython.jar PasslibHash.java
jar cvf PasslibHash.jar PasslibHash.class

5. Execute PasslibHash class from PasslibHash.jar file:
java -cp PasslibHash.jar:/home/test/jython/jython.jar PasslibHash

6. You should see the following output:
generated hash for '123':
$pbkdf2-sha512$25000$z3lvjTHmvDem1Po/x9ibkw$TfszqhnC2ngLAtvDEWerrcGPv9569W9A2H3ir4jxsdmys9C7NjXNVKJztgEBwsWnPhwnfA6bp2Mp1gf1MYWFKA
is hash valid:
true

Conclusion

With Jython you can easily use passlib python library in your java application. But the main downside of this method is very slow performance (comparing to pure python). If you need to speed things up, probably try to call pure python instead of jython. And finally if you know any better solution of how to use passlib in java, please let me know.

No comments:

Post a Comment