Reputation: 7068
I'm trying to create a base64 signature for a rest request using the HMAC-SHA1 algorithm. I'm specifically using the SinglePlatform API, and the steps are:
My current implementation is as follows:
// Convert a modified Base64 key into Base64
NSString *modifiedKey = [SIGNING_KEY stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
modifiedKey = [modifiedKey stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
// Decode the Base64 key
NSData *key = [NSData dataFromBase64String:modifiedKey];
// Construct a url with params
NSString *data = [NSString stringWithFormat:@"/locations/%@?client=%@", _id, CLIENT_ID];
// Convert key and data to c chars
const char *keyBytes = [key bytes];
const char *baseStringBytes = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char digestBytes[CC_SHA1_DIGEST_LENGTH];
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, strlen(keyBytes));
CCHmacUpdate(&ctx, baseStringBytes, strlen(baseStringBytes));
CCHmacFinal(&ctx, digestBytes);
NSData *digestData = [NSData dataWithBytes:digestBytes length:CC_SHA1_DIGEST_LENGTH];
// Reconvert the into Base64 modified
NSString *signingKey = [digestData base64EncodedString];
signingKey = [signingKey stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
signingKey = [signingKey stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
if ( [data hasSuffix:@"="] ) {
[signingKey substringToIndex:[hassigningKeyh length]-1];
}
NSLog(@"Signing Key: %@", signingKey);
The signing key I originally received is modified Base64, which is why I am replacing the -+_/ characters. This implementation has returned the proper signature key, but not consistently.
Am I doing something blatantly wrong in converting Objective-C to C? Is there a better way to handle this?
My application is using ARC.
Upvotes: 2
Views: 731
Reputation: 7068
The issue was that I was C methods to determine the data length:
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, strlen(keyBytes));
CCHmacUpdate(&ctx, baseStringBytes, strlen(baseStringBytes));
CCHmacFinal(&ctx, digestBytes);
It worked consistently when I used the NSString/NSData length methods:
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, [key length]);
CCHmacUpdate(&ctx, baseStringBytes, [data length]);
CCHmacFinal(&ctx, digestBytes);
Edit:
As mentioned by Ivo Beckers
in the comments, this can also be written as a single line:
CCHmac(kCCHmacAlgSHA1, keyBytes, strlen(keyBytes), baseStringBytes, strlen(baseStringBytes), digestBytes);
Upvotes: 1