EXC_BAD_ACCESS CCCrypt 上的代码 2
EXC_BAD_ACCESS Code 2 on CCCrypt
我正在尝试使用 DES
加密来加密密码(不要问为什么使用 DES,我知道它不太安全)。我是在 iOS 中第一次这样做,因此不得不依赖另一个 post 来了解如何做。
当我运行加密的时候returnsnull,和解密一个已经加密的字符串一样(我是用在线工具加密的)。当我设置断点以查看发生了什么时,它停在 CCCrypt
处提到 EXC_BAD_ACCESS (Code 2)
。
我尝试使用不同的 CCOptions,但它 returns 总是一样。
任何提示出了什么问题?是否需要 iv 字符串?
我使用了以下 NSString 类别来加密或解密字符串 -
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey,
kCCKeySizeDES,
NULL,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
- (NSString *) decryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey, //"123456789012345678901234", //key
kCCKeySizeDES,
NULL,// vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
@end
更新:
我又检查了几个地方并稍微更改了代码,加密有效但没有用正确的值解密。
例如当我使用YourName
作为字符串和12345
作为密钥时,我得到Fu2sK61e7l5rkXRhAKjPWA==
作为加密代码,但是解密returns+54qWCYTB5LkdARDZjAow==
而不是 YourName
.
更新代码:
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [self dataUsingEncoding:NSUTF8StringEncoding];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES encrypt...");
return nil;
}
}
- (NSString *) decryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [[NSData alloc] initWithBase64EncodedString:self options:0];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES decrypt...");
return nil;
}
}
@end
似乎普遍混淆了算法,DES 或 3DES,混合使用但密钥是 3DES(24 字节)。密钥需要更改为 8 字节。块大小常量也应更改为 kCCBlockSizeDES
但这不会导致错误,因为它是相同的值。
对于方法:
- (NSString *) decryptDES: (NSString *) key
访问错误错误是因为没有为movedBytes
分配存储空间,只是一个指针。将声明更改为:
size_t movedBytes;
将 CCCrypt
中对 movedBytes
的引用更改为 &movedBytes
。
加密测试输出:
string: "Your Name"
key: "12345678"
movedBytes: 16
myData: 136142f6 6cd98e01 af1eef46 28d36499
result: E2FC9mzZjgGvHu9GKNNkmQ==
根据要求从评论中注释:
ECB 模式不使用 iv。
对于DES,密钥需要恰好是8字节,如果太短,结果将是不确定的。在更新后的代码中,密钥为 5 个字节,但长度为 8 个字节 (kCCKeySizeDES
),因此缺少的三个密钥字节将是 keyData
.
之后的任何字节
更新的答案没有指定ECB模式,默认是CBC模式。添加 kCCOptionECBMode
.
在解密时不要使用Base64编码,将数据转换成NSString
:
NSString * resultStr = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding];
如果使用使用 php mcrypt 函数的在线加密,数据的最后一个块将不正确,因为 mcrypt 不支持 PKCS#7 填充,它使用非标准和不安全的空填充。
我正在尝试使用 DES
加密来加密密码(不要问为什么使用 DES,我知道它不太安全)。我是在 iOS 中第一次这样做,因此不得不依赖另一个 post 来了解如何做。
当我运行加密的时候returnsnull,和解密一个已经加密的字符串一样(我是用在线工具加密的)。当我设置断点以查看发生了什么时,它停在 CCCrypt
处提到 EXC_BAD_ACCESS (Code 2)
。
我尝试使用不同的 CCOptions,但它 returns 总是一样。 任何提示出了什么问题?是否需要 iv 字符串?
我使用了以下 NSString 类别来加密或解密字符串 -
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey,
kCCKeySizeDES,
NULL,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
- (NSString *) decryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey, //"123456789012345678901234", //key
kCCKeySizeDES,
NULL,// vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
@end
更新:
我又检查了几个地方并稍微更改了代码,加密有效但没有用正确的值解密。
例如当我使用YourName
作为字符串和12345
作为密钥时,我得到Fu2sK61e7l5rkXRhAKjPWA==
作为加密代码,但是解密returns+54qWCYTB5LkdARDZjAow==
而不是 YourName
.
更新代码:
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [self dataUsingEncoding:NSUTF8StringEncoding];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES encrypt...");
return nil;
}
}
- (NSString *) decryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [[NSData alloc] initWithBase64EncodedString:self options:0];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES decrypt...");
return nil;
}
}
@end
似乎普遍混淆了算法,DES 或 3DES,混合使用但密钥是 3DES(24 字节)。密钥需要更改为 8 字节。块大小常量也应更改为 kCCBlockSizeDES
但这不会导致错误,因为它是相同的值。
对于方法:
- (NSString *) decryptDES: (NSString *) key
访问错误错误是因为没有为movedBytes
分配存储空间,只是一个指针。将声明更改为:
size_t movedBytes;
将 CCCrypt
中对 movedBytes
的引用更改为 &movedBytes
。
加密测试输出:
string: "Your Name"
key: "12345678"movedBytes: 16
myData: 136142f6 6cd98e01 af1eef46 28d36499
result: E2FC9mzZjgGvHu9GKNNkmQ==
根据要求从评论中注释:
ECB 模式不使用 iv。
对于DES,密钥需要恰好是8字节,如果太短,结果将是不确定的。在更新后的代码中,密钥为 5 个字节,但长度为 8 个字节 (kCCKeySizeDES
),因此缺少的三个密钥字节将是 keyData
.
更新的答案没有指定ECB模式,默认是CBC模式。添加 kCCOptionECBMode
.
在解密时不要使用Base64编码,将数据转换成NSString
:
NSString * resultStr = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding];
如果使用使用 php mcrypt 函数的在线加密,数据的最后一个块将不正确,因为 mcrypt 不支持 PKCS#7 填充,它使用非标准和不安全的空填充。