How to do CRC32 hashing on a string in objective C - objective-c
as per title, i couldnt find another tutorial on this...
i found a piece of code here: http://classroomm.com/objective-c/index.php?action=printpage;topic=2891.0
but it is giving me alot of warnings and doesnt really know how to use it.
Any other solution?
You might want to check this out - http://code.google.com/p/ofc/wiki/DCRC32
Just use crc32() function, it's simple and straight forward. See this answer for details: https://stackoverflow.com/a/14533955/1760595
I modified http://www.csbruce.com/software/crc32.c slightly,
and used UTF8String method to get a pointer to the internal CString representation of NSString.
This saves copying.
Unfotunately zlib's crc32 implementation needs a buffer length.
This one just terminates with the 0 byte at the end of the C-String.
#implementation NSString (crc32)
static unsigned long Crc32_String(const char *string)
{
static const unsigned long crcTable[256] = {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,
0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,
0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,
0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,
0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,
0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,
0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,
0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,
0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,
0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,
0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,
0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,
0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,
0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,
0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,
0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,
0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,
0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,
0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,
0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,
0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,
0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,
0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,
0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,
0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,
0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,
0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,
0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D };
unsigned long crc32;
unsigned char *byteBuf;
size_t i;
char byte;
/** accumulate crc32 for buffer **/
crc32 = 0;
byteBuf = (unsigned char *) string;
i = 0;
while ((byte = byteBuf[i++])) {
crc32 = (crc32 >> 8) ^ crcTable[ (crc32 ^ byte) & 0xFF ];
}
return( crc32 ^ 0xFFFFFFFF );
}
- (unsigned long)crc32
{
return Crc32_String(0, [self UTF8String]);
}
#end
Related
How can I transfer data from unsigned char * to char * safely?
I am willing to transfer data from unsigned char hash[512 + 1] to char res[512 + 1] safely. My C hashing library MHASH returns a result so it can be printed as listed below. for (int i = 0; i < size /*hash block size*/; i++) printf("%.2x", hash[i]); // which is unsigned char - it prints normal hash characters in range [a-z,0-9] printf("\n"); I am willing to do something like that (see below). const char* res = (const char *)hash; // "hash" to "res" printf("%s\n", res); // print "res" (which is const char*) - if i do this, unknown characters are printed I know the difference between char and unsigned char, but I don't know how to transfer data. Any answer would be greatly appreciated, thanks in advance. But please do not recommend me C++ (STD) code, I am working on a project that is not STD-linked.
Given that the contents of the unsigned char array are printable characters, you can always safely convert it to char. Either a hardcopy with memcpy or a pointer reference as in the code you have already written. I'm guessing that the actual problem here is that the unsigned char array contents are not actually printable characters, but integers in some format. You'll have to convert them from integer to ASCII letters. How to do this depends on the format of the data, which isn't clear in your question.
Assuming the following: #define ARR_SIZE (512 + 1) unsigned char hash[ARR_SIZE]; char res[ARR_SIZE]; /* filling up hash here. */ Just do: #include <string.h> ... memcpy(res, hash, ARR_SIZE);
Well, thank you guys for your answers, but unfortunately nothing worked yet. I am now sticking with the code below. char res[(sizeof(hash) * 2) + 1] = { '\0' }; char * pPtr = res; for (int i = 0; i < hashBlockSize; i++) sprintf(pPtr + (i * 2), "%.2x", hash[i]); return (const char *)pPtr; Until there is any other much more performant way to get this done. It's right, my question is strongly related to MHASH Library.
Some info about CC_SHA256 objective-c
For a new project I need to hash a NSString with SHA256. I have used the following code: unsigned char hashedChars[32]; NSString *inputString; inputString = [NSString stringWithFormat:#"hello"]; NSData * inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding]; CC_SHA256(inputData.bytes, inputData.length, hashedChars); I found this piece of code on stackoverflow. I do not really get all the things this code do here are some questions about the code: 1.The CC_SHA256 makes a hash but this hash will be stored in inputData again? What I mean can I do something like this: NSString *string=CC_SHA256(..) //of course you can't put it directly in a NSString, but you get the point 2.In the end the hash has to be a hexadecimal string, but what is the type that CC_SHA256 outputs (UTF-8??)? 3.The first parameter of CC_SHA256 why do I have to put bytes at the end and is "inputData" enough? 4.What is the need of the length of the string (second parameter)? 5.And the last parameter does not make any sense to me, can somebody please explain and why the hashedChars has to be 32?
The argument list for CC_SHA256 is: extern unsigned char *CC_SHA256(const void *data, CC_LONG len, unsigned char *md); From the man page: https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/CC_SHA256.3cc.html Parameters explained: *data is the input string, what you want to be hashed. It's a C string-type. A way to get this is to call 'inputData.bytes', with inputData a NSData object. len is the length of the input string. As you'll realize if you'll start working with C strings, it's pretty normal for functions working with strings to ask for the length. That's because in C strings are just a sequence of bytes, and while text strings are generally terminated by a null byte, binary strings can have any length. It's also for safety ("buffer overflows"). *md is the output. Again, this is returned as a C string, of fixed length 32 bytes for SHA256 (that's why you don't see an outputLength parameter). The output is "not relevant", but can be used to check if the function ran properly: if(CC_SHA256(...)) { all ok; } The result string is stored into *md, and it's a binary C string, 32 bytes long. It's 32 bytes long because that's the length of SHA256 digests; for example, 16 bytes for MD5, 20 bytes for SHA1, etc. It's just how the algorithm works! The output is just a binary string. If you want to make it into hex format you need to store it into a NSData object, and then get a hex representation of it: NSData *resultData = [NSData dataWithBytes:hashedChars length:32]; To get the hex representation then look at this SO answer: https://stackoverflow.com/a/25378464/192024
If anyone trying to find a similar function for Android, the below snippet produces the same output as CC_SHA256 public static String calculateSH256(String secret){ final MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-256"); byte[] bytes = secret.getBytes("UTF-8"); digest.update(bytes, 0, bytes.length); String sig = bytesToHex(digest.digest()); return sig; } catch (NoSuchAlgorithmException | UnsupportedEncodingException e){ throw new RuntimeException("Cannot calculate signature"); } } final protected static char[] hexArray = "0123456789abcdef".toCharArray(); private static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for ( int j = 0; j < bytes.length; j++ ) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); }
What does PKCS5_PBKDF2_HMAC_SHA1 return value mean?
I'm attempting to use OpenSSL's PKCS5_PBKDF2_HMAC_SHA1 method. I gather that it returns 0 if it succeeds, and some other value otherwise. My question is, what does a non-zero return value mean? Memory error? Usage error? How should my program handle it (retry, quit?)? Edit: A corollary question is, is there any way to figure this out besides reverse-engineering the method itself?
is there any way to figure this out besides reverse-engineering the method itself? PKCS5_PBKDF2_HMAC_SHA1 looks like one of those undocumented functions because I can't find it in the OpenSSL docs. OpenSSL has a lot of them, so you should be prepared to study the sources if you are going to use the library. I gather that it returns 0 if it succeeds, and some other value otherwise. Actually, its reversed. Here's how I know... $ grep -R PKCS5_PBKDF2_HMAC_SHA1 * crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, ... So, you find the function's implementation in crypto/evp/p5_crpt2.c: int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, int keylen, unsigned char *out) { return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), keylen, out); } Following PKCS5_PBKDF2_HMAC: $ grep -R PKCS5_PBKDF2_HMAC * ... crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, ... And again, from crypto/evp/p5_crpt2.c: int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) { unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; int cplen, j, k, tkeylen, mdlen; unsigned long i = 1; HMAC_CTX hctx_tpl, hctx; mdlen = EVP_MD_size(digest); if (mdlen < 0) return 0; HMAC_CTX_init(&hctx_tpl); p = out; tkeylen = keylen; if(!pass) passlen = 0; else if(passlen == -1) passlen = strlen(pass); if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) { HMAC_CTX_cleanup(&hctx_tpl); return 0; } while(tkeylen) { if(tkeylen > mdlen) cplen = mdlen; else cplen = tkeylen; /* We are unlikely to ever use more than 256 blocks (5120 bits!) * but just in case... */ itmp[0] = (unsigned char)((i >> 24) & 0xff); itmp[1] = (unsigned char)((i >> 16) & 0xff); itmp[2] = (unsigned char)((i >> 8) & 0xff); itmp[3] = (unsigned char)(i & 0xff); if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { HMAC_CTX_cleanup(&hctx_tpl); return 0; } if (!HMAC_Update(&hctx, salt, saltlen) || !HMAC_Update(&hctx, itmp, 4) || !HMAC_Final(&hctx, digtmp, NULL)) { HMAC_CTX_cleanup(&hctx_tpl); HMAC_CTX_cleanup(&hctx); return 0; } HMAC_CTX_cleanup(&hctx); memcpy(p, digtmp, cplen); for(j = 1; j < iter; j++) { if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { HMAC_CTX_cleanup(&hctx_tpl); return 0; } if (!HMAC_Update(&hctx, digtmp, mdlen) || !HMAC_Final(&hctx, digtmp, NULL)) { HMAC_CTX_cleanup(&hctx_tpl); HMAC_CTX_cleanup(&hctx); return 0; } HMAC_CTX_cleanup(&hctx); for(k = 0; k < cplen; k++) p[k] ^= digtmp[k]; } tkeylen-= cplen; i++; p+= cplen; } HMAC_CTX_cleanup(&hctx_tpl); return 1; } So it looks like 0 on failure, and 1 on success. You should not see other values. And if you get a 0, then all the OUT parameters are junk. Memory error? Usage error? Well, sometimes you can call ERR_get_error. If you call it and it makes sense, then the error code is good. If the error code makes no sense, then its probably not good. Sadly, that's the way I handle it because the library is not consistent with setting error codes. For example, here's the library code to load the RDRAND engine. Notice the code clears the error code on failure if its a 3rd generation Ivy Bridge (that's the capability being tested), and does not clear or set an error otherwise!!! void ENGINE_load_rdrand (void) { extern unsigned int OPENSSL_ia32cap_P[]; if (OPENSSL_ia32cap_P[1] & (1<<(62-32))) { ENGINE *toadd = ENGINE_rdrand(); if(!toadd) return; ENGINE_add(toadd); ENGINE_free(toadd); ERR_clear_error(); } } How should my program handle it (retry, quit?)? It looks like a hard failure. Finally, that's exactly how I navigate the sources in this situation. If you don't like grep you can try ctags or another source code browser.
c and objective-c -- const char* and char*
I have a function: -(void)ADPCMDecode:(char *)indata : (short *)outdata :(long)len { indata is a char and the function does pointer arithmetic to iterate for a length of len, modifying outdata, which is a short and I will need to do pointer arithmetic to get the values from it. I am attempting to call the function using: const char *modulatedBytes1 = [modulatedAudio bytes]; char *modulatedBytes [] = modulatedBytes1; unsigned int moduleatedLength = [modulatedAudio length]; short *decompressedBytes = NULL; [self ADPCMDecode:modulatedBytes :decompressedBytes :moduleatedLength]; DLog(#"%hi",decompressedBytes[1]); I get a BAD ACCESS error on this line: *outp++ = valprev; within the function, because I am passing a constant char * instead of a char * How should I call the function, and how would I get the output from it? I have no background in C, which is why I do not understand how to go about doing this. Here is the C only version of the same question: https://pastee.org/d3y3z
How to interpret objective-c type specifier (e.g. returned by method_copyReturnType())?
Given I have a type specifier as returned by method_copyReturnType(). In the GNU runtime delivered with the GCC there are various methods to work with such a type specifier like objc_sizeof_type(), objc_alignof_type() and others. When using the Apple runtime there are no such methods. How can I interpret a type specifier string (e.g. get the size of a type) using the Apple runtime without implementing an if/else or case switch for myself? [update] I am not able to use the Apple Foundation.
I believe that you're looking for NSGetSizeAndAlignment: Obtains the actual size and the aligned size of an encoded type. const char * NSGetSizeAndAlignment ( const char *typePtr, NSUInteger *sizep, NSUInteger *alignp ); Discussion Obtains the actual size and the aligned size of the first data type represented by typePtr and returns a pointer to the position of the next data type in typePtr. This is a Foundation function, not part of the base runtime, which is probably why you didn't find it. UPDATE: Although you didn't initially mention that you're using Cocotron, it is also available there. You can find it in Cocotron's Foundation, in NSObjCRuntime.m. Obviously, this is much better than rolling your own, since you can trust it to always correctly handle strings generated by its own runtime in the unlikely event that the encoding characters should change. For some reason, however, it's unable to handle the digit elements of a method signature string (which presumably have something to do with offsets in memory). This improved version, by Mike Ash will do so: static const char *SizeAndAlignment(const char *str, NSUInteger *sizep, NSUInteger *alignp, int *len) { const char *out = NSGetSizeAndAlignment(str, sizep, alignp); if(len) *len = out - str; while(isdigit(*out)) out++; return out; }
afaik, you'll need to bake that info into your binary. just create a function which returns the sizeof and alignof in a struct, supports the types you must support, then call that function (or class method) for the info. The program below shows you that many of the primitives are just one character. So the bulk of the function's implementation could be a switch. static void test(SEL sel) { Method method = class_getInstanceMethod([NSString class], sel); const char* const type = method_copyReturnType(method); printf("%s : %s\n", NSStringFromSelector(sel).UTF8String, type); free((void*)type); } int main(int argc, char *argv[]) { #autoreleasepool { test(#selector(init)); test(#selector(superclass)); test(#selector(isEqual:)); test(#selector(length)); return 0; } } and you could then use this as a starting point: typedef struct t_pair_alignof_sizeof { size_t align; size_t size; } t_pair_alignof_sizeof; static t_pair_alignof_sizeof MakeAlignOfSizeOf(size_t align, size_t size) { t_pair_alignof_sizeof ret = {align, size}; return ret; } static t_pair_alignof_sizeof test2(SEL sel) { Method method = class_getInstanceMethod([NSString class], sel); const char* const type = method_copyReturnType(method); const size_t length = strlen(type); if (1U == length) { switch (type[0]) { case '#' : return MakeAlignOfSizeOf(__alignof__(id), sizeof(id)); case '#' : return MakeAlignOfSizeOf(__alignof__(Class), sizeof(Class)); case 'c' : return MakeAlignOfSizeOf(__alignof__(signed char), sizeof(signed char)); ...