Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <iostream>
00017 #include <string>
00018
00019 #include "md5.hpp"
00020 #include "hash.hpp"
00021
00022 namespace util {
00023
00024 const std::string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
00025 const std::string hash_prefix = "$H$";
00026
00027 unsigned char* md5(const std::string& input) {
00028 MD5 md5_worker;
00029 md5_worker.update(const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(input.c_str())), input.size());
00030 md5_worker.finalize();
00031 return md5_worker.raw_digest();
00032 }
00033
00034 int get_iteration_count(const std::string& hash) {
00035 return itoa64.find_first_of(hash[3]);
00036 }
00037
00038 std::string get_salt(const std::string& hash) {
00039 return hash.substr(4,8);
00040 }
00041
00042 bool is_valid_hash(const std::string& hash) {
00043 if(hash.size() != 34) return false;
00044 if(hash.substr(0,3) != hash_prefix) return false;
00045
00046 const int iteration_count = get_iteration_count(hash);
00047 if(iteration_count < 7 || iteration_count > 30) return false;
00048
00049 return true;
00050 }
00051
00052 std::string encode_hash(unsigned char* input) {
00053 std::string encoded_hash;
00054
00055 unsigned int i = 0;
00056 do {
00057 unsigned value = input[i++];
00058 encoded_hash.append(itoa64.substr(value & 0x3f,1));
00059 if(i < 16)
00060 value |= static_cast<int>(input[i]) << 8;
00061 encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
00062 if(i++ >= 16)
00063 break;
00064 if(i < 16)
00065 value |= static_cast<int>(input[i]) << 16;
00066 encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
00067 if(i++ >= 16)
00068 break;
00069 encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
00070 } while (i < 16);
00071
00072 return encoded_hash;
00073 }
00074
00075 std::string create_hash(const std::string& password, const std::string& salt, int iteration_count) {
00076 iteration_count = 1 << iteration_count;
00077
00078 unsigned char* output = md5(salt + password);
00079 do {
00080 output = md5(std::string(reinterpret_cast<char*>(output), reinterpret_cast<char*>(output) + 16).append(password));
00081 } while(--iteration_count);
00082
00083 return encode_hash(output);
00084 }
00085
00086 }