1
2
3
4
5
6 #include <soulng/util/Sha1.hpp>
7 #include <soulng/util/TextUtils.hpp>
8
9 namespace soulng {namespace util {
10
11 inline uint32_t LeftRotate(uint32_t x, uint32_t n)
12 {
13 return (x << n) ^ (x >> (32 - n));
14 }
15
16 Sha1::Sha1()
17 {
18 Reset();
19 }
20
21 void Sha1::Reset()
22 {
23 digest[0] = 0x67452301u;
24 digest[1] = 0xEFCDAB89u;
25 digest[2] = 0x98BADCFEu;
26 digest[3] = 0x10325476u;
27 digest[4] = 0xC3D2E1F0u;
28 byteIndex = 0u;
29 bitCount = 0u;
30 }
31
32 void Sha1::Process(void* begin, void* end)
33 {
34 uint8_t* b = static_cast<uint8_t*>(begin);
35 uint8_t* e = static_cast<uint8_t*>(end);
36 while (b != e)
37 {
38 Process(*b);
39 ++b;
40 }
41 }
42
43 std::string Sha1::GetDigest()
44 {
45 ProcessByte(0x80u);
46 if (byteIndex > 56u)
47 {
48 while (byteIndex != 0u)
49 {
50 ProcessByte(0u);
51 }
52 while (byteIndex < 56u)
53 {
54 ProcessByte(0u);
55 }
56 }
57 else
58 {
59 while (byteIndex < 56u)
60 {
61 ProcessByte(0u);
62 }
63 }
64 ProcessByte(static_cast<uint8_t>((bitCount >> 56u) & 0xFFu));
65 ProcessByte(static_cast<uint8_t>((bitCount >> 48u) & 0xFFu));
66 ProcessByte(static_cast<uint8_t>((bitCount >> 40u) & 0xFFu));
67 ProcessByte(static_cast<uint8_t>((bitCount >> 32u) & 0xFFu));
68 ProcessByte(static_cast<uint8_t>((bitCount >> 24u) & 0xFFu));
69 ProcessByte(static_cast<uint8_t>((bitCount >> 16u) & 0xFFu));
70 ProcessByte(static_cast<uint8_t>((bitCount >> 8u) & 0xFFu));
71 ProcessByte(static_cast<uint8_t>(bitCount & 0xFFu));
72 std::string s = ToHexString(digest[0]);
73 s.append(ToHexString(digest[1]));
74 s.append(ToHexString(digest[2]));
75 s.append(ToHexString(digest[3]));
76 s.append(ToHexString(digest[4]));
77 return s;
78 }
79
80 void Sha1::ProcessBlock()
81 {
82 uint32_t w[80];
83 for (int i = 0; i < 16; ++i)
84 {
85 w[i] = static_cast<uint32_t>(block[4 * i]) << 24u;
86 w[i] = w[i] | static_cast<uint32_t>(block[4 * i + 1]) << 16u;
87 w[i] = w[i] | static_cast<uint32_t>(block[4 * i + 2]) << 8u;
88 w[i] = w[i] | static_cast<uint32_t>(block[4 * i + 3]);
89 }
90 for (int i = 16; i < 80; ++i)
91 {
92 w[i] = LeftRotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1u);
93 }
94 uint32_t a = digest[0];
95 uint32_t b = digest[1];
96 uint32_t c = digest[2];
97 uint32_t d = digest[3];
98 uint32_t e = digest[4];
99 for (int i = 0; i < 80; ++i)
100 {
101 uint32_t f;
102 uint32_t k;
103 if (i < 20)
104 {
105 f = (b & c) | (~b & d);
106 k = 0x5A827999u;
107 }
108 else if (i < 40)
109 {
110 f = b ^ c ^ d;
111 k = 0x6ED9EBA1u;
112 }
113 else if (i < 60)
114 {
115 f = (b & c) | (b & d) | (c & d);
116 k = 0x8F1BBCDCu;
117 }
118 else
119 {
120 f = b ^ c ^ d;
121 k = 0xCA62C1D6u;
122 }
123 uint32_t temp = LeftRotate(a, 5u) + f + e + k + w[i];
124 e = d;
125 d = c;
126 c = LeftRotate(b, 30u);
127 b = a;
128 a = temp;
129 }
130 digest[0] = digest[0] + a;
131 digest[1] = digest[1] + b;
132 digest[2] = digest[2] + c;
133 digest[3] = digest[3] + d;
134 digest[4] = digest[4] + e;
135 }
136
137 std::string GetSha1MessageDigest(const std::string& message)
138 {
139 Sha1 sha1;
140 sha1.Process((void*)message.c_str(), int(message.length()));
141 return sha1.GetDigest();
142 }
143
144 } }