Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -424,10 +424,13 @@ 4BE52D2117B990B4005958D1 /* OFZIPArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE52D1F17B990B4005958D1 /* OFZIPArchive.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BE52D2217B990B4005958D1 /* OFZIPArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2017B990B4005958D1 /* OFZIPArchive.m */; }; 4BE52D2517B990DA005958D1 /* OFChecksumFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE52D2317B990DA005958D1 /* OFChecksumFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BE52D2617B990DA005958D1 /* OFChecksumFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */; }; 4BEAF52D19A811DA00B61868 /* module.map in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BEAF52519A8107500B61868 /* module.map */; }; + 4BEC83B919B7CB7100E4BB08 /* OFRIPEMD160Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BEC83BA19B7CB7100E4BB08 /* OFRIPEMD160Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */; }; + 4BEC83BC19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */; }; 4BF33AFB133807590059CEF7 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; }; 4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66E1235358D0076B512 /* OFArrayTests.m */; }; 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */; }; 4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66F1235358D0076B512 /* OFDataArrayTests.m */; }; 4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */; }; @@ -939,10 +942,13 @@ 4BE5F0D912DF4225005C7A0C /* OFDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFDate.h; path = src/OFDate.h; sourceTree = SOURCE_ROOT; }; 4BE5F0DA12DF4225005C7A0C /* OFDate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFDate.m; path = src/OFDate.m; sourceTree = SOURCE_ROOT; }; 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFBlockTests.m; path = tests/OFBlockTests.m; sourceTree = SOURCE_ROOT; }; 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFDateTests.m; path = tests/OFDateTests.m; sourceTree = SOURCE_ROOT; }; 4BEAF52519A8107500B61868 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.map; path = support/module.map; sourceTree = SOURCE_ROOT; }; + 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRIPEMD160Hash.h; path = src/OFRIPEMD160Hash.h; sourceTree = ""; }; + 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160Hash.m; path = src/OFRIPEMD160Hash.m; sourceTree = ""; }; + 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160HashTests.m; path = tests/OFRIPEMD160HashTests.m; sourceTree = ""; }; 4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURLTests.m; path = tests/OFURLTests.m; sourceTree = SOURCE_ROOT; }; 4BF1BCBF11C9663F0025511F /* objfw-defs.h.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "objfw-defs.h.in"; path = "src/objfw-defs.h.in"; sourceTree = ""; }; 4BF1BCC011C9663F0025511F /* OFHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHash.h; path = src/OFHash.h; sourceTree = ""; }; 4BF1BCC211C9663F0025511F /* OFMD5Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMD5Hash.h; path = src/OFMD5Hash.h; sourceTree = ""; }; 4BF1BCC311C9663F0025511F /* OFMD5Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMD5Hash.m; path = src/OFMD5Hash.m; sourceTree = ""; }; @@ -1349,10 +1355,12 @@ 4B67997A1099E7C50041064A /* OFPlugin.m */, 4BB524BF143D1E4E0085FBCC /* OFProcess.h */, 4BB524C0143D1E4E0085FBCC /* OFProcess.m */, 4B6743FC163C395900EB1E59 /* OFRecursiveMutex.h */, 4B6743FD163C395900EB1E59 /* OFRecursiveMutex.m */, + 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */, + 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */, 4B325ED91605F3A0007836CA /* OFRunLoop.h */, 4B325EDA1605F3A0007836CA /* OFRunLoop.m */, 4B6C8AD117BD5C2E00B194F2 /* OFRunLoop+Private.h */, 4B981CDE116F71DD00294DB7 /* OFSeekableStream.h */, 4B981CDF116F71DD00294DB7 /* OFSeekableStream.m */, @@ -1498,10 +1506,11 @@ 4B6EF6721235358D0076B512 /* OFListTests.m */, 4B6EF6731235358D0076B512 /* OFMD5HashTests.m */, 4B6EF6741235358D0076B512 /* OFNumberTests.m */, 4B6EF6751235358D0076B512 /* OFObjectTests.m */, 4B6EF6761235358D0076B512 /* OFPluginTests.m */, + 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */, 4B3D5693139A617D0010A78F /* OFSerializationTests.m */, 4B4B6903191437D500334775 /* OFSetTests.m */, 4B6EF6771235358D0076B512 /* OFSHA1HashTests.m */, 4B24592E19B53BC80059F271 /* OFSHA224HashTests.m */, 4B24592F19B53BC80059F271 /* OFSHA256HashTests.m */, @@ -1641,10 +1650,11 @@ 4BB25E88139C388A00F574EA /* OFObject+Serialization.h in Headers */, 4BAFC168182EAA7800BE5E57 /* OFOptionsParser.h in Headers */, 4B3D23D21337FCB000DD29B8 /* OFPlugin.h in Headers */, 4BB524C1143D1E4E0085FBCC /* OFProcess.h in Headers */, 4B674405163C395900EB1E59 /* OFRecursiveMutex.h in Headers */, + 4BEC83B919B7CB7100E4BB08 /* OFRIPEMD160Hash.h in Headers */, 4B325EDD1605F3A0007836CA /* OFRunLoop.h in Headers */, 4B3D23D31337FCB000DD29B8 /* OFSeekableStream.h in Headers */, 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */, 4B39844213D3A24600E6F825 /* OFSet.h in Headers */, 4B8385181951BF9500D5358A /* OFSettings.h in Headers */, @@ -2020,10 +2030,11 @@ 4BB25E89139C388A00F574EA /* OFObject+Serialization.m in Sources */, 4BAFC169182EAA7800BE5E57 /* OFOptionsParser.m in Sources */, 4B3D23A01337FC0D00DD29B8 /* OFPlugin.m in Sources */, 4BB524C2143D1E4E0085FBCC /* OFProcess.m in Sources */, 4B674406163C395900EB1E59 /* OFRecursiveMutex.m in Sources */, + 4BEC83BA19B7CB7100E4BB08 /* OFRIPEMD160Hash.m in Sources */, 4B325EDE1605F3A0007836CA /* OFRunLoop.m in Sources */, 4B3D23A11337FC0D00DD29B8 /* OFSeekableStream.m in Sources */, 4B39844313D3A24600E6F825 /* OFSet.m in Sources */, 4BA85BCF140ECCE800E91D51 /* OFSet_hashtable.m in Sources */, 4B8385191951BF9500D5358A /* OFSettings.m in Sources */, @@ -2153,17 +2164,18 @@ 4BF33B03133807A20059CEF7 /* OFListTests.m in Sources */, 4BF33B04133807A20059CEF7 /* OFMD5HashTests.m in Sources */, 4BF33B05133807A20059CEF7 /* OFNumberTests.m in Sources */, 4BF33B06133807A20059CEF7 /* OFObjectTests.m in Sources */, 4BF33B07133807A20059CEF7 /* OFPluginTests.m in Sources */, - 4B6025A819B76B5000694BCC /* OFSHA512HashTests.m in Sources */, + 4BEC83BC19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m in Sources */, 4B3D5694139A617D0010A78F /* OFSerializationTests.m in Sources */, 4B4B6904191437D500334775 /* OFSetTests.m in Sources */, - 4B6025A719B76B5000694BCC /* OFSHA384HashTests.m in Sources */, 4BF33B08133807A20059CEF7 /* OFSHA1HashTests.m in Sources */, 4B24593019B53BC80059F271 /* OFSHA224HashTests.m in Sources */, 4B24593119B53BC80059F271 /* OFSHA256HashTests.m in Sources */, + 4B6025A719B76B5000694BCC /* OFSHA384HashTests.m in Sources */, + 4B6025A819B76B5000694BCC /* OFSHA512HashTests.m in Sources */, 4BF33B09133807A20059CEF7 /* OFStreamTests.m in Sources */, 4BF33B0A133807A20059CEF7 /* OFStringTests.m in Sources */, 4BF33B0B133807A20059CEF7 /* OFTCPSocketTests.m in Sources */, 4BF33B0C133807A20059CEF7 /* OFThreadTests.m in Sources */, 4B0EA925189869D900F573A4 /* OFUDPSocketTests.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -38,10 +38,11 @@ OFNumber.m \ OFObject.m \ OFObject+Serialization.m \ OFOptionsParser.m \ ${OFPROCESS_M} \ + OFRIPEMD160Hash.m \ OFRunLoop.m \ OFSeekableStream.m \ OFSet.m \ OFSHA1Hash.m \ OFSHA224Hash.m \ Index: src/OFDataArray+Hashing.h ================================================================== --- src/OFDataArray+Hashing.h +++ src/OFDataArray+Hashing.h @@ -32,10 +32,18 @@ * * @return The MD5 hash of the data array as an autoreleased OFString */ - (OFString*)MD5Hash; +/*! + * @brief Returns the RIPEMD-160 hash of the data array as an autoreleased + * OFString. + * + * @return The RIPEMD-160 hash of the data array as an autoreleased OFString + */ +- (OFString*)RIPEMD160Hash; + /*! * @brief Returns the SHA-1 hash of the data array as an autoreleased OFString. * * @return The SHA-1 hash of the data array as an autoreleased OFString */ Index: src/OFDataArray+Hashing.m ================================================================== --- src/OFDataArray+Hashing.m +++ src/OFDataArray+Hashing.m @@ -18,10 +18,11 @@ #import "OFDataArray.h" #import "OFString.h" #import "OFHash.h" #import "OFMD5Hash.h" +#import "OFRIPEMD160Hash.h" #import "OFSHA1Hash.h" #import "OFSHA224Hash.h" #import "OFSHA256Hash.h" #import "OFSHA384Hash.h" #import "OFSHA512Hash.h" @@ -61,10 +62,15 @@ - (OFString*)MD5Hash { return [self OF_hashAsStringWithHash: [OFMD5Hash class]]; } + +- (OFString*)RIPEMD160Hash +{ + return [self OF_hashAsStringWithHash: [OFRIPEMD160Hash class]]; +} - (OFString*)SHA1Hash { return [self OF_hashAsStringWithHash: [OFSHA1Hash class]]; } ADDED src/OFRIPEMD160Hash.h Index: src/OFRIPEMD160Hash.h ================================================================== --- src/OFRIPEMD160Hash.h +++ src/OFRIPEMD160Hash.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFHash.h" + +/*! + * @class OFRIPEMD160Hash OFRIPEMD160Hash.h ObjFW/OFRIPEMD160Hash.h + * + * @brief A class which provides functions to create a RIPEMD-160 hash. + */ +@interface OFRIPEMD160Hash: OFObject +{ + uint32_t _state[5]; + uint64_t _bits; + union { + uint8_t bytes[64]; + uint32_t words[16]; + } _buffer; + size_t _bufferLength; + bool _calculated; +} +@end ADDED src/OFRIPEMD160Hash.m Index: src/OFRIPEMD160Hash.m ================================================================== --- src/OFRIPEMD160Hash.m +++ src/OFRIPEMD160Hash.m @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFRIPEMD160Hash.h" + +#import "OFHashAlreadyCalculatedException.h" + +#define F(a, b, c) ((a) ^ (b) ^ (c)) +#define G(a, b, c) (((a) & (b)) | (~(a) & (c))) +#define H(a, b, c) (((a) | ~(b)) ^ (c)) +#define I(a, b, c) (((a) & (c)) | ((b) & ~(c))) +#define J(a, b, c) ((a) ^ ((b) | ~(c))) + +static const uint8_t wordOrder[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +}; +static const uint8_t wordOrder2[] = { + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +}; +static const uint8_t rotateBits[] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +}; +static const uint8_t rotateBits2[] = { + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +}; + +static void +byteSwapVectorIfBE(uint32_t *vector, uint_fast8_t length) +{ + uint_fast8_t i; + + for (i = 0; i < length; i++) + vector[i] = OF_BSWAP32_IF_BE(vector[i]); +} + +static void +processBlock(uint32_t *state, uint32_t *buffer) +{ + uint32_t new[5], new2[5]; + uint_fast8_t i = 0; + + new[0] = new2[0] = state[0]; + new[1] = new2[1] = state[1]; + new[2] = new2[2] = state[2]; + new[3] = new2[3] = state[3]; + new[4] = new2[4] = state[4]; + + byteSwapVectorIfBE(buffer, 16); + +#define LOOP_BODY(f, g, k, k2) \ + { \ + uint32_t tmp; \ + \ + tmp = new[0] + f(new[1], new[2], new[3]) + \ + buffer[wordOrder[i]] + k; \ + tmp = OF_ROL(tmp, rotateBits[i]) + new[4]; \ + \ + new[0] = new[4]; \ + new[4] = new[3]; \ + new[3] = OF_ROL(new[2], 10); \ + new[2] = new[1]; \ + new[1] = tmp; \ + \ + tmp = new2[0] + g(new2[1], new2[2], new2[3]) + \ + buffer[wordOrder2[i]] + k2; \ + tmp = OF_ROL(tmp, rotateBits2[i]) + new2[4]; \ + \ + new2[0] = new2[4]; \ + new2[4] = new2[3]; \ + new2[3] = OF_ROL(new2[2], 10); \ + new2[2] = new2[1]; \ + new2[1] = tmp; \ + } + + for (; i < 16; i++) + LOOP_BODY(F, J, 0x00000000, 0x50A28BE6) + for (; i < 32; i++) + LOOP_BODY(G, I, 0x5A827999, 0x5C4DD124) + for (; i < 48; i++) + LOOP_BODY(H, H, 0x6ED9EBA1, 0x6D703EF3) + for (; i < 64; i++) + LOOP_BODY(I, G, 0x8F1BBCDC, 0x7A6D76E9) + for (; i < 80; i++) + LOOP_BODY(J, F, 0xA953FD4E, 0x00000000) + +#undef LOOP_BODY + + new2[3] += state[1] + new[2]; + state[1] = state[2] + new[3] + new2[4]; + state[2] = state[3] + new[4] + new2[0]; + state[3] = state[4] + new[0] + new2[1]; + state[4] = state[0] + new[1] + new2[2]; + state[0] = new2[3]; +} + +@implementation OFRIPEMD160Hash ++ (size_t)digestSize +{ + return 20; +} + ++ (size_t)blockSize +{ + return 64; +} + ++ (instancetype)hash +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + self = [super init]; + + _state[0] = 0x67452301; + _state[1] = 0xEFCDAB89; + _state[2] = 0x98BADCFE; + _state[3] = 0x10325476; + _state[4] = 0xC3D2E1F0; + + return self; +} + +- (void)updateWithBuffer: (const void*)buffer_ + length: (size_t)length +{ + const uint8_t *buffer = buffer_; + + if (_calculated) + @throw [OFHashAlreadyCalculatedException + exceptionWithHash: self]; + + _bits += (length * 8); + + while (length > 0) { + size_t min = 64 - _bufferLength; + + if (min > length) + min = length; + + memcpy(_buffer.bytes + _bufferLength, buffer, min); + _bufferLength += min; + + buffer += min; + length -= min; + + if (_bufferLength == 64) { + processBlock(_state, _buffer.words); + _bufferLength = 0; + } + } +} + +- (const uint8_t*)digest +{ + if (_calculated) + return (const uint8_t*)_state; + + _buffer.bytes[_bufferLength] = 0x80; + memset(_buffer.bytes + _bufferLength + 1, 0, 64 - _bufferLength - 1); + + if (_bufferLength >= 56) { + processBlock(_state, _buffer.words); + memset(_buffer.bytes, 0, 64); + } + + _buffer.words[14] = OF_BSWAP32_IF_BE((uint32_t)(_bits & 0xFFFFFFFF)); + _buffer.words[15] = OF_BSWAP32_IF_BE((uint32_t)(_bits >> 32)); + + processBlock(_state, _buffer.words); + memset(&_buffer, 0, sizeof(_buffer)); + byteSwapVectorIfBE(_state, 5); + _calculated = true; + + return (const uint8_t*)_state; +} + +- (bool)isCalculated +{ + return _calculated; +} +@end Index: src/OFString+Hashing.h ================================================================== --- src/OFString+Hashing.h +++ src/OFString+Hashing.h @@ -30,10 +30,17 @@ * * @return The MD5 hash of the string as an autoreleased OFString */ - (OFString*)MD5Hash; +/*! + * @brief Returns the RIPEMD-160 hash of the string as an autoreleased OFString. + * + * @return The RIPEMD-160 hash of the string as an autoreleased OFString + */ +- (OFString*)RIPEMD160Hash; + /*! * @brief Returns the SHA-1 hash of the string as an autoreleased OFString. * * @return The SHA-1 hash of the string as an autoreleased OFString */ Index: src/OFString+Hashing.m ================================================================== --- src/OFString+Hashing.m +++ src/OFString+Hashing.m @@ -17,10 +17,11 @@ #include "config.h" #import "OFString.h" #import "OFHash.h" #import "OFMD5Hash.h" +#import "OFRIPEMD160Hash.h" #import "OFSHA1Hash.h" #import "OFSHA224Hash.h" #import "OFSHA256Hash.h" #import "OFSHA384Hash.h" #import "OFSHA512Hash.h" @@ -60,10 +61,15 @@ - (OFString*)MD5Hash { return [self OF_hashAsStringWithHash: [OFMD5Hash class]]; } + +- (OFString*)RIPEMD160Hash +{ + return [self OF_hashAsStringWithHash: [OFRIPEMD160Hash class]]; +} - (OFString*)SHA1Hash { return [self OF_hashAsStringWithHash: [OFSHA1Hash class]]; } Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -71,10 +71,11 @@ # import "OFProcess.h" #endif #import "OFHash.h" #import "OFMD5Hash.h" +#import "OFRIPEMD160Hash.h" #import "OFSHA1Hash.h" #import "OFSHA224Hash.h" #import "OFSHA256Hash.h" #import "OFSHA384Hash.h" #import "OFSHA512Hash.h" Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -32,10 +32,11 @@ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ ${OFHTTPCLIENTTESTS_M} SRCS_FILES = OFINIFileTests.m \ OFMD5HashTests.m \ + OFRIPEMD160HashTests.m \ OFSerializationTests.m \ OFSHA1HashTests.m \ OFSHA224HashTests.m \ OFSHA256HashTests.m \ OFSHA384HashTests.m \ Index: tests/OFDataArrayTests.m ================================================================== --- tests/OFDataArrayTests.m +++ tests/OFDataArrayTests.m @@ -100,10 +100,13 @@ atIndex: 1 count: 2]) && [array[0] count] == 5 && !memcmp([array[0] items], "abcde", 5)) TEST(@"-[MD5Hash]", [[array[0] MD5Hash] isEqual: [@"abcde" MD5Hash]]) + + TEST(@"-[RIPEMD160Hash]", [[array[0] RIPEMD160Hash] + isEqual: [@"abcde" RIPEMD160Hash]]) TEST(@"-[SHA1Hash]", [[array[0] SHA1Hash] isEqual: [@"abcde" SHA1Hash]]) TEST(@"-[SHA224Hash]", [[array[0] SHA224Hash] isEqual: [@"abcde" SHA224Hash]]) ADDED tests/OFRIPEMD160HashTests.m Index: tests/OFRIPEMD160HashTests.m ================================================================== --- tests/OFRIPEMD160HashTests.m +++ tests/OFRIPEMD160HashTests.m @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFRIPEMD160Hash.h" +#import "OFString.h" +#import "OFFile.h" +#import "OFAutoreleasePool.h" + +#import "OFHashAlreadyCalculatedException.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFRIPEMD160Hash"; + +const uint8_t testfile_rmd160[20] = + "\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE" + "\xE6\x08\x8B"; + +@implementation TestsAppDelegate (OFRIPEMD160HashTests) +- (void)RIPEMD160HashTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFRIPEMD160Hash *rmd160; + OFFile *f = [OFFile fileWithPath: @"testfile.bin" + mode: @"rb"]; + + TEST(@"+[hash]", (rmd160 = [OFRIPEMD160Hash hash])) + + while (![f isAtEndOfStream]) { + char buf[64]; + size_t len = [f readIntoBuffer: buf + length: 64]; + [rmd160 updateWithBuffer: buf + length: len]; + } + [f close]; + + TEST(@"-[digest]", !memcmp([rmd160 digest], testfile_rmd160, 20)) + + EXPECT_EXCEPTION(@"Detect invalid call of " + @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException, + [rmd160 updateWithBuffer: "" + length: 1]) + + [pool drain]; +} +@end Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -535,10 +535,13 @@ #undef SWAPPED_BYTE_ORDER TEST(@"-[MD5Hash]", [[@"asdfoobar" MD5Hash] isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) + TEST(@"-[RIPEMD160Hash]", [[@"asdfoobar" RIPEMD160Hash] + isEqual: @"021d773b0fac06eb6755ca6aa58a580c980f7f13"]) + TEST(@"-[SHA1Hash]", [[@"asdfoobar" SHA1Hash] isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"]) TEST(@"-[SHA224Hash]", [[@"asdfoobar" SHA224Hash] isEqual: Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -129,10 +129,14 @@ @end @interface TestsAppDelegate (PropertiesTests) - (void)propertiesTests; @end + +@interface TestsAppDelegate (OFRIPEMD160HashTests) +- (void)RIPEMD160HashTests; +@end @interface TestsAppDelegate (SerializationTests) - (void)serializationTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -338,10 +338,11 @@ [self dateTests]; [self numberTests]; [self streamTests]; #ifdef OF_HAVE_FILES [self MD5HashTests]; + [self RIPEMD160HashTests]; [self SHA1HashTests]; [self SHA224HashTests]; [self SHA256HashTests]; [self SHA384HashTests]; [self SHA512HashTests];