【问题标题】:Generate Initialization Vector In objective c在目标 c 中生成初始化向量
【发布时间】:2018-02-23 14:19:17
【问题描述】:

java代码是

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");

byte[] ivBytes = new byte[c.getBlockSize()];
String IV = CryptoUtils.hexEncode(ivBytes);

它给出随机的 16 字节响应,如

563ffcecaa43753bd09613095ad24a12.

如何将对应的代码写入objective c?

我有一些客观的 c 代码 -

 - (NSData *)createCipher:(NSString*)data WithKey:(NSString*)key {
 NSData* result = nil;

 // setup key
 unsigned char cKey[kCCKeySizeAES256]; // room for terminator (unused)
 bzero(cKey, sizeof(cKey)); // fill with zeroes (for padding)
 [key getBytes:cKey length:kCCKeySizeAES256];

 // setup iv
 char cIv[kCCBlockSizeAES128];
 bzero(cIv, kCCBlockSizeAES128);
 if (iv) {
 [iv getBytes:cIv length:kCCBlockSizeAES128];
 }

 // setup output buffer
 size_t bufferSize = [data length] + kCCBlockSizeAES128;
 void *buffer = malloc(bufferSize);

 // do encrypt
 size_t encryptedSize = 0;
 CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, //CCOperation op
 kCCAlgorithmAES128, //CCAlgorithm alg
 kCCOptionPKCS7Padding, //CCOptions
 cKey, //const void *key
 kCCKeySizeAES256, //size_t keyLength
 cIv, // optional initialization vector
 [data bytes], // optional per op and alg
 [data length],
 buffer, // data RETURNED here
 bufferSize,
 &encryptedSize);


 if (cryptStatus == kCCSuccess) {
 result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
 } else {
 free(buffer);
 NSLog(@"[ERROR] failed to encrypt|CCCryptoStatus: %d", cryptStatus);
 }

 return result;
 }

但是,这段代码是用来加密数据的,现在如何生成IV?

【问题讨论】:

  • 563ffcecaa43753bd09613095ad24a12 是以十六进制表示的 16 字节,而不是问题中所述的“32 位响应”。
  • 天啊,“万事达卡的 iOS 开发人员”,一定有人了解那里的加密以及如何处理 IV!只是想知道万事达卡如何让开发人员在没有密码学基础培训的情况下编写加密代码。

标签: ios objective-c encryption


【解决方案1】:

只需为 IV 生成随机字节:

int             ivLength   = kCCBlockSizeAES128;
NSMutableData  *ivData = [NSMutableData dataWithLength:kCCBlockSizeAES128];
SecRandomCopyBytes(kSecRandomDefault, ivLength, ivData.mutableBytes);

这将产生适合CCCrypt的数据,只需使用ivData.bytes

ivData的使用示例:

ccStatus = CCCrypt(
                   ...
                   ivData.bytes,
                   ...
                  );

在加密时生成随机 IV 并将其传递给加密数据的前缀以进行解密的完整示例:

+ (NSData *)aesCBCEncrypt:(NSData *)data
                         key:(NSData *)key
                       error:(NSError **)error
{
    if (key.length != 16 && key.length != 24 && key.length != 32) {
        *error = [NSError errorWithDomain:@"keyLengthError" code:-1 userInfo:nil];
        return nil;
    }

    CCCryptorStatus ccStatus   = kCCSuccess;
    int             ivLength   = kCCBlockSizeAES128;
    size_t          cryptBytes = 0;
    NSMutableData  *dataOut     = [NSMutableData dataWithLength:ivLength + data.length + kCCBlockSizeAES128];

    int status = SecRandomCopyBytes(kSecRandomDefault, ivLength, dataOut.mutableBytes);
    if (status != 0) {
        *error = [NSError errorWithDomain:@"ivError" code:status userInfo:nil];
        return nil;
    }
    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithmAES,
                       kCCOptionPKCS7Padding,
                       key.bytes, key.length,
                       dataOut.bytes,
                       data.bytes, data.length,
                       dataOut.mutableBytes + ivLength, dataOut.length,
                       &cryptBytes);

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

    return dataOut;
}

+ (NSData *)aesCBCDecrypt:(NSData *)data
                         key:(NSData *)key
                       error:(NSError **)error
{
    if (key.length != 16 && key.length != 24 && key.length != 32) {
        *error = [NSError errorWithDomain:@"keyLengthError" code:-1 userInfo:nil];
        return nil;
    }

    CCCryptorStatus ccStatus   = kCCSuccess;
    int             ivLength   = kCCBlockSizeAES128;
    size_t          clearBytes = 0;
    NSMutableData *dataOut     = [NSMutableData dataWithLength:data.length - ivLength];

    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithmAES,
                       kCCOptionPKCS7Padding,
                       key.bytes, key.length,
                       data.bytes,
                       data.bytes + ivLength, data.length - ivLength,
                       dataOut.mutableBytes, dataOut.length,
                       &clearBytes);

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

    return dataOut;
}

测试:

NSError *error;
NSData *key   = [@"Bad example key " dataUsingEncoding:NSUTF8StringEncoding];
NSData *clear = [@"Test Input"       dataUsingEncoding:NSUTF8StringEncoding];

NSData *encrypted = [Crypto aesCBCEncrypt:clear
                                         key:key
                                       error:&error];

NSData *decrypted = [Crypto aesCBCDecrypt:encrypted
                                         key:key
                                       error:&error];

NSLog(@"key:       %@", key);
NSLog(@"clear:     %@", clear);
NSLog(@"encrypted: %@", encrypted);
NSLog(@"decrypted: %@", decrypted);

输出:

键:42616420 6578616d 706c6520 6b657920 清除:54657374 20496e70 7574 加密:44f02b5e 40bf5031 01cc55fd cad80a77 790b9d05 5a6c8de7 6c949191 d3ba57de 解密:54657374 20496e70 7574

【讨论】:

  • 谢谢Zaph!,我们必须遵循相同的密码生成算法,即“AES/CBC/PKCS5Padding”来生成IV,在服务器端进程解密时随机字节生成如何解决我们的问题会被java lang反转吗?
  • 解密时不会生成IV,用于加密的IV必须以某种方式传递给解密,一种常用的方法是将其添加到加密数据中,这就是我的示例代码所做的.
  • Zalph 我很高兴使用此代码,并且能够使用 KEY 和 IV 加密解密。但是我在使用 PKDF2 创建 salt 并添加加密密钥并对其进行解密时遇到了困难。您也可以通过在答案中包含它来帮助我们吗?
  • @zaph stackoverflow.com/questions/64679465/… .... 先生,我需要您在此链接中的启发
  • 太棒了..它工作正常......非常感谢@zaph
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 2012-06-24
相关资源
最近更新 更多