【问题标题】:AES string encryption in Objective-CObjective-C 中的 AES 字符串加密
【发布时间】:2011-11-09 12:45:45
【问题描述】:

我的 Objective-C 应用程序需要文本/字符串加密(特别是 )。

我知道 AES 是可供消费者使用的最安全的加密方法。我也了解如何将字符串转换为数据并返回......(只是一个初学者)。

许多关于 AES 加密的网页和 Q/As 都不清楚,并且没有一个说明如何使用给定的代码。例如,一个网页可能会说:“这是代码……这是它的作用……”但没有解释如何使用它。

我通过大量研究找到了这段代码:

#import "<CommonCrypto/CommonCryptor.h>"
@implementation NSMutableData(AES)

对于加密:

- (NSMutableData*) EncryptAES:(NSString *)key {
    char keyPtr[kCCKeySizeAES256+1];
    bzero( keyPtr, sizeof(keyPtr) );

    [key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF16StringEncoding];
    size_t numBytesEncrypted = 0;

    NSUInteger dataLength = [self length];

    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    NSMutableData *output = [[NSData alloc] init];

    CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, NULL, [self mutableBytes], [self length], buffer, bufferSize, &numBytesEncrypted);

    output = [NSMutableData dataWithBytesNoCopy:buffer length:numBytesEncrypted];

    if(result == kCCSuccess) {
        return output;
    }
        return NULL;
    }

用于解密:

- (NSMutableData*)DecryptAES: (NSString*)key andForData:(NSMutableData*)objEncryptedData {

    char  keyPtr[kCCKeySizeAES256+1];
    bzero( keyPtr, sizeof(keyPtr) );

    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF16StringEncoding];

    size_t numBytesEncrypted = 0;

    NSUInteger dataLength = [self length];

    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer_decrypt = malloc(bufferSize);    
    NSMutableData *output_decrypt = [[NSData alloc] init];
    CCCryptorStatus result = CCCrypt(kCCDecrypt , kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, NULL, [self mutableBytes], [self length], buffer_decrypt, bufferSize, &numBytesEncrypted);

    output_decrypt = [NSMutableData dataWithBytesNoCopy:buffer_decrypt length:numBytesEncrypted];

    if(result == kCCSuccess) {
        return output_decrypt;
    } 
        return NULL;
    }
}

这是我自己做的代码,想和上面的代码对应起来:

- (void)Encrypt {
    //Convert NSString to NSData so that it can be used to encrypt the Input
    NSString *Input  = [Inputbox text];
    NSData *InputData = [Input dataUsingEncoding:NSUTF8StringEncoding];
    //What to do here
}

我如何使用这段代码,这些方法?它在我的实施文件中的什么位置?

【问题讨论】:

  • 嗨@RazorSharp - 已将您的问题迁移到此处(堆栈溢出)。关于使任何类型的代码工作的问题,加密或其他方式最好在这里回答,因为这里有大量可以提供帮助的人,但是如果您想询问所使用的任何算法、填充等的详细信息,那么加密是它的地方!
  • 要牢记的一个重要设计考虑因素是加密算法只是解决方案的一部分。密钥管理非常重要,很容易成为系统中的最薄弱环节。有一些关于这类事情的好书(例如 Schneier),还有很多关于设计的文章。现在的一些研究可能会在以后节省大量工作。
  • 使用 github.com/Gurpartap/AESCrypt-ObjC 进行快速 AES-256-CBC 密码和基于 Base64 编码的加密/解密。您可以在设备外处理(服务器等)上使用相同的密码和编码。
  • 结果 != kCCSuccess 时可能缺少 free(buffer) / free(buffer_decrypt)?

标签: nsstring objective-c encryption cryptography aes


【解决方案1】:

靠近顶部的这条线表示您正在向 NSMutableData 添加 AES 功能:

@implementation NSMutableData(AES)

在 Objective-C 中,这称为类别;类别让您扩展现有的类。

此代码通常会放在名为 NSMutableData-AES.m 的文件中。还要创建一个头文件 NSMutableData-AES.h。它应该包含:

@interface NSMutableData(AES)
- (NSMutableData*) EncryptAES: (NSString *) key;
@end

在主文件中包含 (#import) 该标题。在代码中添加对加密函数的调用:

NSData *InputData = [Input dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [InputData EncryptAES:@"myencryptionkey"];

同样用于解密。

【讨论】:

  • 你是个天才!这非常有效。不过我有几个问题。首先,在我的 NSMutableData-AES.h 文件中,我应该导入基础吗? #import 我的 NSMutableData-AES.m 中有很多“未声明的标识符”错误,这是因为我必须将 (@) 属性和 (@) 与 kCCSuccess 或 CCCryptorStatus 之类的东西一起使用吗?感谢您的帮助!
  • 您还需要项目中的 CCCrypt 代码以及相应的标头。这里有一个类似的实现,所有需要压缩的文件都很方便:iphonedevelopment.blogspot.com/2009/02/…
  • @GrahamPerks 很抱歉加入这个线程并且有点远,但是我使用 CCryptor 进行了一些加密,需要使用节点解密。遇到可怕的问题,请您看看stackoverflow.com/questions/68136902/…好吗?
【解决方案2】:

因为到目前为止这似乎已被忽略:

CCCryptorStatus result = CCCrypt( kCCDecrypt , kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                 keyPtr, kCCKeySizeAES256,
                                 **NULL**,
                                 [self mutableBytes], [self length],
                                 buffer_decrypt, bufferSize,
                                 &numBytesEncrypted );

来自头文件 CommonCrypto/CommonCryptor.h:

@param iv 初始化向量,可选。使用者 密码块链接 (CBC) 时的块密码 模式已启用。如果存在,必须相同 长度作为所选算法的块大小。 如果选择了 CBC 模式(由于没有 选项标志中的 kCCOptionECBMode 位)并且没有 IV 存在,将使用 NULL(全零)IV。 如果使用 ECB 模式或 如果选择了流密码算法。

粗体的 NULL 对应于 IV。可悲的是,设计 API 的人将其设为可选。这使得这个CBC模式本质上等同于ECB,不推荐for a variety of reasons。

【讨论】:

【解决方案3】:

我通过以下代码使用 AES 获得了成功:

头文件

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCryptor.h>

NS_ASSUME_NONNULL_BEGIN

@interface SecurityUtils : NSObject

+ (NSString *)encrypt:(NSString *)plainText error:(NSError **)error;
+ (NSString *)decrypt:(NSString *)plainText error:(NSError **)error;

@end

NS_ASSUME_NONNULL_END

实施文件

NSString *const IV = @"AEE0515D0B08A4E4";
NSString *const KEY =  @"9336565521E5F082BB5929E8E033BC69";


#import "SecurityUtils.h"


@implementation SecurityUtils


+ (NSString *)encrypt:(NSString *)plainText error:(NSError **)error {
    NSMutableData *result =  [SecurityUtils doAES:[plainText dataUsingEncoding:NSUTF8StringEncoding] context: kCCEncrypt error:error];
    return [result base64EncodedStringWithOptions:0];
}


+ (NSString *)decrypt:(NSString *)encryptedBase64String error:(NSError **)error {
    NSData *dataToDecrypt = [[NSData alloc] initWithBase64EncodedString:encryptedBase64String options:0];
    NSMutableData *result = [SecurityUtils doAES:dataToDecrypt context: kCCDecrypt error:error];
    return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];

}

+ (NSMutableData *)doAES:(NSData *)dataIn context:(CCOperation)kCCEncrypt_or_kCCDecrypt error:(NSError **)error {
        CCCryptorStatus ccStatus   = kCCSuccess;
        size_t          cryptBytes = 0;
        NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeBlowfish];
        NSData *key =[KEY dataUsingEncoding:NSUTF8StringEncoding];
        NSData *iv = [IV dataUsingEncoding:NSUTF8StringEncoding];

        ccStatus = CCCrypt( kCCEncrypt_or_kCCDecrypt,
                           kCCAlgorithmAES,
                           kCCOptionPKCS7Padding,
                           key.bytes,
                           key.length,
                           (iv)?nil:iv.bytes,
                           dataIn.bytes,
                           dataIn.length,
                           dataOut.mutableBytes,
                           dataOut.length,
                           &cryptBytes);

        if (ccStatus == kCCSuccess) {
            dataOut.length = cryptBytes;
        }
        else {
            if (error) {
                *error = [NSError errorWithDomain:@"kEncryptionError"
                                             code:ccStatus
                                         userInfo:nil];
            }
            dataOut = nil;
        }

        return dataOut;
}


@end

IOS 测试

NSError *error;
NSString *encrypted = [SecurityUtils encrypt:@"My Secret Text" error:&error];
NSLog(@"encrypted: %@",encrypted);
NSLog(@"decrypted: %@",[SecurityUtils decrypt:encrypted error:&error]);

最后,测试输出:

IOS 输出

2019-05-16 21:38:02.947043-0300 MyApp[63392:1590665] encrypted: EJ41am5W1k6fA7ygFjTSEw==
2019-05-16 21:38:02.947270-0300 MyApp[63392:1590665] decrypted: My Secret Text

我在 github 上的 repo 有这个例子:https://github.com/juliancorrea/aes-crypto-android-and-ios

【讨论】:

    【解决方案4】:

    在我上面的例子中,给定的代码不起作用。它显示有关“kCCBufferTooSmall errorCode = -4301”的错误。 我得改一下,如果上面的代码不起作用,请尝试一下

    + (NSMutableData *)doAES:(NSData *)dataIn context:(CCOperation)kCCEncrypt_or_kCCDecrypt error:(NSError **)error {
        CCCryptorStatus ccStatus   = kCCSuccess;
        size_t          cryptBytes = 0;
        NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCKeySizeAES256];
        NSData *key =[encryptionNewKey dataUsingEncoding:NSUTF8StringEncoding];
        NSData *iv = [encryptionIV dataUsingEncoding:NSUTF8StringEncoding];
        
        ccStatus = CCCrypt( kCCEncrypt_or_kCCDecrypt,
                           kCCAlgorithmAES,
                           kCCOptionPKCS7Padding,
                           key.bytes,
                           kCCKeySizeAES256,
                           iv.bytes,
                           dataIn.bytes,
                           dataIn.length,
                           dataOut.mutableBytes,
                           dataOut.length,
                           &cryptBytes);
        
        if (ccStatus == kCCSuccess) {
            dataOut.length = cryptBytes;
        }
        else {
            if (error) {
                *error = [NSError errorWithDomain:@"kEncryptionError"
                                             code:ccStatus
                                         userInfo:nil];
            }
            dataOut = nil;
        }
        
        return dataOut;
    } 
    

    希望可以帮助别人

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-04
      • 2016-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-24
      相关资源
      最近更新 更多