Проблемы с реализацией HMAC SHA1 в Objective-C

Я пытаюсь создать подпись base64 для запроса на отдых, используя алгоритм HMAC-SHA1. Я специально использую API-интерфейс SinglePlatform, и следующие шаги:

  1. Удалите доменную часть запроса, оставив только путь и запрос: / location / haru-7? Client = YOUR_CLIENT_ID
  2. Получите свой закрытый ключ, который закодирован в модифицированном Base64 для URL-адресов, и подпишите указанный выше URL-адрес с помощью алгоритма HMAC-SHA1. Возможно, вам потребуется декодировать ключ подписи в исходный двоичный формат. Во многих криптографических библиотеках результирующая подпись будет в двоичном формате.
  3. Закодируйте полученную двоичную подпись с помощью модифицированного Base64 для URL-адресов, чтобы преобразовать эту подпись во что-то, что можно передать в URL-адресе. Прикрепите эту подпись к URL-адресу с помощью параметра sig:

Моя текущая реализация выглядит следующим образом:

    // 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);

Первоначально полученный мной ключ подписи является модифицированным Base64, поэтому я заменяю символы - + _ /. Эта реализация вернула правильный ключ подписи, но не всегда.

Я что-то явно не так делаю, конвертируя Objective-C в C? Есть ли лучший способ справиться с этим?

Мое приложение использует ARC.


person minimalpop    schedule 12.04.2013    source источник


Ответы (1)


Проблема заключалась в том, что я использовал методы C для определения длины данных:

CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, strlen(keyBytes));
CCHmacUpdate(&ctx, baseStringBytes, strlen(baseStringBytes));
CCHmacFinal(&ctx, digestBytes);

Он работал стабильно, когда я использовал методы длины NSString / NSData:

CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, [key length]);
CCHmacUpdate(&ctx, baseStringBytes, [data length]);
CCHmacFinal(&ctx, digestBytes);

Изменить:
Как отмечал Ivo Beckers в комментариях, это также можно записать в одну строку:

CCHmac(kCCHmacAlgSHA1, keyBytes, strlen(keyBytes), baseStringBytes, strlen(baseStringBytes), digestBytes);
person minimalpop    schedule 11.10.2014
comment
хорошо, много боролся с HMAC-SHA1 с использованием ключа base64. Все остальные вопросы, связанные с HMAC-SHA1, похоже, связаны с другими типами ключей. Кстати, вы можете заменить все строки CCHmac одним CCHmac(kCCHmacAlgSHA1, keyBytes, strlen(keyBytes), baseStringBytes, strlen(baseStringBytes), digestBytes);. - person Ivo Beckers; 18.08.2016
comment
@IvoBeckers Спасибо, что указали на это. Я обновил ответ с помощью вашего единственного лайнера. - person minimalpop; 15.01.2017