Credit Andrew - updating patches for FFmpeg 7.0 as needed since 6.1, now at 7.0,...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / sha1.C
1 /*
2 *Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4 *Redistribution and use in source and binary forms, with or without
5 *modification, are permitted provided that the following conditions are
6 *met:
7  *
8 ** Redistributions of source code must retain the above copyright
9 *notice, this list of conditions and the following disclaimer.
10 ** Redistributions in binary form must reproduce the above
11 *copyright notice, this list of conditions and the following disclaimer
12 *in the documentation and/or other materials provided with the
13 *distribution.
14 ** Neither the name of Google Inc. nor the names of its
15 *contributors may be used to endorse or promote products derived from
16 *this software without specific prior written permission.
17  *
18 *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 *"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 *LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 *A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 *OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 *SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 *LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 // A straightforward SHA-1 implementation based on RFC 3174.
32 // http://www.ietf.org/rfc/rfc3174.txt
33 // The names of functions and variables (such as "a", "b", and "f")
34 // follow notations in RFC 3174.
35
36 #include "sha1.h"
37
38 void SHA1::addBytes(const uint8_t* input, size_t length)
39 {
40         m_totalBytes += length;
41         while (length > 0) {
42 #if 1
43 // allow unaliged access
44                 uint64_t *buf = (uint64_t*)&m_buffer[m_cursor];
45                 const uint64_t *inp = (const uint64_t*)input;
46                 while (length >= sizeof(uint64_t) && m_cursor < 64) {
47                         *buf++ = *inp++;
48                         m_cursor += sizeof(uint64_t);
49                         length -= sizeof(uint64_t);
50                 }
51                 input = (const uint8_t *)inp;
52 #endif
53                 while (length > 0 && m_cursor < 64) {
54                         m_buffer[m_cursor++] = *input++;
55                         --length;
56                 }
57                 if( m_cursor >= 64 ) processBlock();
58         }
59 }
60
61 void SHA1::computeHash(uint8_t *digest)
62 {
63         finalize();
64         memset(digest, 0, 20);
65         for (size_t i = 0; i < 5; ++i) {
66                 // Treat hashValue as a big-endian value.
67                 uint32_t hashValue = m_hash[i];
68                 for (int j = 0; j < 4; ++j) {
69                         digest[4*i + (3-j)] = hashValue & 0xFF;
70                         hashValue >>= 8;
71                 }
72         }
73
74         reset();
75 }
76
77 void SHA1::finalize()
78 {
79         m_buffer[m_cursor++] = 0x80;
80         if (m_cursor > 56) {
81                 while (m_cursor < 64) m_buffer[m_cursor++] = 0x00;
82                 processBlock();
83         }
84
85         for (size_t i = m_cursor; i < 56; ++i)
86                 m_buffer[i] = 0x00;
87
88         uint64_t bits = m_totalBytes*8;
89         for (int i = 0; i < 8; ++i) {
90                 m_buffer[56 + (7-i)] = bits & 0xFF;
91                 bits >>= 8;
92         }
93         m_cursor = 64;
94         processBlock();
95 }
96
97 void SHA1::processBlock()
98 {
99         uint32_t w[80] = { 0 };
100         for (int t = 0; t < 16; ++t)
101                 w[t] =  (m_buffer[t*4] << 24) |
102                 (m_buffer[t*4 + 1] << 16) |
103                 (m_buffer[t*4 + 2] << 8) |
104                 (m_buffer[t*4 + 3]);
105         for (int t = 16; t < 80; ++t)
106                 w[t] = rotateLeft(1, w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]);
107
108         uint32_t a = m_hash[0], b = m_hash[1];
109         uint32_t c = m_hash[2], d = m_hash[3];
110         uint32_t e = m_hash[4];
111
112         for (int t = 0; t < 80; ++t) {
113                 uint32_t temp = rotateLeft(5, a) + f(t, b, c, d) + e + w[t] + k(t);
114                 e = d;  d = c;
115                 c = rotateLeft(30, b);
116                 b = a;  a = temp;
117         }
118
119         m_hash[0] += a;  m_hash[1] += b;
120         m_hash[2] += c;  m_hash[3] += d;
121         m_hash[4] += e;
122
123         m_cursor = 0;
124 }
125
126 void SHA1::reset()
127 {
128         m_cursor = 0;
129         m_totalBytes = 0;
130         m_hash[0] = 0x67452301;  m_hash[1] = 0xefcdab89;
131         m_hash[2] = 0x98badcfe;  m_hash[3] = 0x10325476;
132         m_hash[4] = 0xc3d2e1f0;
133         memset(m_buffer, 0, sizeof(m_buffer));
134 }
135
136 #ifdef TEST
137 static void expectSHA1(const char *input, int repeat, const char *expected)
138 {
139         SHA1 sha1;
140         const uint8_t *inp = (const uint8_t *)input;
141         int len = strlen(input);
142         for (int i = 0; i < repeat; ++i) sha1.addBytes(inp, len);
143         uint8_t digest[20];  sha1.computeHash(digest);
144         char actual[64], *buffer = actual;
145         for (size_t i = 0; i < 20; ++i) {
146                 snprintf(buffer, 3, "%02X", digest[i]);
147                 buffer += 2;
148         }
149         if( !strcmp(actual, expected) ) return;
150         printf("input: %s, repeat: %d, actual: %s, expected: %s\n",
151                 input, repeat, actual, expected);
152 }
153
154 int main(int ac, char **av)
155 {
156         // Examples taken from sample code in RFC 3174.
157         expectSHA1("abc", 1, "A9993E364706816ABA3E25717850C26C9CD0D89D");
158         expectSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
159                 1, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
160         expectSHA1("a",
161                 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F");
162         expectSHA1("0123456701234567012345670123456701234567012345670123456701234567",
163                 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452");
164         return 0;
165 }
166 #endif
167