New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

cryptacular

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cryptacular - pypi Package Compare versions

Comparing version
1.2.1
to
1.3
+5
-0
CHANGES.txt

@@ -0,1 +1,6 @@

1.3
===
- Python 3 support contributed by Frank Smit (some tests do not run)
- Fix staticmethod issue with CRYPTPasswordManager
1.2.1

@@ -2,0 +7,0 @@ =====

+14
-2

@@ -1,4 +0,4 @@

Metadata-Version: 1.0
Metadata-Version: 1.1
Name: cryptacular
Version: 1.2.1
Version: 1.3
Summary: A password hashing framework with bcrypt and pbkdf2.

@@ -131,2 +131,7 @@ Home-page: http://bitbucket.org/dholth/cryptacular/

1.3
===
- Python 3 support contributed by Frank Smit (some tests do not run)
- Fix staticmethod issue with CRYPTPasswordManager
1.2.1

@@ -191,3 +196,10 @@ =====

Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: C
Classifier: Topic :: Security :: Cryptography
+0
-1

@@ -14,3 +14,2 @@ CHANGES.txt

crypt_blowfish-1.2/crypt_blowfish.c
crypt_blowfish-1.2/crypt_blowfish.c~
crypt_blowfish-1.2/crypt_blowfish.h

@@ -17,0 +16,0 @@ crypt_blowfish-1.2/crypt_gensalt.c

# Copyright (c) 2009 Daniel Holth <dholth@fastmail.fm>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# of this software and associated documentation files (the 'Software'), to deal
# in the Software without restriction, including without limitation the rights

@@ -13,3 +13,3 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

@@ -24,2 +24,3 @@ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

import os

@@ -29,50 +30,48 @@ import re

from cryptacular.bcrypt._bcrypt import crypt_rn, crypt_gensalt_rn
import cryptacular.core
from cryptacular.core import _cmp, check_unicode
class BCRYPTPasswordManager(object):
# for testing
crypt_rn = crypt_rn
crypt_gensalt_rn = crypt_gensalt_rn
SCHEME = "BCRYPT"
PREFIX = "$2a$"
ROUNDS = 10
_scheme = 'BCRYPT'
_prefix = '$2a$'
_rounds = 10
_bcrypt_syntax = re.compile('\$2a\$[0-9]{2}\$[./A-Za-z0-9]{53}')
def encode(self, password, rounds=None):
"""Hash a password using bcrypt.
def encode(self, text, rounds=None):
'''Hash a password using bcrypt.
Note: only the first 72 characters of password are significant.
"""
work_factor = rounds or self.ROUNDS
settings = crypt_gensalt_rn('$2a$', work_factor, os.urandom(16))
'''
rounds = rounds or self._rounds
settings = self.crypt_gensalt_rn(self._prefix, rounds, os.urandom(16))
if settings is None:
raise ValueError("_bcrypt.crypt_gensalt_rn returned None") # pragma NO COVERAGE
if isinstance(password, unicode):
password = password.encode('utf-8')
if not isinstance(password, str):
raise TypeError("password must be a str")
rc = crypt_rn(password, settings)
if rc is None:
raise ValueError("_bcrypt.crypt_rn returned None") # pragma NO COVERAGE
return rc
raise ValueError('_bcrypt.crypt_gensalt_rn returned None')
def check(self, encoded, password):
"""Check a bcrypt password hash against a password."""
if isinstance(password, unicode):
password = password.encode('utf-8')
if isinstance(encoded, unicode):
encoded = encoded.encode('utf-8')
if not isinstance(password, str):
raise TypeError("password must be a str")
if not isinstance(encoded, str):
raise TypeError("encoded must be a str")
encoded = self.crypt_rn(check_unicode(text), settings)
if encoded is None:
raise ValueError('_bcrypt.crypt_rn returned None')
return encoded
def check(self, encoded, text):
'''Check a bcrypt password hash against a password.
'''
if not self.match(encoded):
return False
rc = crypt_rn(password, encoded)
if rc is None:
raise ValueError("_bcrypt.crypt_rn returned None")
return cryptacular.core._cmp(rc, encoded)
encoded_text = self.crypt_rn(check_unicode(text), encoded)
if encoded_text is None:
raise ValueError('_bcrypt.crypt_rn returned None')
return _cmp(encoded_text, check_unicode(encoded))
def match(self, hash):
"""Return True if hash looks like a BCRYPT password hash."""
'''Return True if hash looks like a BCRYPT password hash.
'''
return self._bcrypt_syntax.match(hash) is not None
/* Python extension module for bcrypt2.
*
* Daniel Holth <dholth@fastmail.fm>, 2010
* Frank Smit <frank@61924.nl>, 2011 (added Python 3 support)
*

@@ -24,70 +25,112 @@ * Permission is hereby granted, free of charge, to any person obtaining a copy

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "ow-crypt.h"
static PyObject *_py_crypt_rn(PyObject *self, PyObject *args) {
char *rc;
const char *key;
const char *setting;
char output[61];
memset(output, 0, sizeof(output));
static PyObject *
_py_crypt_rn(PyObject *self, PyObject *args)
{
char *rc;
const char *key;
const char *setting;
char output[61];
if (!PyArg_ParseTuple(args, "ss", &key, &setting)) {
return NULL;
}
memset(output, 0, sizeof(output));
Py_BEGIN_ALLOW_THREADS;
/* key, setting, output, size */
rc = crypt_rn(key, setting, output, sizeof(output));
if (!PyArg_ParseTuple(args, "ss", &key, &setting)) {
return NULL;
}
Py_END_ALLOW_THREADS;
Py_BEGIN_ALLOW_THREADS;
if (rc == NULL) {
Py_RETURN_NONE;
}
/* key, setting, output, size */
rc = crypt_rn(key, setting, output, sizeof(output));
output[sizeof(output) - 1] = '\0';
Py_END_ALLOW_THREADS;
return Py_BuildValue("s", output);
if (rc == NULL) {
Py_RETURN_NONE;
}
output[sizeof(output) - 1] = '\0';
return Py_BuildValue("s", output);
}
static PyObject *_py_crypt_gensalt_rn(PyObject *self, PyObject *args) {
char *rc;
const char *prefix;
const int count;
const char *salt;
const Py_ssize_t salt_len;
char output[30];
memset(output, 0, sizeof(output));
if (!PyArg_ParseTuple(args, "sis#", &prefix, &count, &salt, &salt_len)) {
return NULL;
}
static PyObject *
_py_crypt_gensalt_rn(PyObject *self, PyObject *args)
{
char *rc;
const char *prefix;
const int count;
const char *salt;
const Py_ssize_t salt_len;
char output[30];
/* prefix, count, input, size, output, output_size */
rc = crypt_gensalt_rn(prefix, count, salt, salt_len, output, sizeof(output));
memset(output, 0, sizeof(output));
if (rc == NULL) {
Py_RETURN_NONE;
}
if (!PyArg_ParseTuple(args, "sis#", &prefix, &count, &salt, &salt_len)) {
return NULL;
}
output[sizeof(output) - 1] = '\0';
Py_BEGIN_ALLOW_THREADS;
return Py_BuildValue("s", output);
/* prefix, count, input, size, output, output_size */
rc = crypt_gensalt_rn(prefix, count, salt, salt_len, output, sizeof(output));
Py_END_ALLOW_THREADS;
if (rc == NULL) {
Py_RETURN_NONE;
}
output[sizeof(output) - 1] = '\0';
return Py_BuildValue("s", output);
}
static PyMethodDef BcryptMethods[] = {
{"crypt_rn", _py_crypt_rn, METH_VARARGS, "Encrypt password"},
{"crypt_gensalt_rn", _py_crypt_gensalt_rn, METH_VARARGS, "Generate salt"},
{NULL, NULL, 0, NULL}
static PyMethodDef _bcrypt_methods[] = {
{"crypt_rn", _py_crypt_rn, METH_VARARGS, "Encrypt password"},
{"crypt_gensalt_rn", _py_crypt_gensalt_rn, METH_VARARGS, "Generate salt"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
init_bcrypt(void)
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_bcrypt",
NULL,
-1,
_bcrypt_methods,
NULL,
NULL,
NULL,
NULL
};
#define INITERROR return NULL
PyObject *
PyInit__bcrypt(void)
#else
#define INITERROR return
PyMODINIT_FUNC
init_bcrypt(void)
#endif
{
(void) Py_InitModule("_bcrypt", BcryptMethods);
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_bcrypt", _bcrypt_methods);
#endif
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}

@@ -62,1 +62,23 @@ from nose.tools import eq_, raises, assert_false, assert_true, assert_not_equal

assert_true(manager.check(hash, password))
@raises(ValueError)
def test_fail_1(self):
def return_none(*args): return None
bcrypt = BCRYPTPasswordManager()
bcrypt.crypt_gensalt_rn = return_none
bcrypt.encode('foo')
@raises(ValueError)
def test_fail_2(self):
def return_none(*args): return None
bcrypt = BCRYPTPasswordManager()
bcrypt.crypt_rn = return_none
bcrypt.encode('foo')
@raises(ValueError)
def test_fail_3(self):
def return_none(*args): return None
bcrypt = BCRYPTPasswordManager()
pw = bcrypt.encode('foobar')
bcrypt.crypt_rn = return_none
bcrypt.check(pw, 'foo')

@@ -23,4 +23,20 @@ # -*- coding: utf-8 -*-

__all__ = ['DelegatingPasswordManager', 'PasswordChecker', 'PasswordManager']
__all__ = [
'DelegatingPasswordManager',
'PasswordChecker',
'PasswordManager',
'check_unicode'
]
if 'unicode' in __builtins__:
def check_unicode(text):
if isinstance(text, unicode):
text = text.encode('utf-8')
return text
else: # pragma NO COVERAGE
def check_unicode(text):
return text
class PasswordChecker(object):

@@ -36,3 +52,4 @@

strings. The schemes included with this package convert unicode
'encoded' and 'password' to utf-8 as necessary."""
'encoded' and 'password' to utf-8 as necessary.
"""
raise NotImplementedError()

@@ -46,8 +63,11 @@

class PasswordManager(PasswordChecker):
def encode(self, password):
"""Return hash of 'password' using this scheme."""
"""Return hash of 'password' using this scheme.
"""
raise NotImplementedError()
class DelegatingPasswordManager(object):

@@ -88,3 +108,4 @@

def _cmp(a, b):
"""Constant-time comparison"""
"""Constant-time comparison.
"""
if len(a) != len(b):

@@ -91,0 +112,0 @@ return False

@@ -36,7 +36,7 @@ # -*- coding: utf-8 -*-

__all__ = ['CRYPTPasswordManager', 'OLDCRYPT', 'MD5CRYPT', 'SHA256CRYPT',
'SHA512CRYPT', 'BCRYPT', 'available']
'SHA512CRYPT', 'BCRYPT']
import os
import re
import crypt
import crypt as system_crypt
import base64

@@ -52,18 +52,20 @@

def available(prefix, _crypt=crypt.crypt):
# Lame 'is implemented' check.
l = len(_crypt('implemented?', prefix + 'xyzzy'))
if prefix == OLDCRYPT:
if l != 13:
return False
elif l < 26:
return False
return True
class CRYPTPasswordManager(object):
_crypt = crypt.crypt
_crypt = staticmethod(system_crypt.crypt)
def available(self, prefix):
# Lame 'is implemented' check.
l = len(self._crypt('implemented?', prefix + 'xyzzy'))
if prefix == OLDCRYPT:
if l != 13:
return False
elif l < 26:
return False
return True
def __init__(self, prefix):
"""prefix: $1$ etc. indicating hashing scheme."""
self.PREFIX = prefix
if not available(prefix, self._crypt):
if not self.available(prefix):
raise NotImplementedError

@@ -70,0 +72,0 @@

@@ -53,2 +53,3 @@ from nose.tools import eq_, raises, assert_false, assert_true, assert_not_equal

available = CRYPTPasswordManager('').available

@@ -55,0 +56,0 @@ if available(BCRYPT):

@@ -30,3 +30,3 @@ # Copyright (c) 2009 Daniel Holth <dholth@fastmail.fm>

except (ImportError, AttributeError): # pragma NO COVERAGE
import pbkdf2
from . import pbkdf2
_pbkdf2 = pbkdf2.pbkdf2

@@ -33,0 +33,0 @@

@@ -1,4 +0,4 @@

Metadata-Version: 1.0
Metadata-Version: 1.1
Name: cryptacular
Version: 1.2.1
Version: 1.3
Summary: A password hashing framework with bcrypt and pbkdf2.

@@ -131,2 +131,7 @@ Home-page: http://bitbucket.org/dholth/cryptacular/

1.3
===
- Python 3 support contributed by Frank Smit (some tests do not run)
- Fix staticmethod issue with CRYPTPasswordManager
1.2.1

@@ -191,3 +196,10 @@ =====

Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: C
Classifier: Topic :: Security :: Cryptography

@@ -14,3 +14,3 @@ import os

setup(name='cryptacular',
version='1.2.1',
version='1.3',
description='A password hashing framework with bcrypt and pbkdf2.',

@@ -22,2 +22,9 @@ long_description=README + '\n\n' + CHANGES,

"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Programming Language :: C",

@@ -24,0 +31,0 @@ "Topic :: Security :: Cryptography",

Sorry, the diff of this file is not supported yet