CCCrypt

时间:2015-05-01 09:56:17

标签: ios encryption ios7.1 des

我正在尝试使用DES加密来加密密码(不要问为什么DES,我知道它不太安全)。我是第一次在iOS中这样做,因此不得不依赖另一篇关于如何做的帖子。

当我运行加密时,它返回null,与解密已经加密的字符串相同(我使用在线工具进行加密)。当我设置一个断点来查看发生了什么时,它会在CCCrypt提到EXC_BAD_ACCESS (Code 2)时停止。

我尝试使用不同的CCOptions,但它总是返回相同的东西。 什么提示出了什么问题?是否需要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==作为加密代码,但解密返回+54qWCYTB5LkdARDZjAow==而不是{{ 1}}。

更新代码:

YourName

1 个答案:

答案 0 :(得分:1)

似乎对算法,DES或3DES存在一般混淆,正在使用混合但关键是3DES(24字节)。密钥需要更改为8个字节。块大小常量也应该更改为kCCBlockSizeDES,但这不会导致错误,因为它是相同的值。

方法:

- (NSString *) decryptDES: (NSString *) key

导致错误访问错误,因为没有为movedBytes分配存储,只是指针。将声明更改为:

size_t movedBytes;

movedBytesCCCrypt的引用更改为&movedBytes

测试加密输出:

  

字符串:"您的姓名"
  关键:" 12345678"

     

movingBytes:16
  myData:136142f6 6cd98e01 af1eef46 28d36499
  结果: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填充,它使用非标准和不安全的空填充。