//
//  DES3Util.m
//  DES
//
//  Created by Toni on 12-12-27.
//  Copyright (c) 2012年 sinofreely. All rights reserved.
//

#import "DES3Util.h"

@implementation DES3Util


const Byte iv[] = {1,2,3,4,5,6,7,8};

// Des加密
+ (NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key
{
    // 密文
    NSString *ciphertext = nil;
    if (!plainText || ![plainText isKindOfClass:[NSString class]] || !plainText.length) {
        return ciphertext;
    }
    // 进行编码（避免特殊字符导致加密/解密失败）
    plainText = [self UrlValueEncode:plainText];
    // 加密后的数据
    uint8_t *dataOut = NULL;
    size_t dataOutAvailable = 0;
    size_t dataOutMove = 0;
    
    dataOutAvailable = (plainText.length + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    dataOut = malloc(dataOutAvailable * sizeof(uint8_t));
    // 将已开辟内存空间buffer的首1个字节的值设为0
    memset((void *)dataOut, 0x0, dataOutAvailable);
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, // 操作名称：加密
                                          kCCAlgorithmDES, // 加密算法
                                          kCCOptionPKCS7Padding | kCCOptionECBMode, // 填充模式，ECB模式
                                          key.UTF8String, // 加密秘钥
                                          kCCKeySizeDES, // 秘钥大小，和加密算法一致
                                          NULL, // 初始向量：ECB模式为空
                                          plainText.UTF8String, // 加密的明文
                                          (size_t)plainText.length, // 加密明文的大小
                                          dataOut, // 密文的接受者
                                          dataOutAvailable, // 预计密文的大小
                                          &dataOutMove); // 加密后密文的实际大小
    if (cryptStatus == kCCSuccess) {
        NSData *data = [NSData dataWithBytes:dataOut length:(NSUInteger)dataOutMove];
        ciphertext = [GTMBase64 stringByEncodingData:data];
    }
    return ciphertext;
}



// Des解密
+ (NSString *)decryptUseDES:(NSString *)cipherText key:(NSString *)key
{
    if (!cipherText || ![cipherText isKindOfClass:[NSString class]] || !cipherText.length) {
        return nil;
    }
    // 将16进制转为data
    NSData *cipherData = [GTMBase64 decodeString:cipherText];
    // 解密后的数据
    uint8_t *dataOut = NULL;
    size_t dataOutAvailable = 0;
    size_t dataOutMove = 0;
    
    dataOutAvailable = (cipherData.length + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    dataOut = malloc(dataOutAvailable * sizeof(uint8_t));
    // 将已开辟内存空间buffer的首1个字节的值设为0
    memset((void *)dataOut, 0x0, dataOutAvailable);
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          key.UTF8String,
                                          kCCKeySizeDES,
                                          NULL,
                                          cipherData.bytes,
                                          (size_t)cipherData.length,
                                          dataOut,
                                          dataOutAvailable,
                                          &dataOutMove);
    NSString* plainText = nil;
    if (cryptStatus == kCCSuccess) {
        NSData *data = [NSData dataWithBytes:dataOut length:(NSUInteger)dataOutMove];
        // 进行解码（避免特殊字符导致加密/解密失败）
        plainText = [self decodeFromPercentEscapeString:[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]];
    }
    return plainText;
}

// url编码
+ (NSString *)UrlValueEncode:(NSString *)str{
    if (!str || ![str isKindOfClass:[NSString class]] || !str.length) {
        return nil;
    }
    NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                             (CFStringRef)str,
                                                                                             NULL,
                                                                                             CFSTR("!*'();:@&=+$,/?%#[]"),
                                                                                             kCFStringEncodingUTF8));
    
    return result;
}
// url 解码
+ (NSString *)decodeFromPercentEscapeString: (NSString *) input
{
    if (!input || ![input isKindOfClass:[NSString class]] || !input.length) {
        return nil;
    }
    NSMutableString *outputStr = [NSMutableString stringWithString:input];
    [outputStr replaceOccurrencesOfString:@"+"
                               withString:@" "
                                  options:NSLiteralSearch
                                    range:NSMakeRange(0, [outputStr length])];
    
    return [outputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
@end
