1 /*
2    Copyright (C) 2008 - 2018 by Thomas Baumhauer <thomas.baumhauer@NOSPAMgmail.com>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include <array>
18 #include <cstdint>
19 #include <string>
20 
21 #include "global.hpp"
22 #include "exceptions.hpp"
23 
24 // Not configurable. The size (64) is both hard-, and implicitly-coded in crypt_blowfish
25 static const int BCRYPT_HASHSIZE = 64;
26 
27 namespace utils {
28 
29 struct hash_error : public game::error
30 {
hash_errorutils::hash_error31 	hash_error(const std::string& message) : game::error(message) {}
32 };
33 
34 class hash_base
35 {
36 public:
37 	virtual std::string base64_digest() const = 0;
38 	virtual std::string hex_digest() const = 0;
~hash_base()39 	virtual ~hash_base() {}
40 };
41 
42 template<size_t sz, typename T = uint8_t>
43 class hash_digest : public hash_base
44 {
45 protected:
46 	std::array<T, sz> hash;
47 public:
48 	static const int DIGEST_SIZE = sz;
raw_digest() const49 	std::array<T, sz> raw_digest() const {return hash;}
50 };
51 
52 class md5 : public hash_digest<16>
53 {
54 public:
55 	static int get_iteration_count(const std::string& hash);
56 	static std::string get_salt(const std::string& hash);
57 	static bool is_valid_prefix(const std::string& hash);
58 	static bool is_valid_hash(const std::string& hash);
59 	explicit md5(const std::string& input);
60 	md5(const std::string& input, const std::string& salt, int iteration_count = 10);
61 	virtual std::string base64_digest() const override;
62 	virtual std::string hex_digest() const override;
63 };
64 
65 class sha1 : public hash_digest<20>
66 {
67 public:
68 	explicit sha1(const std::string& input);
69 	virtual std::string base64_digest() const override;
70 	virtual std::string hex_digest() const override;
71 };
72 
73 class bcrypt : public hash_digest<BCRYPT_HASHSIZE, char>
74 {
bcrypt()75 	bcrypt() {}
76 	bcrypt(const std::string& input);
77 
78 public:
79 	static bcrypt from_salted_salt(const std::string& input);
80 	static bcrypt from_hash_string(const std::string& input);
81 	static bcrypt hash_pw(const std::string& password, bcrypt& salt);
82 
83 	std::size_t iteration_count_delim_pos;
84 
85 	static bool is_valid_prefix(const std::string& hash);
86 	std::string get_salt() const;
87 	virtual std::string hex_digest() const override;
88 	virtual std::string base64_digest() const override;
89 };
90 
91 } // namespace utils
92