Getting HMACSHA1 correctly on iPhone using openssl
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 cha开发者_如何学Pythonr *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!
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.
It could be worth your time to just use the methods in <CommonCrypto/CommonHMAC.h>
(not a framework, just headers in /usr/include
).
精彩评论