Bind to pgcrypto from python
Question: I'd like to call some pgcrypto functions from python. Namely
[px_crypt](http://doxygen.postgresql.org/px-
crypt_8c.html#a6e88d87094f37fecc56c0abfb42d1fc3). I can't seem to figure out
the right object files to link it seems.

Here's my code:

    
    
    #include <Python.h>
    
    #include "postgres.h"
    
    #include "pgcrypto/px-crypt.h"
    
    
    static PyObject*
    pgcrypt(PyObject* self, PyObject* args)
    {
        const char* key;
        const char* setting;
    
        if (!PyArg_ParseTuple(args, "ss", &key, &setting))
            return NULL;
    
        return Py_BuildValue("s", px_crypt(key, setting, "", 0));
    }
    
    static PyMethodDef PgCryptMethods[] =
    {
         {"pgcrypt", pgcrypt, METH_VARARGS, "Call pgcrypto's crypt"},
         {NULL, NULL, 0, NULL}
    };
    
    PyMODINIT_FUNC
    initpypgcrypto(void)
    {
         (void) Py_InitModule("pypgcrypto", PgCryptMethods);
    }
    

and gcc commands and output:

    
    
    x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/home/ionut/github/postgres/contrib/ -I/usr/include/postgresql/9.4/server/ -I/usr/include/python2.7 -c pypgcrypto.c -o build/temp.linux-x86_64-2.7/pypgcrypto.o
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wl,-z,relro -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/pypgcrypto.o /usr/lib/postgresql/9.4/lib/pgcrypto.so -lpgport -lpq -o build/lib.linux-x86_64-2.7/pypgcrypto.so
    

Error is:

    
    
    python -c "import pypgcrypto; print pypgcrypto.pgcrypt('foo', 'bar')"
    
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ImportError: /usr/lib/postgresql/9.4/lib/pgcrypto.so: undefined symbol: InterruptPending
    


Answer: From one of your comments I got this...

> I want to replicate pgcrypto's behavior in order to be able to generate
> password hashes that match the ones already in my database.

You can use python to do this already. I don't know what algorithm you're
using, nor should I, here are two different methods using python to generate
the exact same hash as Postgresql's pgcrypto

**Crypt**

    
    
    =# select crypt('12345678', gen_salt('xdes')), md5('test');
            crypt         |               md5                
    ----------------------+----------------------------------
     _J9..b8FIoskMdlHvKjk | 098f6bcd4621d373cade4e832627b4f6
    

Here's the Python to check the password...

    
    
    #!/usr/bin/env python
    import crypt
    from hmac import compare_digest as compare_hash
    
    def login():
        hash_ = '_J9..OtC82a6snTAAqWg'
        print(compare_hash(crypt.crypt('123456789', hash_), hash_))
        #return True
    
    if __name__ == '__main__':
      login()
    

**MD5**

For md5 you can use `passlib`'s md5_crypt as follows...

    
    
    =# select crypt('12345678', gen_salt('md5')), md5('test');
                   crypt                |               md5                
    ------------------------------------+----------------------------------
     $1$UUVXoPbO$JMA7yhrKvaZcKqoFoi9jl. | 098f6bcd4621d373cade4e832627b4f6
    

Python would look something like...

    
    
    #!/usr/bin/env python
    from passlib.hash import md5_crypt
    
    def login():
        hash_ = '$1$kOFl2EuX$QhhnPMAdx2/j2Tsk15nfQ0'
        print(md5_crypt.verify("12345678", hash_))
    
    if __name__ == '__main__':
      login()
    

**Blowfish**

    
    
    select crypt('12345678', gen_salt('bf')), md5('test');
                                crypt                             |               md5                
    --------------------------------------------------------------+----------------------------------
     $2a$06$HLZUXMgqFhi/sl1D697il.lN8OMQFBWR2VBuZ5nTCd59jvGLU9pQ2 | 098f6bcd4621d373cade4e832627b4f6
    

Python code...

    
    
    #!/usr/bin/env python
    from passlib.hash import md5_crypt
    from passlib.hash import bcrypt
    
    def blowfish():
        hash_ = '$2a$06$HLZUXMgqFhi/sl1D697il.lN8OMQFBWR2VBuZ5nTCd59jvGLU9pQ2'
        print(bcrypt.verify("12345678", hash_))
    
    if __name__ == '__main__':
      blowfish()
    

