How to add salt to AES Encryption in iOS and decrypting it using objective c

不打扰是莪最后的温柔 提交于 2020-12-21 04:18:25

问题


I have appended the IV to the AES Encryption/decryption code by using objective c in iOS and able to decrypt and encrypt the same. Right now I am trying to add the salt to the AES Encryption but unfortunately its not working for me. Here is the code: I have also edited with Android salt generation code for just to check whether my salt generation is valid or not in iOS

Encryption code:

    + (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;
}

Decryption code :

+ (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,
                       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;
}

Generating random salt and Algorithm..

+ (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;
}

I have done all these based on the link enter link description here But unfortunately I am getting the output of decryption as nil

Please suggest where am doing wrong?

I have removed the Salt generation code from the Encrypt method . I moved the code to the ViewController.m here is the code:

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]);

Here is the Android SALT generation code :

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);

回答1:


You're stretching your encryption key, but you're not stretching your decryption key. The decryption code never calls AESKeyForPassword, and I don't see anywhere that you store the salt to send it to the decryptor (the way you send the IV to the decryptor). You can't just apply PBKDF2 to one side. That gives you completely different keys.



来源:https://stackoverflow.com/questions/64679465/how-to-add-salt-to-aes-encryption-in-ios-and-decrypting-it-using-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!