我正在尝试为我的学校制作一个与PowerSchool互动的应用程序,这是一款允许用户查看其成绩,教师,日程安排等的软件。我找到了一个用PHP编写的与PowerSchool交互的基础知识库,并且在过去的一周里一直试图用它来编写目标c。似乎问题是如何使用用户密码创建HMAC(MD5)。要么我使用十六进制摘要而不是摘要,不确定。我从服务器返回的错误是奇数个字符。 这是我试图重新创建的PHP库类的链接: https://github.com/horvste/powerapi-php/blob/master/src/PowerAPI/Core.php 这是我的测试项目中的代码, 命令行主类: https://gist.github.com/anonymous/c40cdd99a826c06073aa NSString类别实现文件:
#import "NSString+MyAdditions.h"
@implementation NSString (MyAdditions)
- (NSString *) hmacMD5WithData: (NSString *) data
{
const char *cKey = [self cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
const unsigned int blockSize = 64;
char ipad[blockSize], opad[blockSize], keypad[blockSize];
unsigned int keyLen = strlen(cKey);
CC_MD5_CTX ctxt;
if(keyLen > blockSize)
{
//CC_MD5(cKey, keyLen, keypad);
CC_MD5_Init(&ctxt);
CC_MD5_Update(&ctxt, cKey, keyLen);
CC_MD5_Final((unsigned char *)keypad, &ctxt);
keyLen = CC_MD5_DIGEST_LENGTH;
}
else
{
memcpy(keypad, cKey, keyLen);
}
memset(ipad, 0x36, blockSize);
memset(opad, 0x5c, blockSize);
int i;
for(i = 0; i < keyLen; i++)
{
ipad[i] ^= keypad[i];
opad[i] ^= keypad[i];
}
CC_MD5_Init(&ctxt);
CC_MD5_Update(&ctxt, ipad, blockSize);
CC_MD5_Update(&ctxt, cData, strlen(cData));
unsigned char md5[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(md5, &ctxt);
CC_MD5_Init(&ctxt);
CC_MD5_Update(&ctxt, opad, blockSize);
CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH);
CC_MD5_Final(md5, &ctxt);
const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2;
char hex[hex_len];
for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
{
snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]);
}
NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)];
NSString *hash = [HMAC base64EncodedStringWithOptions:0];
return hash;
}
@end
感谢您抽出宝贵时间来研究这个问题!
答案 0 :(得分:1)
首先,不要在这里建立自己的HMAC例程。使用CCHmac。它内置并正确处理HMAC + MD5。
如果可能,我建议转到API文档,而不是尝试对另一个代码库进行反向工程。你可能会忽略PHP中有很多小事情发生; API文档应该解释所有这些。
如果PHP代码是您唯一的参考,那么您应该分解每个部分并查看它出错的地方。例如,验证您是否以相同的形式获取身份验证数据。然后确认每个程序在给定相同的auth数据的情况下生成相同的HMAC。然后确认给定相同的HMAC,每个程序生成相同的响应。等等。你正在做某些不同的事情。确保您在相同的位置使用Base64 vs原始数据(PHP开发人员倾向于将Base64字符串视为实际原始数据,这会在转到ObjC时引起混淆。)
当然,您应该检查服务器日志以验证您的最终请求是否与PHP请求匹配。