/*
* Copyright (c) 2006 Damien Miller
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#define PYBCRYPT_VERSION "0.4"
#if defined(_WIN32)
typedef unsigned __int8 u_int8_t;
typedef unsigned __int16 u_int16_t;
typedef unsigned __int32 u_int32_t;
#define strdup _strdup /* strdup is not ANSI C. _strdup */
#endif
/* Import */
int pybc_bcrypt(const char *, const char *, char *, size_t);
void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
PyDoc_STRVAR(bcrypt_encode_salt_doc,
"encode_salt(csalt, log_rounds) -> encoded_salt\n\
Encode a raw binary salt and the specified log2(rounds) as a\n\
standard bcrypt text salt. Used internally by bcrypt.gensalt()\n");
static PyObject *
bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
{
static char *keywords[] = { "csalt", "log_rounds", NULL };
char *csalt = NULL;
Py_ssize_t csaltlen = -1;
long log_rounds = -1;
char ret[64];
if (!PyArg_ParseTupleAndKeywords(args, kw_args, "s#l:encode_salt",
keywords, &csalt, &csaltlen, &log_rounds))
return NULL;
if (csaltlen != 16) {
PyErr_SetString(PyExc_ValueError, "Invalid salt length");
return NULL;
}
if (log_rounds < 4 || log_rounds > 31) {
PyErr_SetString(PyExc_ValueError, "Invalid number of rounds");
return NULL;
}
encode_salt(ret, (u_int8_t *) csalt, csaltlen, log_rounds);
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(ret);
#else
return PyString_FromString(ret);
#endif
}
PyDoc_STRVAR(bcrypt_hashpw_doc,
"hashpw(password, salt) -> hashed_password\n\
Hash the specified password and the salt using the OpenBSD\n\
Blowfish password hashing algorithm. Returns the hashed password.\n");
static PyObject *
bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
{
static char *keywords[] = { "password", "salt", NULL };
char *password = NULL, *salt = NULL;
char hashed[128];
int ret;
char *password_copy;
char *salt_copy;
if (!PyArg_ParseTupleAndKeywords(args, kw_args, "ss:hashpw", keywords,
&password, &salt))
return NULL;
password_copy = strdup(password);
salt_copy = strdup(salt);
Py_BEGIN_ALLOW_THREADS;
ret = pybc_bcrypt(password_copy, salt_copy, hashed, sizeof(hashed));
Py_END_ALLOW_THREADS;
memset(password_copy, 0, strlen(password_copy));
free(password_copy);
memset(salt_copy, 0, strlen(salt_copy));
free(salt_copy);
if (ret != 0 || strcmp(hashed, ":") == 0) {
PyErr_SetString(PyExc_ValueError, "Invalid salt");
return NULL;
}
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(hashed);
#else
return PyString_FromString(hashed);
#endif
}
static PyMethodDef bcrypt_methods[] = {
{ "hashpw", (PyCFunction)bcrypt_hashpw,
METH_VARARGS|METH_KEYWORDS, bcrypt_hashpw_doc },
{ "encode_salt", (PyCFunction)bcrypt_encode_salt,
METH_VARARGS|METH_KEYWORDS, bcrypt_encode_salt_doc },
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(module_doc, "Internal module used by bcrypt.\n");
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef bcrypt_module = {
PyModuleDef_HEAD_INIT,
"bcrypt._bcrypt", /* m_name */
module_doc, /* m_doc */
-1, /* m_size */
bcrypt_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyMODINIT_FUNC
PyInit__bcrypt(void)
{
PyObject *m;
m = PyModule_Create(&bcrypt_module);
PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
return m;
}
#else
PyMODINIT_FUNC
init_bcrypt(void)
{
PyObject *m;
m = Py_InitModule3("bcrypt._bcrypt", bcrypt_methods, module_doc);
PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
}
#endif