记录使用oc进行sha256计算验签的部分逻辑

记录编写的验签部分逻辑
主要用到ascii、unicode编码、sha256

  • IFSignatureHelper.h代码

    #import <Foundation/Foundation.h>
    #import <CommonCrypto/CommonDigest.h>
    #import <CommonCrypto/CommonHMAC.h>
    
    // key的公共部分
    #define KEY_BASIC @"catface@catface@catface-2021"
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface IFSignatureHelper : NSObject
    
    // key的动态部分
    @property(nonatomic,strong)NSString *key;
    
    // 生成验签的对外方法
    -(NSString*)signature:
        (NSString*)keyPrivate
        withNormalParamsDict:(NSDictionary*)normalParamsDict
        withQueryParamsDict:(NSDictionary*)queryParamsDict
        withBodyParamsDict:(NSDictionary*)bodyParamsDict;
    
    // 字符串内中文转unicode
    -(NSString*)utf8ToUnicode:(NSString*)string;
    
    // 字符串encode编码
    -(NSString*)encodeString:(NSString*)unencodedString;
    
    // 单纯的sha256摘要计算
    -(NSString *)hmac:(NSString*)plaintext:(NSString *)key;
    
    // sha256生成验签
    -(NSString*) hmac_sha256: (NSString*)value;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
  • IFSignatureHelper.m代码

    #import "IFSignatureHelper.h"
    #import "NSString+SHA256HMAC.h"
    
    @implementation IFSignatureHelper
    
    
    -(NSString*)utf8ToUnicode:(NSString*)string{
        NSUInteger length = [string length];
        NSMutableString *s = [NSMutableString stringWithCapacity:0];
        for (int i = 0;i < length; i++) {
            unichar _char = [string characterAtIndex:i];
            if (_char <= '9' && _char >='0') {
                [s appendFormat:@"%@",[string substringWithRange:NSMakeRange(i,1)]];
            }else if(_char >='a' && _char <= 'z') {
                [s appendFormat:@"%@",[string substringWithRange:NSMakeRange(i,1)]];
            }else if(_char >='A' && _char <= 'Z') {
                [s appendFormat:@"%@",[string substringWithRange:NSMakeRange(i,1)]];
            }else if(_char >= 0x4e00 && _char <=0x9fff) {
                [s appendFormat:@"\\u%x",[string characterAtIndex:i]];
            } else {
                [s appendFormat:@"%@",[string substringWithRange:NSMakeRange(i,1)]];
            }
        }
        
        return s;
    }
    
    
    -(NSString*)encodeString:(NSString*)unencodedString{
        NSString *encodedString = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)unencodedString, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
        
        return encodedString;
    }
    
    
    -(NSString*)hmac:(NSString*)plaintext:(NSString*)key{
        const char *cKey  = [key cStringUsingEncoding:NSUTF8StringEncoding];
        const char *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];
        unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
        CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
        NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
        const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
        NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];
        for (int i = 0; i < HMACData.length; ++i){
            [HMAC appendFormat:@"%02x", buffer[i]];
        }
    
        return HMAC;
    }
    
    
    -(NSString*)hmac_sha256:(NSString*)value{
        NSString *tempKey = [KEY_BASIC stringByAppendingString:[self key]];
        NSString *temp = [[self key] substringToIndex:1];
        int tempASCII = [temp characterAtIndex:0] + 200;
        NSMutableArray *new_key = [[NSMutableArray alloc] init];
        for (int i = 0, keyLength = tempKey.length; i < keyLength; i++) {
            int characterAtIndex = [tempKey characterAtIndex:i];
            // char转ascii
            int new_temp = (characterAtIndex ^ tempASCII) & 255;
            char charactor = [tempKey characterAtIndex:i];
            // ascii转char
            [new_key addObject:[NSString stringWithFormat:@"%c", new_temp]];
        }
        
        // componentsJoinedByString即数组转字符串
        return [self hmac:value:[new_key componentsJoinedByString:@""]];
    }
    
    
    -(NSString*)signature:
        (NSString*)keyPrivate
        withNormalParamsDict:(NSDictionary*)normalParamsDict
        withQueryParamsDict:(NSDictionary*)queryParamsDict
        withBodyParamsDict:(NSDictionary*)bodyParamsDict{
        [self setKey:keyPrivate];
        
        // 组合params
        NSMutableDictionary* allParamsDict = [[NSMutableDictionary alloc]initWithDictionary:normalParamsDict];
        // 添加query params
        if (nil != queryParamsDict) {
            [allParamsDict setValue:[queryParamsDict objectForKey:@"queryString"] forKey:@"queryString"];
        }
        // 添加body params[// todo 转json会乱序,可能需要处理顺序]
        if (nil != bodyParamsDict) {
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:bodyParamsDict options:NSJSONWritingSortedKeys error:0];
            NSString *dataStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
            dataStr = [self utf8ToUnicode:dataStr];
            [allParamsDict setValue:dataStr forKey:@"bodyString"];
        }
        
        // params排序[最后组合成按顺序的数组,如akey=avalue&bkey=bvalue]
        NSMutableDictionary* allSortedParams = [[NSMutableDictionary alloc]init];
        NSArray* keys = allParamsDict.allKeys;
        NSArray* sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
        }];
        NSMutableArray* resultArray = [[NSMutableArray alloc]init];
        for (int i = 0; i < sortedKeys.count; i++) {
            NSString* key = sortedKeys[i];
            NSString* value = [allParamsDict objectForKey:sortedKeys[i]];
            
            // key和value进行unicode编码
            key = [self encodeString:key];
            value = [self encodeString:value];
            NSString* keyAndValue =[NSString stringWithFormat:@"%@=%@", key, value];
            [resultArray addObject:keyAndValue];
        }
        NSString* resultString = [resultArray componentsJoinedByString:@"&"];
        // 空格和引号后补充加号+
        resultString = [resultString stringByReplacingOccurrencesOfString:@"%3A" withString:@"%3A+"];
        resultString = [resultString stringByReplacingOccurrencesOfString:@"%2C" withString:@"%2C+"];
        
        return [self hmac_sha256:resultString];
    }
    @end
    
  • 使用示例

    #define sig_key @"123456789_987654321"
    // 添加中文测试unicode编码是否正确且符合逻辑
    - (IBAction)generateSignature:(id)sender {
        NSDictionary* normalParams = @{
            @"name":@"zhangsan张三",
            @"pass":@"password密码"
        };
        
        NSDictionary* queryParams = @{
            @"queryString":@"q1=v1&q2=值2"
        };
        
        NSDictionary* bodyParams = @{
            @"b1":@"v1",
            @"b3":@"v值3",
            @"b2":@"值z2",
        };
        
        IFSignatureHelper *helper = [[IFSignatureHelper alloc]init];
        NSString *result = [helper signature:sig_key withNormalParamsDict:normalParams withQueryParamsDict:queryParams withBodyParamsDict:bodyParams];
        NSLog(@"signature result is:%@", result);
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值