如何在iOS的AES加密中添加盐并使用目标c对其解密

问题描述

我已通过在iOS中使用目标c将IV附加到AES加密/解密代码,并能够对其进行解密和加密。现在,我正在尝试将盐添加到AES加密中,但是很不幸,它对我不起作用。这是代码:我还使用Android盐生成代码进行了编辑,目的只是为了检查我的盐生成在iOS中是否有效

加密代码

    + (NSData*)encryptData:(NSData*)data key:(NSData*)key error:(NSError **)error;
{
    NSData *salt = [self randomDataOfLength:16];
    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);
    NSLog(@"Data Out String Encrypt%@",dataOut);
    NSLog(@"Status ID Engrypt%d",status);
    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*)decryptData:(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];
    
    NSLog(@"Data Out String Decrypt%@",dataOut);

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

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

    return dataOut;
}

生成随机盐和算法。

+ (NSData *)randomDataOfLength:(size_t)length {
  NSMutableData *data = [NSMutableData dataWithLength:length];
  
  int result = SecRandomcopyBytes(kSecRandomDefault,length,data.mutableBytes);
  NSAssert(result == 0,@"Unable to generate random bytes: %d",errno);
  
  return data;
}

// Replace this with a 10,000 hash calls if you don't have CCKeyDerivationPBKDF
+ (NSData *)AESKeyForPassword:(Nsstring *)password
                         salt:(NSData *)salt {
  NSMutableData *
  derivedKey = [NSMutableData dataWithLength:32];
  
  int
  result = CCKeyDerivationPBKDF(kCCPBKDF2,// algorithm
                                password.UTF8String,// password
                                [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding],// passwordLength
                                salt.bytes,// salt
                                salt.length,// saltLen
                                kCCPRFHmacAlgSHA1,// PRF
                                10000,// rounds
                                derivedKey.mutableBytes,// derivedKey
                                derivedKey.length); // derivedKeyLen
  
  // Do not log password here
  NSAssert(result == kCCSuccess,@"Unable to create AES key for password: %d",result);
  
  return derivedKey;
}

我已经基于链接enter link description here完成了所有这些操作,但不幸的是,我得到的解密输出为nil

enter image description here

请提出错误的地方?

我从Encrypt方法删除了Salt生成代码。我将代码移到了 ViewController.m ,这里是代码

Nsstring *myScretString = @"My encryption string";
NSData *salt = [FBEncryptorAES randomDataOfLength:16];
NSData *key1 = [FBEncryptorAES AESKeyForPassword:@"E8E033BC691W5F092BB5909933636552" salt:salt];
NSData* encryptedData = [FBEncryptorAES encryptData:[myScretString dataUsingEncoding:NSUTF8StringEncoding]
                                                key:key1
                                              error:&error];

NSLog(@"encryptedWithDynamicIV: %@",[encryptedData base64EncodedStringWithOptions:0]);

NSData* decryptedData = [FBEncryptorAES decryptData:encryptedData
                                                    key: key1
                                                  error:&error];
    NSLog(@"decryptedWithDynamicIV: %@",[[Nsstring alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding]);

这是Android SALT生成代码

private static final String ALGORITHM = "AES";
        private static final String MODE = "AES/CBC/PKCS5Padding";
        private static final String KEY = "5909E8E0335F092BBBC699336365521W";
 
byte[] salt = generateSalt();
               SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
               KeySpec spec = new PBEKeySpec(KEY.tochararray(),salt,65536,256);
               SecretKey tmp = factory.generateSecret(spec);
               SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(),ALGORITHM);

解决方法

您正在扩展加密密钥,但没有扩展解密密钥。解密代码从不调用AESKeyForPassword,而且我看不到您将盐存储到任何地方以将其发送给解密器的方式(将IV发送给解密器的方式)。您不能仅将PBKDF2应用于一侧。这给您完全不同的键。