1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/*
* Copyright (C) 2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
#include "StringUtils.h"
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <openssl/evp.h>
namespace KODI
{
namespace UTILITY
{
/**
* Utility class for calculating message digests/hashes, currently using OpenSSL
*/
class CDigest
{
public:
enum class Type
{
MD5,
SHA1,
SHA256,
SHA512,
INVALID
};
/**
* Convert type enumeration value to lower-case string representation
*/
static std::string TypeToString(Type type);
/**
* Convert digest type string representation to enumeration value
*/
static Type TypeFromString(std::string const& type);
/**
* Create a digest calculation object
*/
CDigest(Type type);
/**
* Update digest with data
*
* Cannot be called after \ref Finalize has been called
*/
void Update(std::string const& data);
/**
* Update digest with data
*
* Cannot be called after \ref Finalize has been called
*/
void Update(void const* data, std::size_t size);
/**
* Finalize and return the digest
*
* The digest object cannot be used any more after this function
* has been called.
*
* \return digest value as string in lower-case hexadecimal notation
*/
std::string Finalize();
/**
* Finalize and return the digest
*
* The digest object cannot be used any more after this
* function has been called.
*
* \return digest value as binary std::string
*/
std::string FinalizeRaw();
/**
* Calculate message digest
*/
static std::string Calculate(Type type, std::string const& data);
/**
* Calculate message digest
*/
static std::string Calculate(Type type, void const* data, std::size_t size);
private:
struct MdCtxDeleter
{
void operator()(EVP_MD_CTX* context);
};
bool m_finalized{false};
std::unique_ptr<EVP_MD_CTX, MdCtxDeleter> m_context;
EVP_MD const* m_md;
};
struct TypedDigest
{
CDigest::Type type{CDigest::Type::INVALID};
std::string value;
TypedDigest() = default;
TypedDigest(CDigest::Type type, std::string const& value)
: type(type), value(value)
{}
bool Empty() const
{
return (type == CDigest::Type::INVALID || value.empty());
}
};
inline bool operator==(TypedDigest const& left, TypedDigest const& right)
{
if (left.type != right.type)
{
throw std::logic_error("Cannot compare digests of different type");
}
return StringUtils::EqualsNoCase(left.value, right.value);
}
inline bool operator!=(TypedDigest const& left, TypedDigest const& right)
{
return !(left == right);
}
std::ostream& operator<<(std::ostream& os, TypedDigest const& digest);
}
}
|