/* This file is part of the KDE project Copyright (C) 2001 George Staikos 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 #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_STDINT_H #include /* For uintXX_t on OSX */ #endif #ifdef HAVE_SYS_BITYPES_H #include /* For uintXX_t on Tru64 */ #endif #ifdef HAVE_STDINT_H #include #endif #include "sha1.h" #include // 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); }