Skip to content

Commit ed3a18b

Browse files
author
wcdolphin
committedJul 20, 2013
Add initial support for Python3
Does not accepts bytes to hashpw, yet.
1 parent 1fcd2e0 commit ed3a18b

File tree

4 files changed

+73
-21
lines changed

4 files changed

+73
-21
lines changed
 

‎.travis.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
language: python
22
python:
3-
- 2.6
4-
- 2.7
5-
3+
- "2.6"
4+
- "2.7"
5+
- "3.2"
6+
- "3.3"
67
install:
78
- python setup.py install
89
script:

‎bcrypt/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"""
2424

2525
import os
26-
from _bcrypt import *
26+
from bcrypt._bcrypt import *
2727

2828
def gensalt(log_rounds = 12):
2929
"""Generate a random text salt for use with hashpw(). "log_rounds"

‎bcrypt/bcrypt_python.c

+50-16
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@
1313
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1414
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
*/
16-
16+
#define PY_SSIZE_T_CLEAN
1717
#include "Python.h"
1818

19+
#define PYBCRYPT_VERSION "0.4"
20+
1921
#if defined(_WIN32)
2022
typedef unsigned __int8 u_int8_t;
2123
typedef unsigned __int16 u_int16_t;
2224
typedef unsigned __int32 u_int32_t;
2325
#define strdup _strdup /* strdup is not ANSI C. _strdup */
2426
#endif
2527

26-
/* $Id$ */
2728

2829
/* Import */
2930
int pybc_bcrypt(const char *, const char *, char *, size_t);
@@ -39,7 +40,7 @@ bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
3940
{
4041
static char *keywords[] = { "csalt", "log_rounds", NULL };
4142
char *csalt = NULL;
42-
int csaltlen = -1;
43+
Py_ssize_t csaltlen = -1;
4344
long log_rounds = -1;
4445
char ret[64];
4546

@@ -54,8 +55,12 @@ bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
5455
PyErr_SetString(PyExc_ValueError, "Invalid number of rounds");
5556
return NULL;
5657
}
57-
encode_salt(ret, csalt, csaltlen, log_rounds);
58-
return PyString_FromString(ret);
58+
encode_salt(ret, (u_int8_t *) csalt, csaltlen, log_rounds);
59+
#if PY_MAJOR_VERSION >= 3
60+
return PyUnicode_FromString(ret);
61+
#else
62+
return PyString_FromString(ret);
63+
#endif
5964
}
6065

6166
PyDoc_STRVAR(bcrypt_hashpw_doc,
@@ -72,7 +77,7 @@ bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
7277
int ret;
7378
char *password_copy;
7479
char *salt_copy;
75-
if (!PyArg_ParseTupleAndKeywords(args, kw_args, "ss:hashpw", keywords,
80+
if (!PyArg_ParseTupleAndKeywords(args, kw_args, "ss:hashpw", keywords,
7681
&password, &salt))
7782
return NULL;
7883

@@ -93,8 +98,11 @@ bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
9398
PyErr_SetString(PyExc_ValueError, "Invalid salt");
9499
return NULL;
95100
}
96-
101+
#if PY_MAJOR_VERSION >= 3
102+
return PyUnicode_FromString(hashed);
103+
#else
97104
return PyString_FromString(hashed);
105+
#endif
98106
}
99107

100108
static PyMethodDef bcrypt_methods[] = {
@@ -107,12 +115,38 @@ static PyMethodDef bcrypt_methods[] = {
107115

108116
PyDoc_STRVAR(module_doc, "Internal module used by bcrypt.\n");
109117

110-
PyMODINIT_FUNC
111-
init_bcrypt(void)
112-
{
113-
PyObject *m;
114-
115-
m = Py_InitModule3("bcrypt._bcrypt", bcrypt_methods, module_doc);
116-
PyModule_AddStringConstant(m, "__version__", "0.3.1");
117-
}
118-
118+
#if PY_MAJOR_VERSION >= 3
119+
static struct PyModuleDef bcrypt_module = {
120+
PyModuleDef_HEAD_INIT,
121+
"bcrypt._bcrypt", /* m_name */
122+
module_doc, /* m_doc */
123+
-1, /* m_size */
124+
bcrypt_methods, /* m_methods */
125+
NULL, /* m_reload */
126+
NULL, /* m_traverse */
127+
NULL, /* m_clear */
128+
NULL, /* m_free */
129+
};
130+
131+
PyMODINIT_FUNC
132+
PyInit__bcrypt(void)
133+
{
134+
PyObject *m;
135+
136+
m = PyModule_Create(&bcrypt_module);
137+
PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
138+
return m;
139+
}
140+
141+
#else
142+
143+
144+
PyMODINIT_FUNC
145+
init_bcrypt(void)
146+
{
147+
PyObject *m;
148+
149+
m = Py_InitModule3("bcrypt._bcrypt", bcrypt_methods, module_doc);
150+
PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
151+
}
152+
#endif

‎test/test.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
# $Id$
1818

1919
import bcrypt
20-
2120
import unittest
21+
import sys
22+
23+
PY3 = (sys.version_info >= (3,0))
24+
25+
def enc(s):
26+
return s.encode("latin-1") if PY3 else s
2227

2328
test_vectors = [
2429
[ '', '$2a$06$DCq7YPn5Rq63x1Lad4cll.',
@@ -61,8 +66,20 @@
6166
'$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS' ],
6267
[ '~!@#$%^&*() ~!@#$%^&*()PNBFRD', '$2a$12$WApznUOJfkEGSmYRfnkrPO',
6368
'$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC' ],
69+
# [ enc('\xa3'), '$2a$05$CCCCCCCCCCCCCCCCCCCCC.', # latin-1 POUND SIGN
70+
# '$2a$05$CCCCCCCCCCCCCCCCCCCCC.BvtRGGx3p8o0C5C36uS442Qqnrwofrq' ],
71+
# [ enc('\xc2\xa3'), '$2a$05$CCCCCCCCCCCCCCCCCCCCC.', # utf-8 POUND SIGN
72+
# '$2a$05$CCCCCCCCCCCCCCCCCCCCC.CAzSxlf0FLW7g1A5q7W/ZCj1xsN6A.e' ],
6473
]
6574

75+
76+
if PY3:
77+
# add 8-bit unicode test as well; to verify PY3 encodes it as UTF-8.
78+
test_vectors.append(
79+
[ '\u00A3', '$2a$05$CCCCCCCCCCCCCCCCCCCCC.', # unicode POUND SIGN
80+
'$2a$05$CCCCCCCCCCCCCCCCCCCCC.CAzSxlf0FLW7g1A5q7W/ZCj1xsN6A.e' ],
81+
)
82+
6683
class TestRadix(unittest.TestCase):
6784
def test_00__test_vectors(self):
6885
for plain, salt, expected in test_vectors:

0 commit comments

Comments
 (0)
Please sign in to comment.