//
//  SPEncryption.m
//  SharedParking
//
//  Created by gui_huan on 2018/4/24.
//  Copyright © 2018年 tangshuanghui. All rights reserved.
//

#import "SPEncryption.h"
#import <CommonCrypto/CommonDigest.h>

@implementation SPEncryption

static NSString * const HHYMD5Key = @"!@#senlanit!#@";

+ (NSDictionary *)getMD5StringWithParameters:(NSDictionary *)parameters
{
    if (parameters == nil) {
        return nil;
    }
    NSMutableDictionary * newParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
    
    NSString * string = [self getParaStringWithParameters:parameters];
    NSString *MD5Srting = [self HMACMD5WithString:string];
    [newParameters setObject:MD5Srting forKey:@"sign"];
    return newParameters;
}

//参数按升序拼成字符串
+ (NSString *)getParaStringWithParameters:(NSDictionary *)parameters
{
    if (nil == parameters) {
        return nil;
    }
    NSArray * keyArray = [parameters allKeys];
    NSArray * sortArray = [keyArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    
    NSMutableArray * valueArray = [NSMutableArray array];
    for (NSString * sortString in sortArray) {
        [valueArray addObject:[parameters objectForKey:sortString]];
    }
    
    NSMutableArray * signArray = [NSMutableArray array];
    for (int i = 0; i < sortArray.count; i++) {
        NSString * keyValueStr = [NSString stringWithFormat:@"%@=%@",sortArray[i],valueArray[i]];
        [signArray addObject:keyValueStr];
    }
    
    NSString * parameterString = [signArray componentsJoinedByString:@"&"];
    
    //    TT_LOG(@"parameterString = %@", parameterString);
    return parameterString;
}
+ (NSString *)HMACMD5WithString:(NSString *)toEncryptStr
{
    const char *cKey  = [HHYMD5Key cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [toEncryptStr cStringUsingEncoding:NSUTF8StringEncoding];
    const unsigned int blockSize = 64;
    char ipad[blockSize];
    char opad[blockSize];
    char keypad[blockSize];
    
    unsigned long keyLen = strlen(cKey);
    CC_MD5_CTX ctxt;
    if (keyLen > blockSize) {
        CC_MD5_Init(&ctxt);
        CC_MD5_Update(&ctxt, cKey, (CC_LONG)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, (CC_LONG)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 = [[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding];
    return hash;
}

+ (NSString *)getmd5Str:(NSString *)str
{    
    //传入参数,转化成char
    const char *cStr = [str UTF8String];
    //开辟一个16字节的空间
    unsigned char result[16];
    /*
     extern unsigned char * CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封装好的加密方法
     把str字符串转换成了32位的16进制数列（这个过程不可逆转） 存储到了md这个空间中
     */
    CC_MD5(cStr, (unsigned)strlen(cStr), result);
    return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
             result[0], result[1], result[2], result[3],
             result[4], result[5], result[6], result[7],
             result[8], result[9], result[10], result[11],
             result[12], result[13], result[14], result[15]
             ];
}


+ (NSString *)getmd5Str32:(NSString *)str
{
    //传入参数,转化成char
    const char *cStr = [str UTF8String];
    //开辟一个16字节的空间
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    /*
     extern unsigned char * CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封装好的加密方法
     把str字符串转换成了32位的16进制数列（这个过程不可逆转） 存储到了md这个空间中
     */
    CC_MD5(cStr, (unsigned)strlen(cStr), result);
    NSMutableString *saveResult = [NSMutableString string];
    
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [saveResult appendFormat:@"%02x", result[i]];
    }
    return saveResult;
}

@end
