//
//  AESEncrypt.m
//  MQTTLearn
//
//  Created by RD on 2020/12/16.
//

#import "AESEncrypt.h"
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"
#import "NSString+convert.h"

#define g128key            @"1234561234567890" //秘钥
#define g256key            @"12345612345678901234561234567890" //秘钥
#define gIv                @"22222222222222222222222222222222" //向量

@implementation AESEncrypt

+(NSString *)cbcEncrypt:(NSString *)content key:(NSString *)key
{
    NSLog(@"加密数据：%@", content);
    if (content != nil && content.length != 0) {
        NSString *result = aesEncryptString(content, key, gIv);
        NSLog(@"cbc加密：%@", result);
        return result;
    }
    return nil;
}
 
+(NSString *)ecbEncrypt:(NSString *)content key:(NSString *)key
{
    NSLog(@"加密数据：%@", content);
    if (content != nil && content.length != 0) {
        NSString *result = aesEncryptString(content, key, nil);
        NSLog(@"ecb加密：%@", result);
        return result;
    }
    return nil;
}

+(NSString *)cbcDecrypt:(NSString *)content key:(NSString *)key
{
    NSLog(@"解密数据：%@", content);
    if (content != nil && content.length != 0) {
        NSString *result = aesDecryptString(content, key, gIv);
        NSLog(@"cbc解密：%@", result);
        return result;
    }
    return nil;
}

+(NSString *)ecbDecrypt:(NSString *)content key:(NSString *)key
{
    NSLog(@"解密数据：%@", content);
    if (content != nil && content.length != 0) {
        NSString *result = aesDecryptString(content, key, nil);
        NSLog(@"ecb解密：%@", result);
        return result;
    }
    return nil;
}


NSData * ecbCipherOperation(NSData *contentData, NSData *keyData, CCOperation operation) {
    NSUInteger dataLength = contentData.length;
    void const *contentBytes = contentData.bytes;
    void const *keyBytes = keyData.bytes;
    
    size_t operationSize = dataLength + kCCBlockSizeAES128;
    void *operationBytes = malloc(operationSize);
    if (operationBytes == NULL) {
        return nil;
    }
    size_t actualOutSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          0x0000 | kCCOptionECBMode,  // noPadding
                                          keyBytes,
                                          kCCKeySizeAES128,  // 秘钥长度选择AES128
                                          NULL,//initVectorBytes,
                                          contentBytes,
                                          dataLength,
                                          operationBytes,
                                          operationSize,
                                          &actualOutSize);
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];
    }
    
    free(operationBytes);
    operationBytes = NULL;
    return nil;
}

NSData * cbcCipherOperation(NSData *contentData, NSData *keyData, NSData *ivData, CCOperation operation) {
    NSUInteger dataLength = contentData.length;
    void const *initVectorBytes = ivData.bytes;
    void const *contentBytes = contentData.bytes;
    void const *keyBytes = keyData.bytes;
    
    size_t operationSize = dataLength + kCCBlockSizeAES128;
    void *operationBytes = malloc(operationSize);
    if (operationBytes == NULL) {
        return nil;
    }
    size_t actualOutSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          0x0000,  // noPadding
                                          keyBytes,
                                          kCCKeySizeAES128,  // 秘钥长度选择AES128
                                          initVectorBytes,
                                          contentBytes,
                                          dataLength,
                                          operationBytes,
                                          operationSize,
                                          &actualOutSize);
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];
    }
    
    free(operationBytes);
    operationBytes = NULL;
    return nil;
}

// 加密
NSString * aesEncryptString(NSString *content, NSString *key, NSString *iv) {
    
    //  把内容转成 data
    NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
    
//    NSData *contentData = [AESEncrypt convertHexStrToData:content];
//    NSData *keyData = [AESEncrypt convertHexStrToData:key];//[key dataUsingEncoding:NSUTF8StringEncoding];
//    NSData *ivData = [AESEncrypt convertHexStrToData:iv];
    
    NSData *encrptedData = aesEncryptData(contentData, keyData, ivData);
    
    // 将加密好的数据转成16进制的字符
    NSString *result;
    result = [AESEncrypt convertDataToHexStr:encrptedData];
    
    return result;
}

// 解密
NSString * aesDecryptString(NSString *content, NSString *key, NSString *iv) {
    
    //  把内容转成 data
    
//    NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
    
    NSData *contentData = [AESEncrypt convertHexStrToData:content];

    
    NSData *decryptedData = aesDecryptData(contentData, keyData, ivData);
    
    NSString *result;
    result = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
        
    return result;
}

NSData * aesEncryptData(NSData *contentData, NSData *keyData, NSData *ivData) {
    if (ivData) {
        return cbcCipherOperation(contentData, keyData, ivData, kCCEncrypt);
    }else{
        return ecbCipherOperation(contentData, keyData, kCCEncrypt);
    }
}

NSData * aesDecryptData(NSData *contentData, NSData *keyData, NSData *ivData) {
    if (ivData) {
        return cbcCipherOperation(contentData, keyData, ivData, kCCDecrypt);
    }else{
        return ecbCipherOperation(contentData, keyData, kCCDecrypt);
    }
}

// data转十六进制字符串
+ (NSString *)convertDataToHexStr:(NSData *)data {
    if (!data || [data length] == 0) {
        return @"";
    }
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
    
    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        unsigned char *dataBytes = (unsigned char*)bytes;
        for (NSInteger i = 0; i < byteRange.length; i++) {
            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            if ([hexStr length] == 2) {
                [string appendString:hexStr];
            } else {
                [string appendFormat:@"0%@", hexStr];
            }
        }
    }];
    
    return string;
}

// 十六进制字符串转data
+ (NSData *)convertHexStrToData:(NSString *)str {
    if (!str || [str length] == 0) {
        return nil;
    }
    
    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
    NSRange range;
    if ([str length] % 2 == 0) {
        range = NSMakeRange(0, 2);
    } else {
        range = NSMakeRange(0, 1);
    }
    for (NSInteger i = range.location; i < [str length]; i += 2) {
        unsigned int anInt;
        NSString *hexCharStr = [str substringWithRange:range];
        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
        
        [scanner scanHexInt:&anInt];
        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
        [hexData appendData:entity];
        
        range.location += range.length;
        range.length = 2;
    }
    
    return hexData;
}
@end
