5

I'm trying to write a password encryption function into my app, following this article.

I wrote a function that runs the CCCalibratePBKDF function and outputs the number of rounds.

const uint32_t oneSecond = 1000;
uint rounds = CCCalibratePBKDF(kCCPBKDF2,
                               predictedPasswordLength,
                               predictedSaltLength,
                               kCCPRFHmacAlgSHA256,
                               kCCKeySizeAES128,
                               oneSecond);

This works perfectly, but when I try to implement the next part it all goes wrong.

I can start writing the CCKeyDerivationPBKDF function call and it auto-completes the function and all the parameters. As I go through filling it in all the parameters are also auto-completed.

- (NSData *)authenticationDataForPassword: (NSString *)password salt: (NSData *)salt rounds: (uint) rounds
{
    const NSString *plainData = @"Fuzzy Aliens";
    uint8_t key[kCCKeySizeAES128] = {0};
    int keyDerivationResult = CCKeyDerivationPBKDF(kCCPBKDF2,
                                                   [password UTF8String],
                                                   [password lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
                                                   [salt bytes],
                                                   [salt length],
                                                   kCCPRFHmacAlgSHA256,
                                                   rounds,
                                                   key,
                                                   kCCKeySizeAES128);
    if (keyDerivationResult == kCCParamError) {
        //you shouldn't get here with the parameters as above
        return nil;
    }
    uint8_t hmac[CC_SHA256_DIGEST_LENGTH] = {0};
    CCHmac(kCCHmacAlgSHA256,
           key,
           kCCKeySizeAES128,
           [plainData UTF8String],
           [plainData lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
           hmac);
    NSData *hmacData = [NSData dataWithBytes: hmac length: CC_SHA256_DIGEST_LENGTH];
    return hmacData;
}

But as soon as I hit ; it marks an error saying "No matching function for call to 'CCKeyDerivationPBKDF'" and it won't build or anything.

I've imported CommonCrypto/CommonKeyDerivation.h and CommonCrypto/CommonCryptor.h as both of these were necessary for the enum names.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • All the code is in the article I linked. Will post some anyway if you would prefer? – Fogmeister Aug 13 '12 at 16:51
  • Not really an answer, but the premise of the article you cite is completely bogus. You are protecting against an off-line attack. The speed of the device on which the key is legitimately derived really shouldn't be a factor. What matters is how fast the attackers' machines are. – erickson Aug 13 '12 at 18:04
  • @erickson, while what you say is true, it is not practical in real systems. You have to scale the number of iterations based on the slowest legitimate machine involved or else you will make the system unusable (i.e. you will DoS yourself). While it would be nice to make the # of iterations arbitrarily high to protect against all possible attackers, this would make encryption and decryption unacceptably slow. The fact that it can be tuned establishes what "acceptable" means, but it will always be based on the slowest machine. – Rob Napier Aug 13 '12 at 18:58

2 Answers2

2

First, make sure that you haven't done anything funny with your include path (in particular, I do not recommend @HachiEthan's solution, which just confuses things). In general, leave this alone, and specifically don't add things like /usr/include to it. Make sure you've added Security.framework to your link step. This is the usual cause of problems.

The biggest thing you want to be sure of is that you're getting the iOS 5 Security.framework (rather than some other version like the OS X 10.6 or iOS 4 versions). But my suspicion is that you have a problem with your build settings.

If you want to see a framework that does all of this for reference, take a look at RNCryptor.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Deleted my answer because I don't know what the heck I was thinking and I agree with you. You are correct, making sure `Security.framework` is added should do it, and is preferred!! – MechEthan Aug 13 '12 at 18:26
  • Thanks for the reply. I hadn't added the Security framework which Inow have but still getting the same problem. The only change I've made to the build settings is the Header Search Paths for the ZXing library. Really odd. – Fogmeister Aug 14 '12 at 06:51
2

Right, I've found the problem (and solution).

Because I was using ZXing I had to rename the .m file to .mm so it could run the C++ stuff in the ZXing library.

I don't know why but renaming the file this way broke the CCKeyDerivationPBKDF function.

I've now moved the crypto code into it's own class and left it as .m and all I need now is to include the two imports as I did in the original post.

I didn't have to include any frameworks or anything.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • 1
    Turns out it's because of mis-matching pointer types that C++ is more picky about. Could have fixed it with casting to the correct pointer types but I was only provisionally building in the file it was in with the intention of moving it into its own class anyway. – Fogmeister Aug 14 '12 at 08:30