最近在做项目的时候,被一个问题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以字节数组或字符串加密的方法!
网友评论