iOS 3DS+Base64加密

作者: 离离离离 | 来源:发表于2016-10-25 17:27 被阅读147次

    最近在做项目的时候,被一个问题3ds以byte数组作为密钥加密的问题困难了很久,百度了很久才找到解决方法,特来分享给大家解决。

    一般我们做3ds加密的时候,加密的key直接使用字符串,但是要是加密的key是字节数组,要怎么办?一种是跟服务端协调,统一改成字符串加密,另一种就是自己想办法利用字节数组进行加密。

    在找到方法前,我曾试了很多种办法,直接把key改成字节数组进行加密,可是发现无论怎么做都跟服务器加密后的字符串不一致也无法解析,原因就是,网上的方法都是以字符串作为密钥,先将字符串进行utf8编码,再转换成data,这样和直接用byte数组进行加密是有区别的,转换后的data字节数增加了一倍,这时候怎么办呢?

    一、以byte数组作为密钥的3des加密

    使用之前要导入类

    #import "NSString+Tencrypt.h"
    #import <CommonCrypto/CommonCryptor.h>  
    #import <CommonCrypto/CommonDigest.h>
    #import "GTMBase64.h" 
    
    @implementation NSString (Tencrypt)
    

    1.首先,对密钥字符串进行处理,把16进制字符串转换为byte数组(nadata)

    #pragma mark -----字节数组密匙3ds加密
    - (NSData *) stringToHexData
    {
        int len = (int)[self length] / 2;    // Target length
        unsigned char *buf = malloc(len);
        unsigned char *whole_byte = buf;
        char byte_chars[3] = {'\0','\0','\0'};
        
        int i;
        for (i=0; i < [self length] / 2; i++) {
            byte_chars[0] = [self characterAtIndex:i*2];
            byte_chars[1] = [self characterAtIndex:i*2+1];
            *whole_byte = strtol(byte_chars, NULL, 16);
            whole_byte++;
        }
        
        NSData *data = [NSData dataWithBytes:buf length:len];
        free( buf );
        return data;
    }
    

    2.这样就得到了data的密钥,然后进行3des加密

    +(NSString*)TripleDES:(NSString*)plainText  andCCOperation:(CCOperation )encryptOrDecrypt  anddata:(NSData*)data
    {
        
        const void *vplainText;
        size_t plainTextBufferSize;
        
        if (encryptOrDecrypt == kCCDecrypt)//解密
        {
            NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];
            plainTextBufferSize = [EncryptData length];
            vplainText = [EncryptData bytes];
        }
        else //加密
        {
            NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
            plainTextBufferSize = [data length];
            vplainText = (const void *)[data bytes];
        }
        
        CCCryptorStatus ccStatus;
        uint8_t *bufferPtr = NULL;
        size_t bufferPtrSize = 0;
        size_t movedBytes = 0;
        
        bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
        bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
        memset((void *)bufferPtr, 0x0, bufferPtrSize);
        // memset((void *) iv, 0x0, (size_t) sizeof(iv));
        
        //const void *vkey = (const void *)[DESKEY UTF8String];
        const void *vkey = (const void *)[data bytes];
        
        // NSString *initVec = @"init Vec";
        //const void *vinitVec = (const void *) [initVec UTF8String];
        //  Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
        ccStatus = CCCrypt(encryptOrDecrypt,
                           kCCAlgorithm3DES,
                           kCCOptionPKCS7Padding | kCCOptionECBMode,
                           vkey,
                           kCCKeySize3DES,
                           nil,
                           vplainText,
                           plainTextBufferSize,
                           (void *)bufferPtr,
                           bufferPtrSize,
                           &movedBytes);
        NSString *result;
        
        if (encryptOrDecrypt == kCCDecrypt)
        {
            result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
                                                                   length:(NSUInteger)movedBytes]
                                           encoding:NSUTF8StringEncoding];
        }
        else
        {
            NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
            result = [GTMBase64 stringByEncodingData:myData];
        }
        return result;
    }
    

    3.调用方法

     // 统一用3des加密
    NSString* encryptedStr = [NSString TripleDES:jsonString andCCOperation:kCCEncrypt anddata:[KEY stringToHexData]];
    
    //key是byte数组转为字符串后再使用
    

    二、以字符串作为密钥的3des加密

    +(NSString*)Tencrypt:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt key:(NSString*)key
    {
        const void *vplainText;
        size_t plainTextBufferSize;
        
        if (encryptOrDecrypt == kCCDecrypt)//解密
        {
            NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];
            plainTextBufferSize = [EncryptData length];
            vplainText = [EncryptData bytes];
        }
        else //加密
        {
            NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
            plainTextBufferSize = [data length];
            vplainText = (const void *)[data bytes];
        }
        
        CCCryptorStatus ccStatus;
        uint8_t *bufferPtr = NULL;
        size_t bufferPtrSize = 0;
        size_t movedBytes = 0;
        
        bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
        bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
        memset((void *)bufferPtr, 0x0, bufferPtrSize);
        // memset((void *) iv, 0x0, (size_t) sizeof(iv));
        
        const void *vkey = (const void *)[key UTF8String];
        // NSString *initVec = @"init Vec";
        //const void *vinitVec = (const void *) [initVec UTF8String];
        //  Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
        ccStatus = CCCrypt(encryptOrDecrypt,
                           kCCAlgorithm3DES,
                           kCCOptionPKCS7Padding | kCCOptionECBMode,
                           vkey,
                           kCCKeySize3DES,
                           nil,
                           vplainText,
                           plainTextBufferSize,
                           (void *)bufferPtr,
                           bufferPtrSize,
                           &movedBytes);
        //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
        /*else if (ccStatus == kCC ParamError) return @"PARAM ERROR";
         else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
         else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
         else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
         else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
         else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED"; */
        
        NSString *result;
        
        if (encryptOrDecrypt == kCCDecrypt)
        {
            result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
                                                    length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding];
        }
        else
        {
            NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
            result = [GTMBase64 stringByEncodingData:myData];
        }
        
        return result;
    }
    
    + (NSString *)encodeToPercentEscapeString: (NSString *) input
    {
        // Encode all the reserved characters, per RFC 3986
        // (<http://www.ietf.org/rfc/rfc3986.txt>)
        NSString *outputStr = (NSString *)
        CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                  (CFStringRef)input,
                                                                  NULL,
                                                                  (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                                  kCFStringEncodingUTF8));
        return outputStr;
    }
    

    以上就是3ds+base64以字节数组或字符串加密的方法!

    感谢:

    此篇文章带来的解决方法

    相关文章

      网友评论

        本文标题:iOS 3DS+Base64加密

        本文链接:https://www.haomeiwen.com/subject/uhgruttx.html