2 * Copyright (C) 2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 #include "StringUtils.h"
16 #include <openssl/evp.h>
26 EVP_MD
const * TypeToEVPMD(CDigest::Type type
)
30 case CDigest::Type::MD5
:
32 case CDigest::Type::SHA1
:
34 case CDigest::Type::SHA256
:
36 case CDigest::Type::SHA512
:
39 throw std::invalid_argument("Unknown digest type");
45 std::ostream
& operator<<(std::ostream
& os
, TypedDigest
const& digest
)
47 return os
<< "{" << CDigest::TypeToString(digest
.type
) << "}" << digest
.value
;
50 std::string
CDigest::TypeToString(Type type
)
65 throw std::invalid_argument("Unknown digest type");
69 CDigest::Type
CDigest::TypeFromString(std::string
const& type
)
71 std::string typeLower
{type
};
72 StringUtils::ToLower(typeLower
);
77 else if (type
== "sha1")
81 else if (type
== "sha256")
85 else if (type
== "sha512")
91 throw std::invalid_argument(std::string("Unknown digest type \"") + type
+ "\"");
95 void CDigest::MdCtxDeleter::operator()(EVP_MD_CTX
* context
)
97 EVP_MD_CTX_destroy(context
);
100 CDigest::CDigest(Type type
)
101 : m_context
{EVP_MD_CTX_create()}, m_md(TypeToEVPMD(type
))
103 if (1 != EVP_DigestInit_ex(m_context
.get(), m_md
, nullptr))
105 throw std::runtime_error("EVP_DigestInit_ex failed");
109 void CDigest::Update(std::string
const& data
)
111 Update(data
.c_str(), data
.size());
114 void CDigest::Update(void const* data
, std::size_t size
)
118 throw std::logic_error("Finalized digest cannot be updated any more");
121 if (1 != EVP_DigestUpdate(m_context
.get(), data
, size
))
123 throw std::runtime_error("EVP_DigestUpdate failed");
127 std::string
CDigest::FinalizeRaw()
131 throw std::logic_error("Digest can only be finalized once");
136 std::array
<unsigned char, 64> digest
;
137 std::size_t size
= EVP_MD_size(m_md
);
138 if (size
> digest
.size())
140 throw std::runtime_error("Digest unexpectedly long");
142 if (1 != EVP_DigestFinal_ex(m_context
.get(), digest
.data(), nullptr))
144 throw std::runtime_error("EVP_DigestFinal_ex failed");
146 return {reinterpret_cast<char*> (digest
.data()), size
};
149 std::string
CDigest::Finalize()
151 return StringUtils::ToHexadecimal(FinalizeRaw());
154 std::string
CDigest::Calculate(Type type
, std::string
const& data
)
156 CDigest digest
{type
};
158 return digest
.Finalize();
161 std::string
CDigest::Calculate(Type type
, void const* data
, std::size_t size
)
163 CDigest digest
{type
};
164 digest
.Update(data
, size
);
165 return digest
.Finalize();