├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── include └── bcrypt │ ├── BCrypt.hpp │ ├── bcrypt.h │ ├── crypt.h │ ├── crypt_blowfish.h │ ├── crypt_gensalt.h │ ├── ow-crypt.h │ └── winbcrypt.h ├── src ├── bcrypt.c ├── crypt_blowfish.c ├── crypt_gensalt.c ├── main.cpp ├── wrapper.c └── x86.S ├── vs2017 ├── libbcrypt │ ├── libbcrypt.sln │ ├── libbcrypt.vcxproj │ └── libbcrypt.vcxproj.filters └── test │ ├── main.cpp │ ├── test.vcxproj │ └── test.vcxproj.filters └── vs2019 ├── libbcrypt ├── libbcrypt.sln ├── libbcrypt.vcxproj └── libbcrypt.vcxproj.filters └── test ├── main.cpp ├── test.vcxproj └── test.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | CMakeCache.txt 3 | CMakeFiles/ 4 | CPackConfig.cmake 5 | CPackSourceConfig.cmake 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | 10 | 11 | **/Debug/ 12 | **/Release/ 13 | 14 | # User-specific files 15 | *.rsuser 16 | *.suo 17 | *.user 18 | *.userosscache 19 | *.sln.docstates 20 | 21 | # Visual Studio 2017 auto generated files 22 | Generated\ Files/ 23 | 24 | # Files built by Visual Studio 25 | *_i.c 26 | *_p.c 27 | *_h.h 28 | *.ilk 29 | *.meta 30 | *.obj 31 | *.iobj 32 | *.pch 33 | *.pdb 34 | *.ipdb 35 | *.pgc 36 | *.pgd 37 | *.rsp 38 | *.sbr 39 | *.tlb 40 | *.tli 41 | *.tlh 42 | *.tmp 43 | *.tmp_proj 44 | *_wpftmp.csproj 45 | *.log 46 | *.vspscc 47 | *.vssscc 48 | .builds 49 | *.pidb 50 | *.svclog 51 | *.scc 52 | 53 | # Visual C++ cache files 54 | ipch/ 55 | *.aps 56 | *.ncb 57 | *.opendb 58 | *.opensdf 59 | *.sdf 60 | *.cachefile 61 | *.VC.db 62 | *.VC.VC.opendb 63 | 64 | # Visual Studio profiler 65 | *.psess 66 | *.vsp 67 | *.vspx 68 | *.sap 69 | 70 | # Visual Studio Trace Files 71 | *.e2e 72 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################################### 2 | # 3 | # Copyright (c) 2014, webvariants GmbH, http://www.webvariants.de 4 | # 5 | # This file is released under the terms of the MIT license. You can find the 6 | # complete text in the attached LICENSE file or online at: 7 | # 8 | # http://www.opensource.org/licenses/mit-license.php 9 | # 10 | # @author: Tino Rusch (tino.rusch@webvariants.de) 11 | # 12 | ################################################################################### 13 | 14 | cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 15 | 16 | project(bcrypt) 17 | 18 | enable_language(ASM) 19 | 20 | set(MYLIB_VERSION_MAJOR 1) 21 | set(MYLIB_VERSION_MINOR 0) 22 | set(MYLIB_VERSION_PATCH 0) 23 | set(MYLIB_VERSION_STRING ${MYLIB_VERSION_MAJOR}.${MYLIB_VERSION_MINOR}.${MYLIB_VERSION_PATCH}) 24 | 25 | # just doing cmake . will build a shared or static lib and honor existing environment setting 26 | # to force build static, cmake . -DBUILD_SHARED_LIBS=Off 27 | # to force build shared, cmake . -DBUILD_SHARED_LIBS=On 28 | 29 | if (NOT BUILD_SHARED_LIBS) 30 | message ("Building a static library") 31 | else () 32 | message ("Building a shared library") 33 | endif () 34 | 35 | 36 | set( CMAKE_COLOR_MAKEFILE ON ) 37 | 38 | set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++11 -O3" ) 39 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3" ) 40 | 41 | set( CMAKE_ASM_FLAGS "${CXXFLAGS} -x assembler-with-cpp") 42 | 43 | set( SRCFILES 44 | ${CMAKE_CURRENT_SOURCE_DIR}/src/bcrypt.c 45 | ${CMAKE_CURRENT_SOURCE_DIR}/src/crypt_blowfish.c 46 | ${CMAKE_CURRENT_SOURCE_DIR}/src/crypt_gensalt.c 47 | ${CMAKE_CURRENT_SOURCE_DIR}/src/wrapper.c 48 | ${CMAKE_CURRENT_SOURCE_DIR}/src/x86.S 49 | ) 50 | 51 | if (NOT WIN32) 52 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include/bcrypt) 53 | endif() 54 | 55 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include) 56 | 57 | add_library( 58 | ${PROJECT_NAME} 59 | ${SRCFILES} 60 | ) 61 | 62 | set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${MYLIB_VERSION_STRING} SOVERSION ${MYLIB_VERSION_MAJOR}) 63 | 64 | set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER include/bcrypt/BCrypt.hpp) 65 | 66 | target_include_directories(${PROJECT_NAME} PRIVATE include) 67 | target_include_directories(${PROJECT_NAME} PRIVATE src) 68 | 69 | add_executable( ${PROJECT_NAME}_test ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) 70 | 71 | target_link_libraries( ${PROJECT_NAME}_test ${PROJECT_NAME}) 72 | 73 | include(GNUInstallDirs) 74 | 75 | install(TARGETS ${PROJECT_NAME} 76 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 77 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 78 | RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} 79 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/bcrypt) 80 | 81 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 82 | FILES_MATCHING PATTERN "*.h") 83 | 84 | SET(CPACK_GENERATOR "DEB") 85 | SET(CPACK_SET_DESTDIR ON) 86 | 87 | SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Manuel Romei") 88 | SET(CPACK_PACKAGE_VERSION "1.0.0") 89 | SET(CPACK_PACKAGE_VERSION_MAJOR "1") 90 | SET(CPACK_PACKAGE_VERSION_MINOR "0") 91 | SET(CPACK_PACKAGE_VERSION_PATCH "0") 92 | 93 | INCLUDE(CPack) 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 trusch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libbcrypt 2 | A c++ wrapper around bcrypt password hashing 3 | 4 | ## How to build this 5 | This is a CMake based project: 6 | 7 | ```bash 8 | git clone https://github.com/trusch/libbcrypt 9 | cd libbcrypt 10 | mkdir build 11 | cd build 12 | cmake .. 13 | make 14 | sudo make install 15 | sudo ldconfig 16 | ``` 17 | 18 | ## How to use this 19 | 20 | Here an example how to use this wrapper class (you can find a slightly edited example in src/ subdirectory) 21 | 22 | ```cpp 23 | #include "bcrypt/BCrypt.hpp" 24 | #include 25 | 26 | int main(){ 27 | std::string password = "test"; 28 | std::string hash = BCrypt::generateHash(password); 29 | 30 | std::cout << BCrypt::validatePassword(password,hash) << std::endl; 31 | std::cout << BCrypt::validatePassword("test1",hash) << std::endl; 32 | 33 | return 0; 34 | } 35 | ``` 36 | 37 | build this with something like this: 38 | 39 | ```bash 40 | g++ --std=c++11 -lbcrypt main.cpp 41 | ``` 42 | -------------------------------------------------------------------------------- /include/bcrypt/BCrypt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BCRYPT__ 2 | #define __BCRYPT__ 3 | 4 | #ifdef _WIN32 5 | #include "winbcrypt.h" 6 | #else 7 | 8 | #include "bcrypt.h" 9 | #include 10 | #include 11 | 12 | class BCrypt { 13 | public: 14 | static std::string generateHash(const std::string & password, int workload = 12){ 15 | char salt[BCRYPT_HASHSIZE]; 16 | char hash[BCRYPT_HASHSIZE]; 17 | int ret; 18 | ret = bcrypt_gensalt(workload, salt); 19 | if(ret != 0)throw std::runtime_error{"bcrypt: can not generate salt"}; 20 | ret = bcrypt_hashpw(password.c_str(), salt, hash); 21 | if(ret != 0)throw std::runtime_error{"bcrypt: can not generate hash"}; 22 | return std::string{hash}; 23 | } 24 | 25 | static bool validatePassword(const std::string & password, const std::string & hash){ 26 | return (bcrypt_checkpw(password.c_str(), hash.c_str()) == 0); 27 | } 28 | }; 29 | 30 | #endif 31 | 32 | #endif // __BCRYPT__ 33 | -------------------------------------------------------------------------------- /include/bcrypt/bcrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef BCRYPT_H_ 2 | #define BCRYPT_H_ 3 | /* 4 | * bcrypt wrapper library 5 | * 6 | * Written in 2011, 2013, 2014, 2015 by Ricardo Garcia 7 | * 8 | * To the extent possible under law, the author(s) have dedicated all copyright 9 | * and related and neighboring rights to this software to the public domain 10 | * worldwide. This software is distributed without any warranty. 11 | * 12 | * You should have received a copy of the CC0 Public Domain Dedication along 13 | * with this software. If not, see 14 | * . 15 | */ 16 | 17 | #define BCRYPT_HASHSIZE (64) 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* 24 | * This function expects a work factor between 4 and 31 and a char array to 25 | * store the resulting generated salt. The char array should typically have 26 | * BCRYPT_HASHSIZE bytes at least. If the provided work factor is not in the 27 | * previous range, it will default to 12. 28 | * 29 | * The return value is zero if the salt could be correctly generated and 30 | * nonzero otherwise. 31 | * 32 | */ 33 | int bcrypt_gensalt(int workfactor, char salt[BCRYPT_HASHSIZE]); 34 | 35 | /* 36 | * This function expects a password to be hashed, a salt to hash the password 37 | * with and a char array to leave the result. Both the salt and the hash 38 | * parameters should have room for BCRYPT_HASHSIZE characters at least. 39 | * 40 | * It can also be used to verify a hashed password. In that case, provide the 41 | * expected hash in the salt parameter and verify the output hash is the same 42 | * as the input hash. However, to avoid timing attacks, it's better to use 43 | * bcrypt_checkpw when verifying a password. 44 | * 45 | * The return value is zero if the password could be hashed and nonzero 46 | * otherwise. 47 | */ 48 | int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], 49 | char hash[BCRYPT_HASHSIZE]); 50 | 51 | /* 52 | * This function expects a password and a hash to verify the password against. 53 | * The internal implementation is tuned to avoid timing attacks. 54 | * 55 | * The return value will be -1 in case of errors, zero if the provided password 56 | * matches the given hash and greater than zero if no errors are found and the 57 | * passwords don't match. 58 | * 59 | */ 60 | int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]); 61 | 62 | /* 63 | * Brief Example 64 | * ------------- 65 | * 66 | * Hashing a password: 67 | * 68 | * char salt[BCRYPT_HASHSIZE]; 69 | * char hash[BCRYPT_HASHSIZE]; 70 | * int ret; 71 | * 72 | * ret = bcrypt_gensalt(12, salt); 73 | * assert(ret == 0); 74 | * ret = bcrypt_hashpw("thepassword", salt, hash); 75 | * assert(ret == 0); 76 | * 77 | * 78 | * Verifying a password: 79 | * 80 | * int ret; 81 | * 82 | * ret = bcrypt_checkpw("thepassword", "expectedhash"); 83 | * assert(ret != -1); 84 | * 85 | * if (ret == 0) { 86 | * printf("The password matches\n"); 87 | * } else { 88 | * printf("The password does NOT match\n"); 89 | * } 90 | * 91 | */ 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /include/bcrypt/crypt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2002. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2002 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #include 18 | 19 | #if defined(_OW_SOURCE) || defined(__USE_OW) 20 | #define __SKIP_GNU 21 | #undef __SKIP_OW 22 | #include 23 | #undef __SKIP_GNU 24 | #endif 25 | -------------------------------------------------------------------------------- /include/bcrypt/crypt_blowfish.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2011. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #ifndef _CRYPT_BLOWFISH_H 18 | #define _CRYPT_BLOWFISH_H 19 | 20 | extern int _crypt_output_magic(const char *setting, char *output, int size); 21 | extern char *_crypt_blowfish_rn(const char *key, const char *setting, 22 | char *output, int size); 23 | extern char *_crypt_gensalt_blowfish_rn(const char *prefix, 24 | unsigned long count, 25 | const char *input, int size, char *output, int output_size); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/bcrypt/crypt_gensalt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2011. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #ifndef _CRYPT_GENSALT_H 18 | #define _CRYPT_GENSALT_H 19 | 20 | extern unsigned char _crypt_itoa64[]; 21 | extern char *_crypt_gensalt_traditional_rn(const char *prefix, 22 | unsigned long count, 23 | const char *input, int size, char *output, int output_size); 24 | extern char *_crypt_gensalt_extended_rn(const char *prefix, 25 | unsigned long count, 26 | const char *input, int size, char *output, int output_size); 27 | extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, 28 | const char *input, int size, char *output, int output_size); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/bcrypt/ow-crypt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2011. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #ifndef _OW_CRYPT_H 18 | #define _OW_CRYPT_H 19 | 20 | #ifndef __GNUC__ 21 | #undef __const 22 | #define __const const 23 | #endif 24 | 25 | #if __FreeBSD__ 26 | #include 27 | #if __FreeBSD_version >= 1200000 28 | #define __SKIP_GNU 29 | #endif 30 | #endif 31 | 32 | #ifndef __SKIP_GNU 33 | extern char *crypt(__const char *key, __const char *setting); 34 | extern char *crypt_r(__const char *key, __const char *setting, void *data); 35 | #endif 36 | 37 | #ifndef __SKIP_OW 38 | extern char *crypt_rn(__const char *key, __const char *setting, 39 | void *data, int size); 40 | extern char *crypt_ra(__const char *key, __const char *setting, 41 | void **data, int *size); 42 | extern char *crypt_gensalt(__const char *prefix, unsigned long count, 43 | __const char *input, int size); 44 | extern char *crypt_gensalt_rn(__const char *prefix, unsigned long count, 45 | __const char *input, int size, char *output, int output_size); 46 | extern char *crypt_gensalt_ra(__const char *prefix, unsigned long count, 47 | __const char *input, int size); 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/bcrypt/winbcrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef __WIN_BCRYPT__H 2 | #define __WIN_BCRYPT__H 3 | 4 | #include 5 | 6 | #include "crypt_blowfish.h" 7 | #include "./bcrypt.h" 8 | 9 | class BCrypt { 10 | public: 11 | static std::string generateHash(const std::string & password, int workload = 12) { 12 | char salt[BCRYPT_HASHSIZE]; 13 | char hash[BCRYPT_HASHSIZE]; 14 | int ret; 15 | ret = bcrypt_gensalt(workload, salt); 16 | if (ret != 0)throw std::runtime_error{ "bcrypt: can not generate salt" }; 17 | ret = bcrypt_hashpw(password.c_str(), salt, hash); 18 | if (ret != 0)throw std::runtime_error{ "bcrypt: can not generate hash" }; 19 | return std::string{ hash }; 20 | } 21 | 22 | static bool validatePassword(const std::string & password, const std::string & hash) { 23 | return (bcrypt_checkpw(password.c_str(), hash.c_str()) == 0); 24 | } 25 | }; 26 | 27 | #endif -------------------------------------------------------------------------------- /src/bcrypt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * bcrypt wrapper library 3 | * 4 | * Written in 2011, 2013, 2014, 2015 by Ricardo Garcia 5 | * 6 | * To the extent possible under law, the author(s) have dedicated all copyright 7 | * and related and neighboring rights to this software to the public domain 8 | * worldwide. This software is distributed without any warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication along 11 | * with this software. If not, see 12 | * . 13 | */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #ifdef _WIN32 19 | #elif _WIN64 20 | #else 21 | #include 22 | #endif 23 | #include 24 | 25 | #if defined(_WIN32) || defined(_WIN64) 26 | // On windows we need to generate random bytes differently. 27 | #if defined(_WIN32) && !defined(_WIN64) 28 | typedef __int32 ssize_t; 29 | #elif defined(_WIN32) && defined(_WIN64) 30 | typedef __int64 ssize_t; 31 | #endif 32 | #define BCRYPT_HASHSIZE 60 33 | 34 | #include "../include/bcrypt/bcrypt.h" 35 | 36 | #include 37 | #include /* CryptAcquireContext, CryptGenRandom */ 38 | #else 39 | #include "bcrypt.h" 40 | #include "ow-crypt.h" 41 | #endif 42 | 43 | #define RANDBYTES (16) 44 | 45 | static int try_close(int fd) 46 | { 47 | int ret; 48 | for (;;) { 49 | errno = 0; 50 | ret = close(fd); 51 | if (ret == -1 && errno == EINTR) 52 | continue; 53 | break; 54 | } 55 | return ret; 56 | } 57 | 58 | static int try_read(int fd, char *out, size_t count) 59 | { 60 | size_t total; 61 | ssize_t partial; 62 | 63 | total = 0; 64 | while (total < count) 65 | { 66 | for (;;) { 67 | errno = 0; 68 | partial = read(fd, out + total, count - total); 69 | if (partial == -1 && errno == EINTR) 70 | continue; 71 | break; 72 | } 73 | 74 | if (partial < 1) 75 | return -1; 76 | 77 | total += partial; 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | /* 84 | * This is a best effort implementation. Nothing prevents a compiler from 85 | * optimizing this function and making it vulnerable to timing attacks, but 86 | * this method is commonly used in crypto libraries like NaCl. 87 | * 88 | * Return value is zero if both strings are equal and nonzero otherwise. 89 | */ 90 | static int timing_safe_strcmp(const char *str1, const char *str2) 91 | { 92 | const unsigned char *u1; 93 | const unsigned char *u2; 94 | int ret; 95 | int i; 96 | 97 | int len1 = strlen(str1); 98 | int len2 = strlen(str2); 99 | 100 | /* In our context both strings should always have the same length 101 | * because they will be hashed passwords. */ 102 | if (len1 != len2) 103 | return 1; 104 | 105 | /* Force unsigned for bitwise operations. */ 106 | u1 = (const unsigned char *)str1; 107 | u2 = (const unsigned char *)str2; 108 | 109 | ret = 0; 110 | for (i = 0; i < len1; ++i) 111 | ret |= (u1[i] ^ u2[i]); 112 | 113 | return ret; 114 | } 115 | 116 | int bcrypt_gensalt(int factor, char salt[BCRYPT_HASHSIZE]) 117 | { 118 | int fd; 119 | char input[RANDBYTES]; 120 | int workf; 121 | char *aux; 122 | 123 | // Note: Windows does not have /dev/urandom sadly. 124 | #if defined(_WIN32) || defined(_WIN64) 125 | HCRYPTPROV p; 126 | ULONG i; 127 | 128 | // Acquire a crypt context for generating random bytes. 129 | if (CryptAcquireContext(&p, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { 130 | return 1; 131 | } 132 | 133 | if (CryptGenRandom(p, RANDBYTES, (BYTE*)input) == FALSE) { 134 | return 2; 135 | } 136 | 137 | if (CryptReleaseContext(p, 0) == FALSE) { 138 | return 3; 139 | } 140 | #else 141 | // Get random bytes on Unix/Linux. 142 | fd = open("/dev/urandom", O_RDONLY); 143 | if (fd == -1) 144 | return 1; 145 | 146 | if (try_read(fd, input, RANDBYTES) != 0) { 147 | if (try_close(fd) != 0) 148 | return 4; 149 | return 2; 150 | } 151 | 152 | if (try_close(fd) != 0) 153 | return 3; 154 | #endif 155 | 156 | /* Generate salt. */ 157 | workf = (factor < 4 || factor > 31)?12:factor; 158 | aux = crypt_gensalt_rn("$2a$", workf, input, RANDBYTES, 159 | salt, BCRYPT_HASHSIZE); 160 | return (aux == NULL)?5:0; 161 | } 162 | 163 | int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) 164 | { 165 | char *aux; 166 | aux = crypt_rn(passwd, salt, hash, BCRYPT_HASHSIZE); 167 | return (aux == NULL)?1:0; 168 | } 169 | 170 | int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]) 171 | { 172 | int ret; 173 | char outhash[BCRYPT_HASHSIZE]; 174 | 175 | ret = bcrypt_hashpw(passwd, hash, outhash); 176 | if (ret != 0) 177 | return -1; 178 | 179 | return timing_safe_strcmp(hash, outhash); 180 | } 181 | 182 | #ifdef TEST_BCRYPT 183 | #include 184 | #include 185 | #include 186 | #include 187 | 188 | int main(void) 189 | { 190 | clock_t before; 191 | clock_t after; 192 | char salt[BCRYPT_HASHSIZE]; 193 | char hash[BCRYPT_HASHSIZE]; 194 | int ret; 195 | 196 | const char pass[] = "hi,mom"; 197 | const char hash1[] = "$2a$10$VEVmGHy4F4XQMJ3eOZJAUeb.MedU0W10pTPCuf53eHdKJPiSE8sMK"; 198 | const char hash2[] = "$2a$10$3F0BVk5t8/aoS.3ddaB3l.fxg5qvafQ9NybxcpXLzMeAt.nVWn.NO"; 199 | 200 | ret = bcrypt_gensalt(12, salt); 201 | assert(ret == 0); 202 | printf("Generated salt: %s\n", salt); 203 | before = clock(); 204 | ret = bcrypt_hashpw("testtesttest", salt, hash); 205 | assert(ret == 0); 206 | after = clock(); 207 | printf("Hashed password: %s\n", hash); 208 | printf("Time taken: %f seconds\n", 209 | (double)(after - before) / CLOCKS_PER_SEC); 210 | 211 | ret = bcrypt_hashpw(pass, hash1, hash); 212 | assert(ret == 0); 213 | printf("First hash check: %s\n", (strcmp(hash1, hash) == 0)?"OK":"FAIL"); 214 | ret = bcrypt_hashpw(pass, hash2, hash); 215 | assert(ret == 0); 216 | printf("Second hash check: %s\n", (strcmp(hash2, hash) == 0)?"OK":"FAIL"); 217 | 218 | before = clock(); 219 | ret = (bcrypt_checkpw(pass, hash1) == 0); 220 | after = clock(); 221 | printf("First hash check with bcrypt_checkpw: %s\n", ret?"OK":"FAIL"); 222 | printf("Time taken: %f seconds\n", 223 | (double)(after - before) / CLOCKS_PER_SEC); 224 | 225 | before = clock(); 226 | ret = (bcrypt_checkpw(pass, hash2) == 0); 227 | after = clock(); 228 | printf("Second hash check with bcrypt_checkpw: %s\n", ret?"OK":"FAIL"); 229 | printf("Time taken: %f seconds\n", 230 | (double)(after - before) / CLOCKS_PER_SEC); 231 | 232 | return 0; 233 | } 234 | #endif 235 | -------------------------------------------------------------------------------- /src/crypt_blowfish.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The crypt_blowfish homepage is: 3 | * 4 | * http://www.openwall.com/crypt/ 5 | * 6 | * This code comes from John the Ripper password cracker, with reentrant 7 | * and crypt(3) interfaces added, but optimizations specific to password 8 | * cracking removed. 9 | * 10 | * Written by Solar Designer in 1998-2014. 11 | * No copyright is claimed, and the software is hereby placed in the public 12 | * domain. In case this attempt to disclaim copyright and place the software 13 | * in the public domain is deemed null and void, then the software is 14 | * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the 15 | * general public under the following terms: 16 | * 17 | * Redistribution and use in source and binary forms, with or without 18 | * modification, are permitted. 19 | * 20 | * There's ABSOLUTELY NO WARRANTY, express or implied. 21 | * 22 | * It is my intent that you should be able to use this on your system, 23 | * as part of a software package, or anywhere else to improve security, 24 | * ensure compatibility, or for any other purpose. I would appreciate 25 | * it if you give credit where it is due and keep your modifications in 26 | * the public domain as well, but I don't require that in order to let 27 | * you place this code and any modifications you make under a license 28 | * of your choice. 29 | * 30 | * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix 31 | * "$2b$", originally by Niels Provos , and it uses 32 | * some of his ideas. The password hashing algorithm was designed by David 33 | * Mazieres . For information on the level of 34 | * compatibility for bcrypt hash prefixes other than "$2b$", please refer to 35 | * the comments in BF_set_key() below and to the included crypt(3) man page. 36 | * 37 | * There's a paper on the algorithm that explains its design decisions: 38 | * 39 | * http://www.usenix.org/events/usenix99/provos.html 40 | * 41 | * Some of the tricks in BF_ROUND might be inspired by Eric Young's 42 | * Blowfish library (I can't be sure if I would think of something if I 43 | * hadn't seen his code). 44 | */ 45 | 46 | #include 47 | 48 | #include 49 | #ifndef __set_errno 50 | #define __set_errno(val) errno = (val) 51 | #endif 52 | 53 | /* Just to make sure the prototypes match the actual definitions */ 54 | #if defined(_WIN32) || defined(_WIN64) 55 | #include "../include/bcrypt/crypt_blowfish.h" 56 | #else 57 | #include "crypt_blowfish.h" 58 | #endif 59 | 60 | #ifdef __i386__ 61 | #define BF_ASM 1 62 | #define BF_SCALE 1 63 | #elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__) 64 | #define BF_ASM 0 65 | #define BF_SCALE 1 66 | #else 67 | #define BF_ASM 0 68 | #define BF_SCALE 0 69 | #endif 70 | 71 | typedef unsigned int BF_word; 72 | typedef signed int BF_word_signed; 73 | 74 | /* Number of Blowfish rounds, this is also hardcoded into a few places */ 75 | #define BF_N 16 76 | 77 | typedef BF_word BF_key[BF_N + 2]; 78 | 79 | typedef struct { 80 | BF_word S[4][0x100]; 81 | BF_key P; 82 | } BF_ctx; 83 | 84 | /* 85 | * Magic IV for 64 Blowfish encryptions that we do at the end. 86 | * The string is "OrpheanBeholderScryDoubt" on big-endian. 87 | */ 88 | static BF_word BF_magic_w[6] = { 89 | 0x4F727068, 0x65616E42, 0x65686F6C, 90 | 0x64657253, 0x63727944, 0x6F756274 91 | }; 92 | 93 | /* 94 | * P-box and S-box tables initialized with digits of Pi. 95 | */ 96 | static BF_ctx BF_init_state = { 97 | { 98 | { 99 | 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 100 | 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 101 | 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 102 | 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 103 | 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 104 | 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 105 | 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 106 | 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 107 | 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 108 | 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 109 | 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 110 | 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 111 | 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 112 | 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 113 | 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 114 | 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 115 | 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 116 | 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 117 | 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 118 | 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 119 | 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 120 | 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 121 | 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 122 | 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 123 | 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 124 | 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 125 | 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 126 | 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 127 | 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 128 | 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 129 | 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 130 | 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 131 | 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 132 | 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 133 | 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 134 | 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 135 | 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 136 | 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 137 | 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 138 | 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 139 | 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 140 | 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 141 | 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 142 | 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 143 | 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 144 | 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 145 | 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 146 | 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 147 | 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 148 | 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 149 | 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 150 | 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 151 | 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 152 | 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 153 | 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 154 | 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 155 | 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 156 | 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 157 | 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 158 | 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 159 | 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 160 | 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 161 | 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 162 | 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a 163 | }, { 164 | 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 165 | 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 166 | 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 167 | 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 168 | 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 169 | 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 170 | 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 171 | 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 172 | 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 173 | 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 174 | 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 175 | 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 176 | 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 177 | 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 178 | 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 179 | 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 180 | 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 181 | 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 182 | 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 183 | 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 184 | 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 185 | 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 186 | 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 187 | 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 188 | 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 189 | 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 190 | 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 191 | 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 192 | 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 193 | 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 194 | 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 195 | 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 196 | 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 197 | 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 198 | 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 199 | 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 200 | 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 201 | 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 202 | 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 203 | 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 204 | 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 205 | 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 206 | 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 207 | 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 208 | 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 209 | 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 210 | 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 211 | 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 212 | 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 213 | 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 214 | 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 215 | 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 216 | 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 217 | 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 218 | 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 219 | 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 220 | 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 221 | 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 222 | 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 223 | 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 224 | 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 225 | 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 226 | 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 227 | 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 228 | }, { 229 | 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 230 | 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 231 | 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 232 | 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 233 | 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 234 | 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 235 | 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 236 | 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 237 | 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 238 | 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 239 | 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 240 | 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 241 | 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 242 | 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 243 | 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 244 | 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 245 | 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 246 | 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 247 | 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 248 | 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 249 | 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 250 | 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 251 | 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 252 | 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 253 | 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 254 | 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 255 | 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 256 | 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 257 | 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 258 | 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 259 | 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 260 | 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 261 | 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 262 | 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 263 | 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 264 | 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 265 | 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 266 | 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 267 | 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 268 | 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 269 | 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 270 | 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 271 | 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 272 | 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 273 | 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 274 | 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 275 | 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 276 | 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 277 | 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 278 | 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 279 | 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 280 | 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 281 | 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 282 | 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 283 | 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 284 | 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 285 | 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 286 | 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 287 | 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 288 | 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 289 | 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 290 | 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 291 | 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 292 | 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 293 | }, { 294 | 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 295 | 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 296 | 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 297 | 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 298 | 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 299 | 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 300 | 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 301 | 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 302 | 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 303 | 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 304 | 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 305 | 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 306 | 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 307 | 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 308 | 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 309 | 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 310 | 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 311 | 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 312 | 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 313 | 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 314 | 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 315 | 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 316 | 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 317 | 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 318 | 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 319 | 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 320 | 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 321 | 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 322 | 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 323 | 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 324 | 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 325 | 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 326 | 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 327 | 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 328 | 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 329 | 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 330 | 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 331 | 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 332 | 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 333 | 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 334 | 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 335 | 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 336 | 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 337 | 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 338 | 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 339 | 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 340 | 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 341 | 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 342 | 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 343 | 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 344 | 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 345 | 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 346 | 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 347 | 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 348 | 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 349 | 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 350 | 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 351 | 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 352 | 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 353 | 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 354 | 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 355 | 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 356 | 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 357 | 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 358 | } 359 | }, { 360 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 361 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 362 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 363 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 364 | 0x9216d5d9, 0x8979fb1b 365 | } 366 | }; 367 | 368 | static unsigned char BF_itoa64[64 + 1] = 369 | "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 370 | 371 | static unsigned char BF_atoi64[0x60] = { 372 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, 373 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, 374 | 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 375 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, 376 | 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 377 | 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 378 | }; 379 | 380 | #define BF_safe_atoi64(dst, src) \ 381 | { \ 382 | tmp = (unsigned char)(src); \ 383 | if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ 384 | tmp = BF_atoi64[tmp]; \ 385 | if (tmp > 63) return -1; \ 386 | (dst) = tmp; \ 387 | } 388 | 389 | static int BF_decode(BF_word *dst, const char *src, int size) 390 | { 391 | unsigned char *dptr = (unsigned char *)dst; 392 | unsigned char *end = dptr + size; 393 | const unsigned char *sptr = (const unsigned char *)src; 394 | unsigned int tmp, c1, c2, c3, c4; 395 | 396 | do { 397 | BF_safe_atoi64(c1, *sptr++); 398 | BF_safe_atoi64(c2, *sptr++); 399 | *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); 400 | if (dptr >= end) break; 401 | 402 | BF_safe_atoi64(c3, *sptr++); 403 | *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); 404 | if (dptr >= end) break; 405 | 406 | BF_safe_atoi64(c4, *sptr++); 407 | *dptr++ = ((c3 & 0x03) << 6) | c4; 408 | } while (dptr < end); 409 | 410 | return 0; 411 | } 412 | 413 | static void BF_encode(char *dst, const BF_word *src, int size) 414 | { 415 | const unsigned char *sptr = (const unsigned char *)src; 416 | const unsigned char *end = sptr + size; 417 | unsigned char *dptr = (unsigned char *)dst; 418 | unsigned int c1, c2; 419 | 420 | do { 421 | c1 = *sptr++; 422 | *dptr++ = BF_itoa64[c1 >> 2]; 423 | c1 = (c1 & 0x03) << 4; 424 | if (sptr >= end) { 425 | *dptr++ = BF_itoa64[c1]; 426 | break; 427 | } 428 | 429 | c2 = *sptr++; 430 | c1 |= c2 >> 4; 431 | *dptr++ = BF_itoa64[c1]; 432 | c1 = (c2 & 0x0f) << 2; 433 | if (sptr >= end) { 434 | *dptr++ = BF_itoa64[c1]; 435 | break; 436 | } 437 | 438 | c2 = *sptr++; 439 | c1 |= c2 >> 6; 440 | *dptr++ = BF_itoa64[c1]; 441 | *dptr++ = BF_itoa64[c2 & 0x3f]; 442 | } while (sptr < end); 443 | } 444 | 445 | static void BF_swap(BF_word *x, int count) 446 | { 447 | static int endianness_check = 1; 448 | char *is_little_endian = (char *)&endianness_check; 449 | BF_word tmp; 450 | 451 | if (*is_little_endian) 452 | do { 453 | tmp = *x; 454 | tmp = (tmp << 16) | (tmp >> 16); 455 | *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); 456 | } while (--count); 457 | } 458 | 459 | #if BF_SCALE 460 | /* Architectures which can shift addresses left by 2 bits with no extra cost */ 461 | #define BF_ROUND(L, R, N) \ 462 | tmp1 = L & 0xFF; \ 463 | tmp2 = L >> 8; \ 464 | tmp2 &= 0xFF; \ 465 | tmp3 = L >> 16; \ 466 | tmp3 &= 0xFF; \ 467 | tmp4 = L >> 24; \ 468 | tmp1 = data.ctx.S[3][tmp1]; \ 469 | tmp2 = data.ctx.S[2][tmp2]; \ 470 | tmp3 = data.ctx.S[1][tmp3]; \ 471 | tmp3 += data.ctx.S[0][tmp4]; \ 472 | tmp3 ^= tmp2; \ 473 | R ^= data.ctx.P[N + 1]; \ 474 | tmp3 += tmp1; \ 475 | R ^= tmp3; 476 | #else 477 | /* Architectures with no complicated addressing modes supported */ 478 | #define BF_INDEX(S, i) \ 479 | (*((BF_word *)(((unsigned char *)S) + (i)))) 480 | #define BF_ROUND(L, R, N) \ 481 | tmp1 = L & 0xFF; \ 482 | tmp1 <<= 2; \ 483 | tmp2 = L >> 6; \ 484 | tmp2 &= 0x3FC; \ 485 | tmp3 = L >> 14; \ 486 | tmp3 &= 0x3FC; \ 487 | tmp4 = L >> 22; \ 488 | tmp4 &= 0x3FC; \ 489 | tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \ 490 | tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \ 491 | tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \ 492 | tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \ 493 | tmp3 ^= tmp2; \ 494 | R ^= data.ctx.P[N + 1]; \ 495 | tmp3 += tmp1; \ 496 | R ^= tmp3; 497 | #endif 498 | 499 | /* 500 | * Encrypt one block, BF_N is hardcoded here. 501 | */ 502 | #define BF_ENCRYPT \ 503 | L ^= data.ctx.P[0]; \ 504 | BF_ROUND(L, R, 0); \ 505 | BF_ROUND(R, L, 1); \ 506 | BF_ROUND(L, R, 2); \ 507 | BF_ROUND(R, L, 3); \ 508 | BF_ROUND(L, R, 4); \ 509 | BF_ROUND(R, L, 5); \ 510 | BF_ROUND(L, R, 6); \ 511 | BF_ROUND(R, L, 7); \ 512 | BF_ROUND(L, R, 8); \ 513 | BF_ROUND(R, L, 9); \ 514 | BF_ROUND(L, R, 10); \ 515 | BF_ROUND(R, L, 11); \ 516 | BF_ROUND(L, R, 12); \ 517 | BF_ROUND(R, L, 13); \ 518 | BF_ROUND(L, R, 14); \ 519 | BF_ROUND(R, L, 15); \ 520 | tmp4 = R; \ 521 | R = L; \ 522 | L = tmp4 ^ data.ctx.P[BF_N + 1]; 523 | 524 | #if BF_ASM 525 | #define BF_body() \ 526 | _BF_body_r(&data.ctx); 527 | #else 528 | #define BF_body() \ 529 | L = R = 0; \ 530 | ptr = data.ctx.P; \ 531 | do { \ 532 | ptr += 2; \ 533 | BF_ENCRYPT; \ 534 | *(ptr - 2) = L; \ 535 | *(ptr - 1) = R; \ 536 | } while (ptr < &data.ctx.P[BF_N + 2]); \ 537 | \ 538 | ptr = data.ctx.S[0]; \ 539 | do { \ 540 | ptr += 2; \ 541 | BF_ENCRYPT; \ 542 | *(ptr - 2) = L; \ 543 | *(ptr - 1) = R; \ 544 | } while (ptr < &data.ctx.S[3][0xFF]); 545 | #endif 546 | 547 | static void BF_set_key(const char *key, BF_key expanded, BF_key initial, 548 | unsigned char flags) 549 | { 550 | const char *ptr = key; 551 | unsigned int bug, i, j; 552 | BF_word safety, sign, diff, tmp[2]; 553 | 554 | /* 555 | * There was a sign extension bug in older revisions of this function. While 556 | * we would have liked to simply fix the bug and move on, we have to provide 557 | * a backwards compatibility feature (essentially the bug) for some systems and 558 | * a safety measure for some others. The latter is needed because for certain 559 | * multiple inputs to the buggy algorithm there exist easily found inputs to 560 | * the correct algorithm that produce the same hash. Thus, we optionally 561 | * deviate from the correct algorithm just enough to avoid such collisions. 562 | * While the bug itself affected the majority of passwords containing 563 | * characters with the 8th bit set (although only a percentage of those in a 564 | * collision-producing way), the anti-collision safety measure affects 565 | * only a subset of passwords containing the '\xff' character (not even all of 566 | * those passwords, just some of them). This character is not found in valid 567 | * UTF-8 sequences and is rarely used in popular 8-bit character encodings. 568 | * Thus, the safety measure is unlikely to cause much annoyance, and is a 569 | * reasonable tradeoff to use when authenticating against existing hashes that 570 | * are not reliably known to have been computed with the correct algorithm. 571 | * 572 | * We use an approach that tries to minimize side-channel leaks of password 573 | * information - that is, we mostly use fixed-cost bitwise operations instead 574 | * of branches or table lookups. (One conditional branch based on password 575 | * length remains. It is not part of the bug aftermath, though, and is 576 | * difficult and possibly unreasonable to avoid given the use of C strings by 577 | * the caller, which results in similar timing leaks anyway.) 578 | * 579 | * For actual implementation, we set an array index in the variable "bug" 580 | * (0 means no bug, 1 means sign extension bug emulation) and a flag in the 581 | * variable "safety" (bit 16 is set when the safety measure is requested). 582 | * Valid combinations of settings are: 583 | * 584 | * Prefix "$2a$": bug = 0, safety = 0x10000 585 | * Prefix "$2b$": bug = 0, safety = 0 586 | * Prefix "$2x$": bug = 1, safety = 0 587 | * Prefix "$2y$": bug = 0, safety = 0 588 | */ 589 | bug = (unsigned int)flags & 1; 590 | safety = ((BF_word)flags & 2) << 15; 591 | 592 | sign = diff = 0; 593 | 594 | for (i = 0; i < BF_N + 2; i++) { 595 | tmp[0] = tmp[1] = 0; 596 | for (j = 0; j < 4; j++) { 597 | tmp[0] <<= 8; 598 | tmp[0] |= (unsigned char)*ptr; /* correct */ 599 | tmp[1] <<= 8; 600 | tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */ 601 | /* 602 | * Sign extension in the first char has no effect - nothing to overwrite yet, 603 | * and those extra 24 bits will be fully shifted out of the 32-bit word. For 604 | * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign 605 | * extension in tmp[1] occurs. Once this flag is set, it remains set. 606 | */ 607 | if (j) 608 | sign |= tmp[1] & 0x80; 609 | if (!*ptr) 610 | ptr = key; 611 | else 612 | ptr++; 613 | } 614 | diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */ 615 | 616 | expanded[i] = tmp[bug]; 617 | initial[i] = BF_init_state.P[i] ^ tmp[bug]; 618 | } 619 | 620 | /* 621 | * At this point, "diff" is zero iff the correct and buggy algorithms produced 622 | * exactly the same result. If so and if "sign" is non-zero, which indicates 623 | * that there was a non-benign sign extension, this means that we have a 624 | * collision between the correctly computed hash for this password and a set of 625 | * passwords that could be supplied to the buggy algorithm. Our safety measure 626 | * is meant to protect from such many-buggy to one-correct collisions, by 627 | * deviating from the correct algorithm in such cases. Let's check for this. 628 | */ 629 | diff |= diff >> 16; /* still zero iff exact match */ 630 | diff &= 0xffff; /* ditto */ 631 | diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */ 632 | sign <<= 9; /* move the non-benign sign extension flag to bit 16 */ 633 | sign &= ~diff & safety; /* action needed? */ 634 | 635 | /* 636 | * If we have determined that we need to deviate from the correct algorithm, 637 | * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but 638 | * let's stick to it now. It came out of the approach we used above, and it's 639 | * not any worse than any other choice we could make.) 640 | * 641 | * It is crucial that we don't do the same to the expanded key used in the main 642 | * Eksblowfish loop. By doing it to only one of these two, we deviate from a 643 | * state that could be directly specified by a password to the buggy algorithm 644 | * (and to the fully correct one as well, but that's a side-effect). 645 | */ 646 | initial[0] ^= sign; 647 | } 648 | 649 | static const unsigned char flags_by_subtype[26] = 650 | {2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 651 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0}; 652 | 653 | static char *BF_crypt(const char *key, const char *setting, 654 | char *output, int size, 655 | BF_word min) 656 | { 657 | #if BF_ASM 658 | extern void _BF_body_r(BF_ctx *ctx); 659 | #endif 660 | struct { 661 | BF_ctx ctx; 662 | BF_key expanded_key; 663 | union { 664 | BF_word salt[4]; 665 | BF_word output[6]; 666 | } binary; 667 | } data; 668 | BF_word L, R; 669 | BF_word tmp1, tmp2, tmp3, tmp4; 670 | BF_word *ptr; 671 | BF_word count; 672 | int i; 673 | 674 | if (size < 7 + 22 + 31 + 1) { 675 | __set_errno(ERANGE); 676 | return NULL; 677 | } 678 | 679 | if (setting[0] != '$' || 680 | setting[1] != '2' || 681 | setting[2] < 'a' || setting[2] > 'z' || 682 | !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] || 683 | setting[3] != '$' || 684 | setting[4] < '0' || setting[4] > '3' || 685 | setting[5] < '0' || setting[5] > '9' || 686 | (setting[4] == '3' && setting[5] > '1') || 687 | setting[6] != '$') { 688 | __set_errno(EINVAL); 689 | return NULL; 690 | } 691 | 692 | count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); 693 | if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) { 694 | __set_errno(EINVAL); 695 | return NULL; 696 | } 697 | BF_swap(data.binary.salt, 4); 698 | 699 | BF_set_key(key, data.expanded_key, data.ctx.P, 700 | flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']); 701 | 702 | memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S)); 703 | 704 | L = R = 0; 705 | for (i = 0; i < BF_N + 2; i += 2) { 706 | L ^= data.binary.salt[i & 2]; 707 | R ^= data.binary.salt[(i & 2) + 1]; 708 | BF_ENCRYPT; 709 | data.ctx.P[i] = L; 710 | data.ctx.P[i + 1] = R; 711 | } 712 | 713 | ptr = data.ctx.S[0]; 714 | do { 715 | ptr += 4; 716 | L ^= data.binary.salt[(BF_N + 2) & 3]; 717 | R ^= data.binary.salt[(BF_N + 3) & 3]; 718 | BF_ENCRYPT; 719 | *(ptr - 4) = L; 720 | *(ptr - 3) = R; 721 | 722 | L ^= data.binary.salt[(BF_N + 4) & 3]; 723 | R ^= data.binary.salt[(BF_N + 5) & 3]; 724 | BF_ENCRYPT; 725 | *(ptr - 2) = L; 726 | *(ptr - 1) = R; 727 | } while (ptr < &data.ctx.S[3][0xFF]); 728 | 729 | do { 730 | int done; 731 | 732 | for (i = 0; i < BF_N + 2; i += 2) { 733 | data.ctx.P[i] ^= data.expanded_key[i]; 734 | data.ctx.P[i + 1] ^= data.expanded_key[i + 1]; 735 | } 736 | 737 | done = 0; 738 | do { 739 | BF_body(); 740 | if (done) 741 | break; 742 | done = 1; 743 | 744 | tmp1 = data.binary.salt[0]; 745 | tmp2 = data.binary.salt[1]; 746 | tmp3 = data.binary.salt[2]; 747 | tmp4 = data.binary.salt[3]; 748 | for (i = 0; i < BF_N; i += 4) { 749 | data.ctx.P[i] ^= tmp1; 750 | data.ctx.P[i + 1] ^= tmp2; 751 | data.ctx.P[i + 2] ^= tmp3; 752 | data.ctx.P[i + 3] ^= tmp4; 753 | } 754 | data.ctx.P[16] ^= tmp1; 755 | data.ctx.P[17] ^= tmp2; 756 | } while (1); 757 | } while (--count); 758 | 759 | for (i = 0; i < 6; i += 2) { 760 | L = BF_magic_w[i]; 761 | R = BF_magic_w[i + 1]; 762 | 763 | count = 64; 764 | do { 765 | BF_ENCRYPT; 766 | } while (--count); 767 | 768 | data.binary.output[i] = L; 769 | data.binary.output[i + 1] = R; 770 | } 771 | 772 | memcpy(output, setting, 7 + 22 - 1); 773 | output[7 + 22 - 1] = BF_itoa64[(int) 774 | BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30]; 775 | 776 | /* This has to be bug-compatible with the original implementation, so 777 | * only encode 23 of the 24 bytes. :-) */ 778 | BF_swap(data.binary.output, 6); 779 | BF_encode(&output[7 + 22], data.binary.output, 23); 780 | output[7 + 22 + 31] = '\0'; 781 | 782 | return output; 783 | } 784 | 785 | int _crypt_output_magic(const char *setting, char *output, int size) 786 | { 787 | if (size < 3) 788 | return -1; 789 | 790 | output[0] = '*'; 791 | output[1] = '0'; 792 | output[2] = '\0'; 793 | 794 | if (setting[0] == '*' && setting[1] == '0') 795 | output[1] = '1'; 796 | 797 | return 0; 798 | } 799 | 800 | /* 801 | * Please preserve the runtime self-test. It serves two purposes at once: 802 | * 803 | * 1. We really can't afford the risk of producing incompatible hashes e.g. 804 | * when there's something like gcc bug 26587 again, whereas an application or 805 | * library integrating this code might not also integrate our external tests or 806 | * it might not run them after every build. Even if it does, the miscompile 807 | * might only occur on the production build, but not on a testing build (such 808 | * as because of different optimization settings). It is painful to recover 809 | * from incorrectly-computed hashes - merely fixing whatever broke is not 810 | * enough. Thus, a proactive measure like this self-test is needed. 811 | * 812 | * 2. We don't want to leave sensitive data from our actual password hash 813 | * computation on the stack or in registers. Previous revisions of the code 814 | * would do explicit cleanups, but simply running the self-test after hash 815 | * computation is more reliable. 816 | * 817 | * The performance cost of this quick self-test is around 0.6% at the "$2a$08" 818 | * setting. 819 | */ 820 | char *_crypt_blowfish_rn(const char *key, const char *setting, 821 | char *output, int size) 822 | { 823 | const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; 824 | const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu"; 825 | static const char * const test_hashes[2] = 826 | {"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */ 827 | "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */ 828 | const char *test_hash = test_hashes[0]; 829 | char *retval; 830 | const char *p; 831 | int save_errno, ok; 832 | struct { 833 | char s[7 + 22 + 1]; 834 | char o[7 + 22 + 31 + 1 + 1 + 1]; 835 | } buf; 836 | 837 | /* Hash the supplied password */ 838 | _crypt_output_magic(setting, output, size); 839 | retval = BF_crypt(key, setting, output, size, 16); 840 | save_errno = errno; 841 | 842 | /* 843 | * Do a quick self-test. It is important that we make both calls to BF_crypt() 844 | * from the same scope such that they likely use the same stack locations, 845 | * which makes the second call overwrite the first call's sensitive data on the 846 | * stack and makes it more likely that any alignment related issues would be 847 | * detected by the self-test. 848 | */ 849 | memcpy(buf.s, test_setting, sizeof(buf.s)); 850 | if (retval) { 851 | unsigned int flags = flags_by_subtype[ 852 | (unsigned int)(unsigned char)setting[2] - 'a']; 853 | test_hash = test_hashes[flags & 1]; 854 | buf.s[2] = setting[2]; 855 | } 856 | memset(buf.o, 0x55, sizeof(buf.o)); 857 | buf.o[sizeof(buf.o) - 1] = 0; 858 | p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1); 859 | 860 | ok = (p == buf.o && 861 | !memcmp(p, buf.s, 7 + 22) && 862 | !memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1)); 863 | 864 | { 865 | const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; 866 | BF_key ae, ai, ye, yi; 867 | BF_set_key(k, ae, ai, 2); /* $2a$ */ 868 | BF_set_key(k, ye, yi, 4); /* $2y$ */ 869 | ai[0] ^= 0x10000; /* undo the safety (for comparison) */ 870 | ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 && 871 | !memcmp(ae, ye, sizeof(ae)) && 872 | !memcmp(ai, yi, sizeof(ai)); 873 | } 874 | 875 | __set_errno(save_errno); 876 | if (ok) 877 | return retval; 878 | 879 | /* Should not happen */ 880 | _crypt_output_magic(setting, output, size); 881 | __set_errno(EINVAL); /* pretend we don't support this hash type */ 882 | return NULL; 883 | } 884 | 885 | char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count, 886 | const char *input, int size, char *output, int output_size) 887 | { 888 | if (size < 16 || output_size < 7 + 22 + 1 || 889 | (count && (count < 4 || count > 31)) || 890 | prefix[0] != '$' || prefix[1] != '2' || 891 | (prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) { 892 | if (output_size > 0) output[0] = '\0'; 893 | __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); 894 | return NULL; 895 | } 896 | 897 | if (!count) count = 5; 898 | 899 | output[0] = '$'; 900 | output[1] = '2'; 901 | output[2] = prefix[2]; 902 | output[3] = '$'; 903 | output[4] = '0' + count / 10; 904 | output[5] = '0' + count % 10; 905 | output[6] = '$'; 906 | 907 | BF_encode(&output[7], (const BF_word *)input, 16); 908 | output[7 + 22] = '\0'; 909 | 910 | return output; 911 | } 912 | -------------------------------------------------------------------------------- /src/crypt_gensalt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2011. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | * 16 | * This file contains salt generation functions for the traditional and 17 | * other common crypt(3) algorithms, except for bcrypt which is defined 18 | * entirely in crypt_blowfish.c. 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | #ifndef __set_errno 25 | #define __set_errno(val) errno = (val) 26 | #endif 27 | 28 | /* Just to make sure the prototypes match the actual definitions */ 29 | #ifdef _WIN32 30 | #include "../include/bcrypt/crypt_gensalt.h" 31 | #else 32 | #include "crypt_gensalt.h" 33 | #endif 34 | 35 | unsigned char _crypt_itoa64[64 + 1] = 36 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 37 | 38 | char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count, 39 | const char *input, int size, char *output, int output_size) 40 | { 41 | (void) prefix; 42 | 43 | if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { 44 | if (output_size > 0) output[0] = '\0'; 45 | __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); 46 | return NULL; 47 | } 48 | 49 | output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f]; 50 | output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f]; 51 | output[2] = '\0'; 52 | 53 | return output; 54 | } 55 | 56 | char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count, 57 | const char *input, int size, char *output, int output_size) 58 | { 59 | unsigned long value; 60 | 61 | (void) prefix; 62 | 63 | /* Even iteration counts make it easier to detect weak DES keys from a look 64 | * at the hash, so they should be avoided */ 65 | if (size < 3 || output_size < 1 + 4 + 4 + 1 || 66 | (count && (count > 0xffffff || !(count & 1)))) { 67 | if (output_size > 0) output[0] = '\0'; 68 | __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); 69 | return NULL; 70 | } 71 | 72 | if (!count) count = 725; 73 | 74 | output[0] = '_'; 75 | output[1] = _crypt_itoa64[count & 0x3f]; 76 | output[2] = _crypt_itoa64[(count >> 6) & 0x3f]; 77 | output[3] = _crypt_itoa64[(count >> 12) & 0x3f]; 78 | output[4] = _crypt_itoa64[(count >> 18) & 0x3f]; 79 | value = (unsigned long)(unsigned char)input[0] | 80 | ((unsigned long)(unsigned char)input[1] << 8) | 81 | ((unsigned long)(unsigned char)input[2] << 16); 82 | output[5] = _crypt_itoa64[value & 0x3f]; 83 | output[6] = _crypt_itoa64[(value >> 6) & 0x3f]; 84 | output[7] = _crypt_itoa64[(value >> 12) & 0x3f]; 85 | output[8] = _crypt_itoa64[(value >> 18) & 0x3f]; 86 | output[9] = '\0'; 87 | 88 | return output; 89 | } 90 | 91 | char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, 92 | const char *input, int size, char *output, int output_size) 93 | { 94 | unsigned long value; 95 | 96 | (void) prefix; 97 | 98 | if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) { 99 | if (output_size > 0) output[0] = '\0'; 100 | __set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL); 101 | return NULL; 102 | } 103 | 104 | output[0] = '$'; 105 | output[1] = '1'; 106 | output[2] = '$'; 107 | value = (unsigned long)(unsigned char)input[0] | 108 | ((unsigned long)(unsigned char)input[1] << 8) | 109 | ((unsigned long)(unsigned char)input[2] << 16); 110 | output[3] = _crypt_itoa64[value & 0x3f]; 111 | output[4] = _crypt_itoa64[(value >> 6) & 0x3f]; 112 | output[5] = _crypt_itoa64[(value >> 12) & 0x3f]; 113 | output[6] = _crypt_itoa64[(value >> 18) & 0x3f]; 114 | output[7] = '\0'; 115 | 116 | if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { 117 | value = (unsigned long)(unsigned char)input[3] | 118 | ((unsigned long)(unsigned char)input[4] << 8) | 119 | ((unsigned long)(unsigned char)input[5] << 16); 120 | output[7] = _crypt_itoa64[value & 0x3f]; 121 | output[8] = _crypt_itoa64[(value >> 6) & 0x3f]; 122 | output[9] = _crypt_itoa64[(value >> 12) & 0x3f]; 123 | output[10] = _crypt_itoa64[(value >> 18) & 0x3f]; 124 | output[11] = '\0'; 125 | } 126 | 127 | return output; 128 | } 129 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "bcrypt/BCrypt.hpp" 2 | #include 3 | 4 | int main(){ 5 | std::string right_password = "right_password"; 6 | std::string wrong_password = "wrong_password"; 7 | 8 | std::cout << "generate hash... " << std::flush; 9 | std::string hash = BCrypt::generateHash(right_password, 12); 10 | std::cout << "done." << std::endl; 11 | 12 | std::cout << "checking right password: " << std::flush 13 | << BCrypt::validatePassword(right_password,hash) << std::endl; 14 | 15 | std::cout << "checking wrong password: " << std::flush 16 | << BCrypt::validatePassword(wrong_password,hash) << std::endl; 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 2000-2014. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 2000-2014 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #ifndef __set_errno 22 | #define __set_errno(val) errno = (val) 23 | #endif 24 | 25 | #ifdef TEST 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #ifdef TEST_THREADS 33 | #include 34 | #endif 35 | #endif 36 | 37 | #define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1) 38 | #define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1) 39 | 40 | #if defined(__GLIBC__) && defined(_LIBC) 41 | #define __SKIP_GNU 42 | #endif 43 | 44 | #if defined(_WIN32) || defined(_WIN64) 45 | #include "../include/bcrypt/ow-crypt.h" 46 | 47 | #include "../include/bcrypt/crypt_blowfish.h" 48 | #include "../include/bcrypt/crypt_gensalt.h" 49 | #else 50 | #include "ow-crypt.h" 51 | 52 | #include "crypt_blowfish.h" 53 | #include "crypt_gensalt.h" 54 | #endif 55 | 56 | #if defined(__GLIBC__) && defined(_LIBC) 57 | /* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */ 58 | #include "crypt.h" 59 | extern char *__md5_crypt_r(const char *key, const char *salt, 60 | char *buffer, int buflen); 61 | /* crypt-entry.c needs to be patched to define __des_crypt_r rather than 62 | * __crypt_r, and not define crypt_r and crypt at all */ 63 | extern char *__des_crypt_r(const char *key, const char *salt, 64 | struct crypt_data *data); 65 | extern struct crypt_data _ufc_foobar; 66 | #endif 67 | 68 | static int _crypt_data_alloc(void **data, int *size, int need) 69 | { 70 | void *updated; 71 | 72 | if (*data && *size >= need) return 0; 73 | 74 | updated = realloc(*data, need); 75 | 76 | if (!updated) { 77 | #ifndef __GLIBC__ 78 | /* realloc(3) on glibc sets errno, so we don't need to bother */ 79 | __set_errno(ENOMEM); 80 | #endif 81 | return -1; 82 | } 83 | 84 | #if defined(__GLIBC__) && defined(_LIBC) 85 | if (need >= sizeof(struct crypt_data)) 86 | ((struct crypt_data *)updated)->initialized = 0; 87 | #endif 88 | 89 | *data = updated; 90 | *size = need; 91 | 92 | return 0; 93 | } 94 | 95 | static char *_crypt_retval_magic(char *retval, const char *setting, 96 | char *output, int size) 97 | { 98 | if (retval) 99 | return retval; 100 | 101 | if (_crypt_output_magic(setting, output, size)) 102 | return NULL; /* shouldn't happen */ 103 | 104 | return output; 105 | } 106 | 107 | #if defined(__GLIBC__) && defined(_LIBC) 108 | /* 109 | * Applications may re-use the same instance of struct crypt_data without 110 | * resetting the initialized field in order to let crypt_r() skip some of 111 | * its initialization code. Thus, it is important that our multiple hashing 112 | * algorithms either don't conflict with each other in their use of the 113 | * data area or reset the initialized field themselves whenever required. 114 | * Currently, the hashing algorithms simply have no conflicts: the first 115 | * field of struct crypt_data is the 128-byte large DES key schedule which 116 | * __des_crypt_r() calculates each time it is called while the two other 117 | * hashing algorithms use less than 128 bytes of the data area. 118 | */ 119 | 120 | char *__crypt_rn(__const char *key, __const char *setting, 121 | void *data, int size) 122 | { 123 | if (setting[0] == '$' && setting[1] == '2') 124 | return _crypt_blowfish_rn(key, setting, (char *)data, size); 125 | if (setting[0] == '$' && setting[1] == '1') 126 | return __md5_crypt_r(key, setting, (char *)data, size); 127 | if (setting[0] == '$' || setting[0] == '_') { 128 | __set_errno(EINVAL); 129 | return NULL; 130 | } 131 | if (size >= sizeof(struct crypt_data)) 132 | return __des_crypt_r(key, setting, (struct crypt_data *)data); 133 | __set_errno(ERANGE); 134 | return NULL; 135 | } 136 | 137 | char *__crypt_ra(__const char *key, __const char *setting, 138 | void **data, int *size) 139 | { 140 | if (setting[0] == '$' && setting[1] == '2') { 141 | if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) 142 | return NULL; 143 | return _crypt_blowfish_rn(key, setting, (char *)*data, *size); 144 | } 145 | if (setting[0] == '$' && setting[1] == '1') { 146 | if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) 147 | return NULL; 148 | return __md5_crypt_r(key, setting, (char *)*data, *size); 149 | } 150 | if (setting[0] == '$' || setting[0] == '_') { 151 | __set_errno(EINVAL); 152 | return NULL; 153 | } 154 | if (_crypt_data_alloc(data, size, sizeof(struct crypt_data))) 155 | return NULL; 156 | return __des_crypt_r(key, setting, (struct crypt_data *)*data); 157 | } 158 | 159 | char *__crypt_r(__const char *key, __const char *setting, 160 | struct crypt_data *data) 161 | { 162 | return _crypt_retval_magic( 163 | __crypt_rn(key, setting, data, sizeof(*data)), 164 | setting, (char *)data, sizeof(*data)); 165 | } 166 | 167 | char *__crypt(__const char *key, __const char *setting) 168 | { 169 | return _crypt_retval_magic( 170 | __crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)), 171 | setting, (char *)&_ufc_foobar, sizeof(_ufc_foobar)); 172 | } 173 | #else 174 | char *crypt_rn(const char *key, const char *setting, void *data, int size) 175 | { 176 | return _crypt_blowfish_rn(key, setting, (char *)data, size); 177 | } 178 | 179 | char *crypt_ra(const char *key, const char *setting, 180 | void **data, int *size) 181 | { 182 | if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) 183 | return NULL; 184 | return _crypt_blowfish_rn(key, setting, (char *)*data, *size); 185 | } 186 | 187 | char *crypt_r(const char *key, const char *setting, void *data) 188 | { 189 | return _crypt_retval_magic( 190 | crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE), 191 | setting, (char *)data, CRYPT_OUTPUT_SIZE); 192 | } 193 | 194 | char *crypt(const char *key, const char *setting) 195 | { 196 | static char output[CRYPT_OUTPUT_SIZE]; 197 | 198 | return _crypt_retval_magic( 199 | crypt_rn(key, setting, output, sizeof(output)), 200 | setting, output, sizeof(output)); 201 | } 202 | 203 | #define __crypt_gensalt_rn crypt_gensalt_rn 204 | #define __crypt_gensalt_ra crypt_gensalt_ra 205 | #define __crypt_gensalt crypt_gensalt 206 | #endif 207 | 208 | char *__crypt_gensalt_rn(const char *prefix, unsigned long count, 209 | const char *input, int size, char *output, int output_size) 210 | { 211 | char *(*use)(const char *_prefix, unsigned long _count, 212 | const char *_input, int _size, 213 | char *_output, int _output_size); 214 | 215 | /* This may be supported on some platforms in the future */ 216 | if (!input) { 217 | __set_errno(EINVAL); 218 | return NULL; 219 | } 220 | 221 | if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2b$", 4) || 222 | !strncmp(prefix, "$2y$", 4)) 223 | use = _crypt_gensalt_blowfish_rn; 224 | else 225 | if (!strncmp(prefix, "$1$", 3)) 226 | use = _crypt_gensalt_md5_rn; 227 | else 228 | if (prefix[0] == '_') 229 | use = _crypt_gensalt_extended_rn; 230 | else 231 | if (!prefix[0] || 232 | (prefix[0] && prefix[1] && 233 | memchr(_crypt_itoa64, prefix[0], 64) && 234 | memchr(_crypt_itoa64, prefix[1], 64))) 235 | use = _crypt_gensalt_traditional_rn; 236 | else { 237 | __set_errno(EINVAL); 238 | return NULL; 239 | } 240 | 241 | return use(prefix, count, input, size, output, output_size); 242 | } 243 | 244 | char *__crypt_gensalt_ra(const char *prefix, unsigned long count, 245 | const char *input, int size) 246 | { 247 | char output[CRYPT_GENSALT_OUTPUT_SIZE]; 248 | char *retval; 249 | 250 | retval = __crypt_gensalt_rn(prefix, count, 251 | input, size, output, sizeof(output)); 252 | 253 | if (retval) { 254 | #if defined(_WIN32) || defined(_WIN64) 255 | retval = _strdup(retval); 256 | #else 257 | retval = strdup(retval); 258 | #endif 259 | #ifndef __GLIBC__ 260 | /* strdup(3) on glibc sets errno, so we don't need to bother */ 261 | if (!retval) 262 | __set_errno(ENOMEM); 263 | #endif 264 | } 265 | 266 | return retval; 267 | } 268 | 269 | char *__crypt_gensalt(const char *prefix, unsigned long count, 270 | const char *input, int size) 271 | { 272 | static char output[CRYPT_GENSALT_OUTPUT_SIZE]; 273 | 274 | return __crypt_gensalt_rn(prefix, count, 275 | input, size, output, sizeof(output)); 276 | } 277 | 278 | #if defined(__GLIBC__) && defined(_LIBC) 279 | weak_alias(__crypt_rn, crypt_rn) 280 | weak_alias(__crypt_ra, crypt_ra) 281 | weak_alias(__crypt_r, crypt_r) 282 | weak_alias(__crypt, crypt) 283 | weak_alias(__crypt_gensalt_rn, crypt_gensalt_rn) 284 | weak_alias(__crypt_gensalt_ra, crypt_gensalt_ra) 285 | weak_alias(__crypt_gensalt, crypt_gensalt) 286 | weak_alias(crypt, fcrypt) 287 | #endif 288 | 289 | #ifdef TEST 290 | static const char *tests[][3] = { 291 | {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", 292 | "U*U"}, 293 | {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", 294 | "U*U*"}, 295 | {"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", 296 | "U*U*U"}, 297 | {"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", 298 | "0123456789abcdefghijklmnopqrstuvwxyz" 299 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 300 | "chars after 72 are ignored"}, 301 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", 302 | "\xa3"}, 303 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", 304 | "\xff\xff\xa3"}, 305 | {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", 306 | "\xff\xff\xa3"}, 307 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.", 308 | "\xff\xff\xa3"}, 309 | {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", 310 | "\xff\xff\xa3"}, 311 | {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", 312 | "\xa3"}, 313 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", 314 | "\xa3"}, 315 | {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", 316 | "\xa3"}, 317 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", 318 | "1\xa3" "345"}, 319 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", 320 | "\xff\xa3" "345"}, 321 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", 322 | "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, 323 | {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", 324 | "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, 325 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.", 326 | "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, 327 | {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", 328 | "\xff\xa3" "345"}, 329 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", 330 | "\xff\xa3" "345"}, 331 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", 332 | "\xa3" "ab"}, 333 | {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", 334 | "\xa3" "ab"}, 335 | {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", 336 | "\xa3" "ab"}, 337 | {"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS", 338 | "\xd1\x91"}, 339 | {"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS", 340 | "\xd0\xc1\xd2\xcf\xcc\xd8"}, 341 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", 342 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 343 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 344 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 345 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 346 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 347 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 348 | "chars after 72 are ignored as usual"}, 349 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy", 350 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" 351 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" 352 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" 353 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" 354 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" 355 | "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"}, 356 | {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe", 357 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" 358 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" 359 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" 360 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" 361 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" 362 | "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"}, 363 | {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", 364 | ""}, 365 | {"*0", "", "$2a$03$CCCCCCCCCCCCCCCCCCCCC."}, 366 | {"*0", "", "$2a$32$CCCCCCCCCCCCCCCCCCCCC."}, 367 | {"*0", "", "$2c$05$CCCCCCCCCCCCCCCCCCCCC."}, 368 | {"*0", "", "$2z$05$CCCCCCCCCCCCCCCCCCCCC."}, 369 | {"*0", "", "$2`$05$CCCCCCCCCCCCCCCCCCCCC."}, 370 | {"*0", "", "$2{$05$CCCCCCCCCCCCCCCCCCCCC."}, 371 | {"*1", "", "*0"}, 372 | {NULL} 373 | }; 374 | 375 | #define which tests[0] 376 | 377 | static volatile sig_atomic_t running; 378 | 379 | static void handle_timer(int signum) 380 | { 381 | (void) signum; 382 | running = 0; 383 | } 384 | 385 | static void *run(void *arg) 386 | { 387 | unsigned long count = 0; 388 | int i = 0; 389 | void *data = NULL; 390 | int size = 0x12345678; 391 | 392 | do { 393 | const char *hash = tests[i][0]; 394 | const char *key = tests[i][1]; 395 | const char *setting = tests[i][2]; 396 | 397 | if (!tests[++i][0]) 398 | i = 0; 399 | 400 | if (setting && strlen(hash) < 30) /* not for benchmark */ 401 | continue; 402 | 403 | if (strcmp(crypt_ra(key, hash, &data, &size), hash)) { 404 | printf("%d: FAILED (crypt_ra/%d/%lu)\n", 405 | (int)((char *)arg - (char *)0), i, count); 406 | free(data); 407 | return NULL; 408 | } 409 | count++; 410 | } while (running); 411 | 412 | free(data); 413 | return count + (char *)0; 414 | } 415 | 416 | int main(void) 417 | { 418 | struct itimerval it; 419 | struct tms buf; 420 | clock_t clk_tck, start_real, start_virtual, end_real, end_virtual; 421 | unsigned long count; 422 | void *data; 423 | int size; 424 | char *setting1, *setting2; 425 | int i; 426 | #ifdef TEST_THREADS 427 | pthread_t t[TEST_THREADS]; 428 | void *t_retval; 429 | #endif 430 | 431 | data = NULL; 432 | size = 0x12345678; 433 | 434 | for (i = 0; tests[i][0]; i++) { 435 | const char *hash = tests[i][0]; 436 | const char *key = tests[i][1]; 437 | const char *setting = tests[i][2]; 438 | const char *p; 439 | int ok = !setting || strlen(hash) >= 30; 440 | int o_size; 441 | char s_buf[30], o_buf[61]; 442 | if (!setting) { 443 | memcpy(s_buf, hash, sizeof(s_buf) - 1); 444 | s_buf[sizeof(s_buf) - 1] = 0; 445 | setting = s_buf; 446 | } 447 | 448 | __set_errno(0); 449 | p = crypt(key, setting); 450 | if ((!ok && !errno) || strcmp(p, hash)) { 451 | printf("FAILED (crypt/%d)\n", i); 452 | return 1; 453 | } 454 | 455 | if (ok && strcmp(crypt(key, hash), hash)) { 456 | printf("FAILED (crypt/%d)\n", i); 457 | return 1; 458 | } 459 | 460 | for (o_size = -1; o_size <= (int)sizeof(o_buf); o_size++) { 461 | int ok_n = ok && o_size == (int)sizeof(o_buf); 462 | const char *x = "abc"; 463 | strcpy(o_buf, x); 464 | if (o_size >= 3) { 465 | x = "*0"; 466 | if (setting[0] == '*' && setting[1] == '0') 467 | x = "*1"; 468 | } 469 | __set_errno(0); 470 | p = crypt_rn(key, setting, o_buf, o_size); 471 | if ((ok_n && (!p || strcmp(p, hash))) || 472 | (!ok_n && (!errno || p || strcmp(o_buf, x)))) { 473 | printf("FAILED (crypt_rn/%d)\n", i); 474 | return 1; 475 | } 476 | } 477 | 478 | __set_errno(0); 479 | p = crypt_ra(key, setting, &data, &size); 480 | if ((ok && (!p || strcmp(p, hash))) || 481 | (!ok && (!errno || p || strcmp((char *)data, hash)))) { 482 | printf("FAILED (crypt_ra/%d)\n", i); 483 | return 1; 484 | } 485 | } 486 | 487 | setting1 = crypt_gensalt(which[0], 12, data, size); 488 | if (!setting1 || strncmp(setting1, "$2a$12$", 7)) { 489 | puts("FAILED (crypt_gensalt)\n"); 490 | return 1; 491 | } 492 | 493 | setting2 = crypt_gensalt_ra(setting1, 12, data, size); 494 | if (strcmp(setting1, setting2)) { 495 | puts("FAILED (crypt_gensalt_ra/1)\n"); 496 | return 1; 497 | } 498 | 499 | (*(char *)data)++; 500 | setting1 = crypt_gensalt_ra(setting2, 12, data, size); 501 | if (!strcmp(setting1, setting2)) { 502 | puts("FAILED (crypt_gensalt_ra/2)\n"); 503 | return 1; 504 | } 505 | 506 | free(setting1); 507 | free(setting2); 508 | free(data); 509 | 510 | #if defined(_SC_CLK_TCK) || !defined(CLK_TCK) 511 | clk_tck = sysconf(_SC_CLK_TCK); 512 | #else 513 | clk_tck = CLK_TCK; 514 | #endif 515 | 516 | running = 1; 517 | signal(SIGALRM, handle_timer); 518 | 519 | memset(&it, 0, sizeof(it)); 520 | it.it_value.tv_sec = 5; 521 | setitimer(ITIMER_REAL, &it, NULL); 522 | 523 | start_real = times(&buf); 524 | start_virtual = buf.tms_utime + buf.tms_stime; 525 | 526 | count = (char *)run((char *)0) - (char *)0; 527 | 528 | end_real = times(&buf); 529 | end_virtual = buf.tms_utime + buf.tms_stime; 530 | if (end_virtual == start_virtual) end_virtual++; 531 | 532 | printf("%.1f c/s real, %.1f c/s virtual\n", 533 | (float)count * clk_tck / (end_real - start_real), 534 | (float)count * clk_tck / (end_virtual - start_virtual)); 535 | 536 | #ifdef TEST_THREADS 537 | running = 1; 538 | it.it_value.tv_sec = 60; 539 | setitimer(ITIMER_REAL, &it, NULL); 540 | start_real = times(&buf); 541 | 542 | for (i = 0; i < TEST_THREADS; i++) 543 | if (pthread_create(&t[i], NULL, run, i + (char *)0)) { 544 | perror("pthread_create"); 545 | return 1; 546 | } 547 | 548 | for (i = 0; i < TEST_THREADS; i++) { 549 | if (pthread_join(t[i], &t_retval)) { 550 | perror("pthread_join"); 551 | continue; 552 | } 553 | if (!t_retval) continue; 554 | count = (char *)t_retval - (char *)0; 555 | end_real = times(&buf); 556 | printf("%d: %.1f c/s real\n", i, 557 | (float)count * clk_tck / (end_real - start_real)); 558 | } 559 | #endif 560 | 561 | return 0; 562 | } 563 | #endif 564 | -------------------------------------------------------------------------------- /src/x86.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Solar Designer in 1998-2010. 3 | * No copyright is claimed, and the software is hereby placed in the public 4 | * domain. In case this attempt to disclaim copyright and place the software 5 | * in the public domain is deemed null and void, then the software is 6 | * Copyright (c) 1998-2010 Solar Designer and it is hereby released to the 7 | * general public under the following terms: 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted. 11 | * 12 | * There's ABSOLUTELY NO WARRANTY, express or implied. 13 | * 14 | * See crypt_blowfish.c for more information. 15 | */ 16 | 17 | #ifdef __i386__ 18 | 19 | #if defined(__OpenBSD__) && !defined(__ELF__) 20 | #define UNDERSCORES 21 | #define ALIGN_LOG 22 | #endif 23 | 24 | #if defined(__CYGWIN32__) || defined(__MINGW32__) 25 | #define UNDERSCORES 26 | #endif 27 | 28 | #ifdef __DJGPP__ 29 | #define UNDERSCORES 30 | #define ALIGN_LOG 31 | #endif 32 | 33 | #ifdef UNDERSCORES 34 | #define _BF_body_r __BF_body_r 35 | #endif 36 | 37 | #ifdef ALIGN_LOG 38 | #define DO_ALIGN(log) .align (log) 39 | #elif defined(DUMBAS) 40 | #define DO_ALIGN(log) .align 1 << log 41 | #else 42 | #define DO_ALIGN(log) .align (1 << (log)) 43 | #endif 44 | 45 | #define BF_FRAME 0x200 46 | #define ctx %esp 47 | 48 | #define BF_ptr (ctx) 49 | 50 | #define S(N, r) N+BF_FRAME(ctx,r,4) 51 | #ifdef DUMBAS 52 | #define P(N) 0x1000+N+N+N+N+BF_FRAME(ctx) 53 | #else 54 | #define P(N) 0x1000+4*N+BF_FRAME(ctx) 55 | #endif 56 | 57 | /* 58 | * This version of the assembly code is optimized primarily for the original 59 | * Intel Pentium but is also careful to avoid partial register stalls on the 60 | * Pentium Pro family of processors (tested up to Pentium III Coppermine). 61 | * 62 | * It is possible to do 15% faster on the Pentium Pro family and probably on 63 | * many non-Intel x86 processors, but, unfortunately, that would make things 64 | * twice slower for the original Pentium. 65 | * 66 | * An additional 2% speedup may be achieved with non-reentrant code. 67 | */ 68 | 69 | #define L %esi 70 | #define R %edi 71 | #define tmp1 %eax 72 | #define tmp1_lo %al 73 | #define tmp2 %ecx 74 | #define tmp2_hi %ch 75 | #define tmp3 %edx 76 | #define tmp3_lo %dl 77 | #define tmp4 %ebx 78 | #define tmp4_hi %bh 79 | #define tmp5 %ebp 80 | 81 | .text 82 | 83 | #define BF_ROUND(L, R, N) \ 84 | xorl L,tmp2; \ 85 | xorl tmp1,tmp1; \ 86 | movl tmp2,L; \ 87 | shrl $16,tmp2; \ 88 | movl L,tmp4; \ 89 | movb tmp2_hi,tmp1_lo; \ 90 | andl $0xFF,tmp2; \ 91 | movb tmp4_hi,tmp3_lo; \ 92 | andl $0xFF,tmp4; \ 93 | movl S(0,tmp1),tmp1; \ 94 | movl S(0x400,tmp2),tmp5; \ 95 | addl tmp5,tmp1; \ 96 | movl S(0x800,tmp3),tmp5; \ 97 | xorl tmp5,tmp1; \ 98 | movl S(0xC00,tmp4),tmp5; \ 99 | addl tmp1,tmp5; \ 100 | movl 4+P(N),tmp2; \ 101 | xorl tmp5,R 102 | 103 | #define BF_ENCRYPT_START \ 104 | BF_ROUND(L, R, 0); \ 105 | BF_ROUND(R, L, 1); \ 106 | BF_ROUND(L, R, 2); \ 107 | BF_ROUND(R, L, 3); \ 108 | BF_ROUND(L, R, 4); \ 109 | BF_ROUND(R, L, 5); \ 110 | BF_ROUND(L, R, 6); \ 111 | BF_ROUND(R, L, 7); \ 112 | BF_ROUND(L, R, 8); \ 113 | BF_ROUND(R, L, 9); \ 114 | BF_ROUND(L, R, 10); \ 115 | BF_ROUND(R, L, 11); \ 116 | BF_ROUND(L, R, 12); \ 117 | BF_ROUND(R, L, 13); \ 118 | BF_ROUND(L, R, 14); \ 119 | BF_ROUND(R, L, 15); \ 120 | movl BF_ptr,tmp5; \ 121 | xorl L,tmp2; \ 122 | movl P(17),L 123 | 124 | #define BF_ENCRYPT_END \ 125 | xorl R,L; \ 126 | movl tmp2,R 127 | 128 | DO_ALIGN(5) 129 | .globl _BF_body_r 130 | _BF_body_r: 131 | movl 4(%esp),%eax 132 | pushl %ebp 133 | pushl %ebx 134 | pushl %esi 135 | pushl %edi 136 | subl $BF_FRAME-8,%eax 137 | xorl L,L 138 | cmpl %esp,%eax 139 | ja BF_die 140 | xchgl %eax,%esp 141 | xorl R,R 142 | pushl %eax 143 | leal 0x1000+BF_FRAME-4(ctx),%eax 144 | movl 0x1000+BF_FRAME-4(ctx),tmp2 145 | pushl %eax 146 | xorl tmp3,tmp3 147 | BF_loop_P: 148 | BF_ENCRYPT_START 149 | addl $8,tmp5 150 | BF_ENCRYPT_END 151 | leal 0x1000+18*4+BF_FRAME(ctx),tmp1 152 | movl tmp5,BF_ptr 153 | cmpl tmp5,tmp1 154 | movl L,-8(tmp5) 155 | movl R,-4(tmp5) 156 | movl P(0),tmp2 157 | ja BF_loop_P 158 | leal BF_FRAME(ctx),tmp5 159 | xorl tmp3,tmp3 160 | movl tmp5,BF_ptr 161 | BF_loop_S: 162 | BF_ENCRYPT_START 163 | BF_ENCRYPT_END 164 | movl P(0),tmp2 165 | movl L,(tmp5) 166 | movl R,4(tmp5) 167 | BF_ENCRYPT_START 168 | BF_ENCRYPT_END 169 | movl P(0),tmp2 170 | movl L,8(tmp5) 171 | movl R,12(tmp5) 172 | BF_ENCRYPT_START 173 | BF_ENCRYPT_END 174 | movl P(0),tmp2 175 | movl L,16(tmp5) 176 | movl R,20(tmp5) 177 | BF_ENCRYPT_START 178 | addl $32,tmp5 179 | BF_ENCRYPT_END 180 | leal 0x1000+BF_FRAME(ctx),tmp1 181 | movl tmp5,BF_ptr 182 | cmpl tmp5,tmp1 183 | movl P(0),tmp2 184 | movl L,-8(tmp5) 185 | movl R,-4(tmp5) 186 | ja BF_loop_S 187 | movl 4(%esp),%esp 188 | popl %edi 189 | popl %esi 190 | popl %ebx 191 | popl %ebp 192 | ret 193 | 194 | BF_die: 195 | /* Oops, need to re-compile with a larger BF_FRAME. */ 196 | hlt 197 | jmp BF_die 198 | 199 | #if defined(__ELF__) && defined(__linux__) 200 | .section .note.GNU-stack,"",@progbits 201 | #endif 202 | #endif 203 | -------------------------------------------------------------------------------- /vs2017/libbcrypt/libbcrypt.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbcrypt", "libbcrypt.vcxproj", "{D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "..\test\test.vcxproj", "{C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x64.ActiveCfg = Debug|x64 19 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x64.Build.0 = Debug|x64 20 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x86.ActiveCfg = Debug|Win32 21 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x86.Build.0 = Debug|Win32 22 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x64.ActiveCfg = Release|x64 23 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x64.Build.0 = Release|x64 24 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x86.ActiveCfg = Release|Win32 25 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x86.Build.0 = Release|Win32 26 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x64.ActiveCfg = Debug|x64 27 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x64.Build.0 = Debug|x64 28 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x86.ActiveCfg = Debug|Win32 29 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x86.Build.0 = Debug|Win32 30 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x64.ActiveCfg = Release|x64 31 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x64.Build.0 = Release|x64 32 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x86.ActiveCfg = Release|Win32 33 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {2DB786F9-9679-4A72-A4A0-2544E42B78CB} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /vs2017/libbcrypt/libbcrypt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4} 24 | libbcrypt 25 | 10.0.17763.0 26 | 27 | 28 | 29 | StaticLibrary 30 | true 31 | v141 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v141 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | Level3 92 | MaxSpeed 93 | true 94 | true 95 | true 96 | true 97 | 98 | 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | MaxSpeed 107 | true 108 | true 109 | true 110 | true 111 | 112 | 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /vs2017/libbcrypt/libbcrypt.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /vs2017/test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/bcrypt/BCrypt.hpp" 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | string right_password = "right_password"; 8 | string wrong_password = "wrong_password"; 9 | 10 | cout << "generate hash... " << flush; 11 | string hash = BCrypt::generateHash(right_password, 12); 12 | cout << "done." << endl; 13 | 14 | cout << "checking right password: " << flush 15 | << BCrypt::validatePassword(right_password, hash) << endl; 16 | 17 | cout << "checking wrong password: " << flush 18 | << BCrypt::validatePassword(wrong_password, hash) << endl; 19 | 20 | system("pause"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /vs2017/test/test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {d6a9a3f3-1312-4494-85b8-7ce7dd4d78f4} 27 | 28 | 29 | 30 | 15.0 31 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68} 32 | test 33 | 10.0.17763.0 34 | 35 | 36 | 37 | Application 38 | true 39 | v141 40 | MultiByte 41 | 42 | 43 | Application 44 | false 45 | v141 46 | true 47 | MultiByte 48 | 49 | 50 | Application 51 | true 52 | v141 53 | MultiByte 54 | 55 | 56 | Application 57 | false 58 | v141 59 | true 60 | MultiByte 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | true 87 | 88 | 89 | ../libbcrypt/Debug/libbcrypt.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | Level3 95 | Disabled 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | Level3 103 | MaxSpeed 104 | true 105 | true 106 | true 107 | true 108 | 109 | 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | true 121 | true 122 | 123 | 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /vs2017/test/test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /vs2019/libbcrypt/libbcrypt.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbcrypt", "libbcrypt.vcxproj", "{D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "..\test\test.vcxproj", "{C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x64.ActiveCfg = Debug|x64 19 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x64.Build.0 = Debug|x64 20 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x86.ActiveCfg = Debug|Win32 21 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Debug|x86.Build.0 = Debug|Win32 22 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x64.ActiveCfg = Release|x64 23 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x64.Build.0 = Release|x64 24 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x86.ActiveCfg = Release|Win32 25 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4}.Release|x86.Build.0 = Release|Win32 26 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x64.ActiveCfg = Debug|x64 27 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x64.Build.0 = Debug|x64 28 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x86.ActiveCfg = Debug|Win32 29 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Debug|x86.Build.0 = Debug|Win32 30 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x64.ActiveCfg = Release|x64 31 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x64.Build.0 = Release|x64 32 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x86.ActiveCfg = Release|Win32 33 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {2DB786F9-9679-4A72-A4A0-2544E42B78CB} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /vs2019/libbcrypt/libbcrypt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {D6A9A3F3-1312-4494-85B8-7CE7DD4D78F4} 24 | libbcrypt 25 | 10.0 26 | 27 | 28 | 29 | StaticLibrary 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | StaticLibrary 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | StaticLibrary 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | Level3 92 | MaxSpeed 93 | true 94 | true 95 | true 96 | true 97 | 98 | 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | MaxSpeed 107 | true 108 | true 109 | true 110 | true 111 | 112 | 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /vs2019/libbcrypt/libbcrypt.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /vs2019/test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/bcrypt/BCrypt.hpp" 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | string right_password = "right_password"; 8 | string wrong_password = "wrong_password"; 9 | 10 | cout << "generate hash... " << flush; 11 | string hash = BCrypt::generateHash(right_password, 12); 12 | cout << "done." << endl; 13 | 14 | cout << "checking right password: " << flush 15 | << BCrypt::validatePassword(right_password, hash) << endl; 16 | 17 | cout << "checking wrong password: " << flush 18 | << BCrypt::validatePassword(wrong_password, hash) << endl; 19 | 20 | system("pause"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /vs2019/test/test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {d6a9a3f3-1312-4494-85b8-7ce7dd4d78f4} 27 | 28 | 29 | 30 | 15.0 31 | {C6B1CF6E-88DF-4109-9EF4-06CBA5BD5B68} 32 | test 33 | 10.0 34 | 35 | 36 | 37 | Application 38 | true 39 | v142 40 | MultiByte 41 | 42 | 43 | Application 44 | false 45 | v142 46 | true 47 | MultiByte 48 | 49 | 50 | Application 51 | true 52 | v142 53 | MultiByte 54 | 55 | 56 | Application 57 | false 58 | v142 59 | true 60 | MultiByte 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | true 87 | 88 | 89 | ../libbcrypt/Debug/libbcrypt.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | Level3 95 | Disabled 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | Level3 103 | MaxSpeed 104 | true 105 | true 106 | true 107 | true 108 | 109 | 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | true 121 | true 122 | 123 | 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /vs2019/test/test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | --------------------------------------------------------------------------------