Reputation: 15813
Argh, my head hurts!
Context
I need to write some C/Objective-C code to decrypt files that are stored on a remote server. The encryption is open-source and written in C#
I'm using libssl.a and libcrypto.a from this project;
https://github.com/x2on/OpenSSL-for-iPhone
My first hurdle is even getting the HMACSHA1 of a string to be correct :( The SHA1 seems to be correct according to a reference site here - http://hash.online-convert.com/sha1-generator but the HMAC is not. OK, so now some code;
NSString *input = @"wombats";
// Define some strings etc that we need
unsigned char *inStrg = malloc(256);
inStrg = (unsigned char *)[input UTF8String];
unsigned long lngth = [input length];
unsigned char result [EVP_MAX_MD_SIZE];
unsigned char hmacresult [EVP_MAX_MD_SIZE];
unsigned char newPassPhrase[25];
memset(newPassPhrase, 0, 25);
unsigned char salt[] = "\x01\x02\x03\x04\x05\x06\x07\x08";
// The real code requires us to re-hash the input 1000 times. For now lets
// just check it with 10 (hey even the first is wrong).
for (int i=0; i<10; i++)
{
// Use openssl
SHA_CTX shaContext;
SHA1_Init(&shaContext);
SHA1_Update(&shaContext, inStrg, lngth );
SHA1_Final(result, &shaContext);
unsigned int len;
// If I look at result now, it matches the reference, so I think it is the next stage that goes wrong.
HMAC(EVP_sha1(),salt,8,result,20,hmacresult,&len);
printf("HMAC ----------------- : ");
hexPrint(hmacresult,len);
// Copy the result to the input so we can re-hash;
lngth = len;
memcpy((char *)inStrg,(char *)hmacresult,len);
}
The code I am trying to match is the following C# fragment. This code generates the correct output and is an extract from the production server.
byte[] salt={0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
UTF8Encoding utf8 = new UTF8Encoding();
byte[] data = utf8.GetBytes("wombats");
HMACSHA1 sha1= new HMACSHA1();
sha1.Key = salt;
for(int i=0; i<10; i++)
{
sha1.ComputeHash(data);
data = sha1.Hash;
Console.WriteLine(System.BitConverter.ToString(data));
}
If I compile and run the C# code, the output I get is the following sequence;
DC-F3-1C-C1-2F-8A-86-16-CC-74-1E-DA-25-7B-FF-16-6E-EB-2A-0F
E7-6A-F4-C6-73-07-DB-E8-52-82-9E-D1-96-BF-06-95-85-C6-94-F4
1F-E2-61-BC-F0-08-92-3C-14-70-2B-89-EB-46-C9-20-A5-90-65-9B
etc
If I look at the output from the iPhone version, I get the following;
44-35-5b-bb-41-0e-bc-c3-d3-58-62-e6-5c-a0-51-6b-bc-97-11-f6
4c-3b-61-bd-1f-f7-72-13-af-1b-5e-5e-e3-70-8a-31-08-11-67-f2
41-56-8d-41-c1-3e-02-d0-d2-76-ad-d3-49-ba-71-ff-34-d7-3e-8b
etc
So there is clearly something seriously wrong.
If I check just the SHA1 part, that seems correct, so I'm guessing that either I'm using HMAC with the wrong parameters, or the C# HMACSHA1 does something different to my expectations.
I should add that if I use a suitable ASCII salt, the result of the online generator here http://hash.online-convert.com/sha1-generator also matches the C# code which strongly leads me to suspect it is my C on the iPhone that is wrong.
Can anyone assist me with working out what the problem is, I'm running out of ideas at the moment!
Upvotes: 2
Views: 865
Reputation: 15813
Removing the duplicate SHA1 fixes it. DOH!
SHA_CTX shaContext;
SHA1_Init(&shaContext);
SHA1_Update(&shaContext, inStrg, lngth );
SHA1_Final(result, &shaContext);
Delete all of this.
Upvotes: 1
Reputation: 11156
It could be worth your time to just use the methods in <CommonCrypto/CommonHMAC.h>
(not a framework, just headers in /usr/include
).
Upvotes: 0