Back to index

python-bcrypt  0.2
bcrypt_python.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006 Damien Miller <djm@mindrot.org>
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include "Python.h"
00018 
00019 #if defined(_MSC_VER)
00020 typedef unsigned __int8            u_int8_t;
00021 typedef unsigned __int16    u_int16_t;
00022 typedef unsigned __int32    u_int32_t;
00023 #endif
00024 
00025 /* $Id: bcrypt_python.c,v 1.3 2009/10/01 13:09:52 djm Exp $ */
00026 
00027 /* Import */
00028 char *pybc_bcrypt(const char *, const char *);
00029 void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
00030 
00031 PyDoc_STRVAR(bcrypt_encode_salt_doc,
00032 "encode_salt(csalt, log_rounds) -> encoded_salt\n\
00033     Encode a raw binary salt and the specified log2(rounds) as a\n\
00034     standard bcrypt text salt. Used internally by bcrypt.gensalt()\n");
00035 
00036 static PyObject *
00037 bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
00038 {
00039        static char *keywords[] = { "csalt", "log_rounds", NULL };
00040        char *csalt = NULL;
00041        int csaltlen = -1;
00042        long log_rounds = -1;
00043        char ret[64];
00044 
00045        if (!PyArg_ParseTupleAndKeywords(args, kw_args, "s#l:encode_salt",
00046            keywords, &csalt, &csaltlen, &log_rounds))
00047                 return NULL;
00048        if (csaltlen != 16) {
00049               PyErr_SetString(PyExc_ValueError, "Invalid salt length");
00050               return NULL;
00051        }
00052        if (log_rounds < 4 || log_rounds > 31) {
00053               PyErr_SetString(PyExc_ValueError, "Invalid number of rounds");
00054               return NULL;
00055        }
00056        encode_salt(ret, csalt, csaltlen, log_rounds);
00057        return PyString_FromString(ret);
00058 }
00059 
00060 PyDoc_STRVAR(bcrypt_hashpw_doc,
00061 "hashpw(password, salt) -> hashed_password\n\
00062     Hash the specified password and the salt using the OpenBSD\n\
00063     Blowfish password hashing algorithm. Returns the hashed password.\n");
00064 
00065 static PyObject *
00066 bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
00067 {
00068        static char *keywords[] = { "password", "salt", NULL };
00069        char *password = NULL, *salt = NULL;
00070        char *ret;
00071 
00072        if (!PyArg_ParseTupleAndKeywords(args, kw_args, "ss:hashpw", keywords,
00073            &password, &salt))
00074                 return NULL;
00075 
00076        char *password_copy = strdup(password);
00077        char *salt_copy = strdup(salt);
00078 
00079        Py_BEGIN_ALLOW_THREADS;
00080        ret = pybc_bcrypt(password_copy, salt_copy);
00081        Py_END_ALLOW_THREADS;
00082 
00083        free(password_copy);
00084        free(salt_copy);
00085        if ((ret == NULL) ||
00086            strcmp(ret, ":") == 0) {
00087               PyErr_SetString(PyExc_ValueError, "Invalid salt");
00088               return NULL;
00089        }
00090 
00091        return PyString_FromString(ret);
00092 }
00093 
00094 static PyMethodDef bcrypt_methods[] = {
00095        {      "hashpw",     (PyCFunction)bcrypt_hashpw,
00096               METH_VARARGS|METH_KEYWORDS, bcrypt_hashpw_doc    },
00097        {      "encode_salt",       (PyCFunction)bcrypt_encode_salt,
00098               METH_VARARGS|METH_KEYWORDS, bcrypt_encode_salt_doc      },
00099        {NULL,        NULL}         /* sentinel */
00100 };
00101 
00102 PyDoc_STRVAR(module_doc, "Internal module used by bcrypt.\n");
00103 
00104 PyMODINIT_FUNC
00105 init_bcrypt(void)
00106 {
00107        PyObject *m;
00108 
00109        m = Py_InitModule3("bcrypt._bcrypt", bcrypt_methods, module_doc);
00110        PyModule_AddStringConstant(m, "__version__", "0.1");
00111 }
00112