diff options
Diffstat (limited to 'src/sha1.cc')
-rw-r--r-- | src/sha1.cc | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/sha1.cc b/src/sha1.cc new file mode 100644 index 0000000..3f5dbd9 --- /dev/null +++ b/src/sha1.cc @@ -0,0 +1,433 @@ +/* This file is part of the KDE project + Copyright (C) 2001 George Staikos <[email protected]> + Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <config.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_STDINT_H +#include <stdint.h> /* For uintXX_t on OSX */ +#endif +#ifdef HAVE_SYS_BITYPES_H +#include <sys/bitypes.h> /* For uintXX_t on Tru64 */ +#endif +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#include "sha1.h" +#include <string.h> + +// FIXME: this can be optimized to one instruction on most cpus. +#define rol(x,y) ((x << y) | (x >> (32-y))) + + +#define K1 0x5a827999L +#define K2 0x6ed9eba1L +#define K3 0x8f1bbcdcL +#define K4 0xca62c1d6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) + +#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ + ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ + , (x[i&0x0f] = (tm << 1) | (tm >> 31))) + +#define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \ + + f(b, c, d) \ + + k \ + + m; \ + b = rol(b, 30); \ + } while(0) + +const char Base64EncMap[64] = +{ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, + 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F +}; + +void base64Encode( const TQByteArray& in, TQByteArray& out, bool insertLFs ) +{ + // clear out the output buffer + out.resize (0); + if ( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + const char* data = in.data(); + const unsigned int len = in.size(); + + unsigned int out_len = ((len+2)/3)*4; + + // Deal with the 76 characters or less per + // line limit specified in RFC 2045 on a + // pre request basis. + insertLFs = (insertLFs && out_len > 76); + if ( insertLFs ) + out_len += ((out_len-1)/76); + + int count = 0; + out.resize( out_len ); + + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + if ( len > 1 ) + { + while (sidx < len-2) + { + if ( insertLFs ) + { + if ( count && (count%76) == 0 ) + out[didx++] = '\n'; + count += 4; + } + out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; + out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out[didx++] = Base64EncMap[data[sidx+2] & 077]; + sidx += 3; + } + } + + if (sidx < len) + { + if ( insertLFs && (count > 0) && (count%76) == 0 ) + out[didx++] = '\n'; + + out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; + if (sidx < len-1) + { + out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077]; + } + else + { + out[didx++] = Base64EncMap[(data[sidx] << 4) & 077]; + } + } + + // Add padding + while (didx < out.size()) + { + out[didx] = '='; + didx++; + } +} + +SHA1::SHA1() { + _hashlen = 160; + _init = false; + reset(); +} + + +int SHA1::reset() { + _h0 = 0x67452301; + _h1 = 0xefcdab89; + _h2 = 0x98badcfe; + _h3 = 0x10325476; + _h4 = 0xc3d2e1f0; + _nblocks = 0; + _count = 0; + memset(_buf, 0, 56); // clear the buffer + + _init = true; + return 0; +} + + +int SHA1::size() const { + return _hashlen; +} + + +SHA1::~SHA1() { + +} + + +void SHA1::transform(void *data) { + unsigned int a, b, c, d, e, tm; + unsigned int x[16]; + unsigned char *_data = (unsigned char *)data; + + a = _h0; + b = _h1; + c = _h2; + d = _h3; + e = _h4; + +#ifdef WORDS_BIGENDIAN + memcpy(x, _data, 64); +#else + int i; + unsigned char *p2; + for (i = 0, p2 = (unsigned char *)x; + i < 16; i++, p2 += 4) { + p2[3] = *_data++; + p2[2] = *_data++; + p2[1] = *_data++; + p2[0] = *_data++; + } +#endif + + R(a, b, c, d, e, F1, K1, x[ 0]); + R(e, a, b, c, d, F1, K1, x[ 1]); + R(d, e, a, b, c, F1, K1, x[ 2]); + R(c, d, e, a, b, F1, K1, x[ 3]); + R(b, c, d, e, a, F1, K1, x[ 4]); + R(a, b, c, d, e, F1, K1, x[ 5]); + R(e, a, b, c, d, F1, K1, x[ 6]); + R(d, e, a, b, c, F1, K1, x[ 7]); + R(c, d, e, a, b, F1, K1, x[ 8]); + R(b, c, d, e, a, F1, K1, x[ 9]); + R(a, b, c, d, e, F1, K1, x[10]); + R(e, a, b, c, d, F1, K1, x[11]); + R(d, e, a, b, c, F1, K1, x[12]); + R(c, d, e, a, b, F1, K1, x[13]); + R(b, c, d, e, a, F1, K1, x[14]); + R(a, b, c, d, e, F1, K1, x[15]); + R(e, a, b, c, d, F1, K1, M(16)); + R(d, e, a, b, c, F1, K1, M(17)); + R(c, d, e, a, b, F1, K1, M(18)); + R(b, c, d, e, a, F1, K1, M(19)); + R(a, b, c, d, e, F2, K2, M(20)); + R(e, a, b, c, d, F2, K2, M(21)); + R(d, e, a, b, c, F2, K2, M(22)); + R(c, d, e, a, b, F2, K2, M(23)); + R(b, c, d, e, a, F2, K2, M(24)); + R(a, b, c, d, e, F2, K2, M(25)); + R(e, a, b, c, d, F2, K2, M(26)); + R(d, e, a, b, c, F2, K2, M(27)); + R(c, d, e, a, b, F2, K2, M(28)); + R(b, c, d, e, a, F2, K2, M(29)); + R(a, b, c, d, e, F2, K2, M(30)); + R(e, a, b, c, d, F2, K2, M(31)); + R(d, e, a, b, c, F2, K2, M(32)); + R(c, d, e, a, b, F2, K2, M(33)); + R(b, c, d, e, a, F2, K2, M(34)); + R(a, b, c, d, e, F2, K2, M(35)); + R(e, a, b, c, d, F2, K2, M(36)); + R(d, e, a, b, c, F2, K2, M(37)); + R(c, d, e, a, b, F2, K2, M(38)); + R(b, c, d, e, a, F2, K2, M(39)); + R(a, b, c, d, e, F3, K3, M(40)); + R(e, a, b, c, d, F3, K3, M(41)); + R(d, e, a, b, c, F3, K3, M(42)); + R(c, d, e, a, b, F3, K3, M(43)); + R(b, c, d, e, a, F3, K3, M(44)); + R(a, b, c, d, e, F3, K3, M(45)); + R(e, a, b, c, d, F3, K3, M(46)); + R(d, e, a, b, c, F3, K3, M(47)); + R(c, d, e, a, b, F3, K3, M(48)); + R(b, c, d, e, a, F3, K3, M(49)); + R(a, b, c, d, e, F3, K3, M(50)); + R(e, a, b, c, d, F3, K3, M(51)); + R(d, e, a, b, c, F3, K3, M(52)); + R(c, d, e, a, b, F3, K3, M(53)); + R(b, c, d, e, a, F3, K3, M(54)); + R(a, b, c, d, e, F3, K3, M(55)); + R(e, a, b, c, d, F3, K3, M(56)); + R(d, e, a, b, c, F3, K3, M(57)); + R(c, d, e, a, b, F3, K3, M(58)); + R(b, c, d, e, a, F3, K3, M(59)); + R(a, b, c, d, e, F4, K4, M(60)); + R(e, a, b, c, d, F4, K4, M(61)); + R(d, e, a, b, c, F4, K4, M(62)); + R(c, d, e, a, b, F4, K4, M(63)); + R(b, c, d, e, a, F4, K4, M(64)); + R(a, b, c, d, e, F4, K4, M(65)); + R(e, a, b, c, d, F4, K4, M(66)); + R(d, e, a, b, c, F4, K4, M(67)); + R(c, d, e, a, b, F4, K4, M(68)); + R(b, c, d, e, a, F4, K4, M(69)); + R(a, b, c, d, e, F4, K4, M(70)); + R(e, a, b, c, d, F4, K4, M(71)); + R(d, e, a, b, c, F4, K4, M(72)); + R(c, d, e, a, b, F4, K4, M(73)); + R(b, c, d, e, a, F4, K4, M(74)); + R(a, b, c, d, e, F4, K4, M(75)); + R(e, a, b, c, d, F4, K4, M(76)); + R(d, e, a, b, c, F4, K4, M(77)); + R(c, d, e, a, b, F4, K4, M(78)); + R(b, c, d, e, a, F4, K4, M(79)); + + _h0 += a; + _h1 += b; + _h2 += c; + _h3 += d; + _h4 += e; + +} + + +bool SHA1::readyToGo() const { + return _init; +} + + +int SHA1::process(const void *block, int len) { + if (!_init) { + return -1; + } + + unsigned char *_block = (unsigned char *)block; + + int cnt = 0; + // Flush the buffer before proceeding + if (_count == 64) { + transform(_buf); + _count = 0; + _nblocks++; + } + + if (!_block) { + return 0; + } + + if (_count) { + for (; len && _count < 64; len--, cnt++) { + _buf[_count++] = *_block++; + } + process(0, 0); // flush the buffer if necessary + if (!len) { + return cnt; + } + } + + while (len >= 64) { + transform(_block); + _count = 0; + _nblocks++; + len -= 64; + cnt += 64; + _block += 64; + } + + for (; len && _count < 64; len--, cnt++) { + _buf[_count++] = *_block++; + } + + return cnt; +} + + +const unsigned char *SHA1::hash() { + unsigned int t, msb, lsb; + unsigned char *p; + + + if (!_init) { + return (unsigned char *)_buf; + } + + process(0, 0); + + msb = 0; + t = _nblocks; + + if ((lsb = t << 6) < t) { + msb++; + } + + msb += t >> 26; + t = lsb; + + if ((lsb = t + _count) < t) { + msb++; + } + + t = lsb; + + if ((lsb = t << 3) < t) { + msb++; + } + + msb += t >> 29; + + _buf[_count++] = 0x80; + + if (_count < 56) { + while (_count < 56) { + _buf[_count++] = 0; + } + } else { + while (_count < 64) { + _buf[_count++] = 0; + } + process(0, 0); + memset(_buf, 0, 56); + } + + _buf[56] = msb >> 24; + _buf[57] = msb >> 16; + _buf[58] = msb >> 8; + _buf[59] = msb; + _buf[60] = lsb >> 24; + _buf[61] = lsb >> 16; + _buf[62] = lsb >> 8; + _buf[63] = lsb; + + transform(_buf); + + p = _buf; + +#ifdef WORDS_BIGENDIAN +#define X( a ) do { *( uint32_t * )p = _h##a; p += 4; } while ( 0 ) +#else +#define X(a) do { *p++ = _h##a >> 24; *p++ = _h##a >> 16; \ + *p++ = _h##a >> 8; *p++ = _h##a; } while (0) +#endif + + X(0); + X(1); + X(2); + X(3); + X(4); + +#undef X + + _init = false; + + return (unsigned char *)_buf; +} + +TQString SHA1::base64Hash() +{ + const char * output = (const char *)hash(); + TQByteArray binhash(20); + TQByteArray enchash(28); + memcpy(binhash.data(), output, 20); + base64Encode(binhash, enchash, false); + return TQString(enchash); +} + |