File: sha.hh

package info (click to toggle)
pdns-recursor 4.8.8-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,620 kB
  • sloc: cpp: 95,714; javascript: 20,651; sh: 4,679; makefile: 652; xml: 37
file content (125 lines) | stat: -rw-r--r-- 3,841 bytes parent folder | download | duplicates (2)
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
/*
 * This file is part of PowerDNS or dnsdist.
 * Copyright -- PowerDNS.COM B.V. and its contributors
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * In addition, for the avoidance of any doubt, permission is granted to
 * link this program with OpenSSL and to (re)distribute the binaries
 * produced as the result of such linking.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#pragma once

#include <string>
#include <openssl/sha.h>
#include <openssl/evp.h>

inline std::string pdns_sha1sum(const std::string& input)
{
  unsigned char result[20] = {0};
  SHA1(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result);
  return std::string(result, result + sizeof result);
}

inline std::string pdns_sha256sum(const std::string& input)
{
  unsigned char result[32] = {0};
  SHA256(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result);
  return std::string(result, result + sizeof result);
}

inline std::string pdns_sha384sum(const std::string& input)
{
  unsigned char result[48] = {0};
  SHA384(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result);
  return std::string(result, result + sizeof result);
}

inline std::string pdns_sha512sum(const std::string& input)
{
  unsigned char result[64] = {0};
  SHA512(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result);
  return std::string(result, result + sizeof result);
}

namespace pdns
{
class SHADigest
{
public:
  SHADigest() :
    SHADigest(256) {}
  SHADigest(unsigned int bits) :
#if defined(HAVE_EVP_MD_CTX_NEW) && defined(HAVE_EVP_MD_CTX_FREE)
    mdctx(std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), EVP_MD_CTX_free))
#else
    mdctx(std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), EVP_MD_CTX_destroy))
#endif
  {
    if (mdctx == nullptr) {
      throw std::runtime_error("SHADigest: EVP_MD_CTX_new failed");
    }
    switch (bits) {
    case 256:
      md = EVP_sha256();
      break;
    case 384:
      md = EVP_sha384();
      break;
    case 512:
      md = EVP_sha512();
      break;
    default:
      throw std::invalid_argument("SHADigest: unsupported size");
    }
    if (EVP_DigestInit_ex(mdctx.get(), md, NULL) == 0) {
      throw std::runtime_error("SHADigest: init error");
    }
  }

  ~SHADigest()
  {
    // No free of md needed and mdctx is cleaned up by unique_ptr
  }

  void process(const std::string& msg)
  {
    if (EVP_DigestUpdate(mdctx.get(), msg.data(), msg.size()) == 0) {
      throw std::runtime_error("SHADigest: update error");
    }
  }

  std::string digest()
  {
    std::string md_value;
    md_value.resize(EVP_MD_size(md));
    unsigned int md_len;
    if (EVP_DigestFinal_ex(mdctx.get(), reinterpret_cast<unsigned char*>(md_value.data()), &md_len) == 0) {
      throw std::runtime_error("SHADigest: finalize error");
    }
    if (md_len != md_value.size()) {
      throw std::runtime_error("SHADigest: inconsistent size");
    }
    return md_value;
  }

private:
#if defined(HAVE_EVP_MD_CTX_NEW) && defined(HAVE_EVP_MD_CTX_FREE)
  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> mdctx;
#else
  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> mdctx;
#endif
  const EVP_MD* md;
};
}