V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
Livid
V2EX  ›  iDev

一个关于 CommonCrypto 的问题

  •  
  •   Livid · 2012-02-23 05:00:22 +08:00 · 3741 次点击
    这是一个创建于 4448 天前的主题,其中的信息可能已经有所发展或是发生改变。
    同样的输入条件,同样的加密算法,理论上来说,应该可以产生完全一致的输出,但是 Objective-C 的输出始终是错的。

    Python 代码:

    payload['sig'] = base64.b64encode(hmac.new(bf3api_key, payload['data'], hashlib.sha256).digest(), '-_')

    Objective-C 代码:

    dataString = [[[[[data JSONRepresentation] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding] stringByReplacingOccurrencesOfString:@"+" withString:@"-"] stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
    NSMutableDictionary * payload = [[NSMutableDictionary alloc] initWithCapacity:2];
    [payload setObject:dataString forKey:@"data"];

    const char * cKey = [BF3API_KEY cStringUsingEncoding:NSASCIIStringEncoding];
    const char * cData = [dataString cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData * HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    NSString * hash = [HMAC base64Encoding];
    hash = [hash stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
    hash = [hash stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

    [payload setObject:hash forKey:@"sig"];

    输入是 data 和 key,目的是输出 sig。这些条件在两个版本的代码里是一样,用的也是同样的加密算法 SHA256,但是 Objective-C 出来就是错的。

    因为最后 sig 会作为 post 参数提交到服务上进行验证,而 Python 生成的 sig 是可以过的,也就是正确的。但是 Objective-C 用 CommonCrypto 生成的 sig 就没法过了。

    实在不明白为什么,所以请教这里的众多高手了。谢谢。
    5 条回复    1970-01-01 08:00:00 +08:00
    Livid
        1
    Livid  
    MOD
    OP
       2012-02-23 05:50:20 +08:00
    问题解决了。

    CommonCrypto 生成的输出肯定是和其他语言的一样的。

    确实是因为我输入的值在各种编码过程中造成的问题。
    Livid
        2
    Livid  
    MOD
    OP
       2012-02-23 05:52:22 +08:00
    不过真的还是想借此机会吐槽一下 Objective-C,一件本来很简单的事情,用 Python 一句话可以解决,但是到了这边就各种周折。

    另外就是,大家推荐一个比较好的将 NSDictionary 转化为 HTTP POST BODY 的 NSData 的开源实现吧?
    Kai
        3
    Kai  
    MOD
       2012-02-23 06:02:58 +08:00
    RKRequestSerialization ?
    shinyzhu
        4
    shinyzhu  
       2012-02-23 08:54:35 +08:00
    @Livid NSDictionary转换成POST body的在AFNetworking里面都有喔。具体代码在AFHTTPClient.m里面。

    函数
    NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding encoding);
    把字典做成HTTP Body的格式,然后再用
    - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding;
    转换成NSData,就可以直接放到body里面了。
    tokki
        5
    tokki  
       2012-02-23 09:46:03 +08:00
    这个asi里面也有的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1249 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 23:45 · PVG 07:45 · LAX 16:45 · JFK 19:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.