Search code examples
iosobjective-cnsdatarncryptor

RNCryptor: get public key as NSString


I'm successfully encrypting/decrypting data in iOS using RNCryptor.

I'm trying to get the public key to send to a server, so it can encrypt some data.

NSString *saltString = @"salt'n'peppa";
NSData *salt = [saltString dataUsingEncoding:NSUTF8StringEncoding];
NSData *key = [RNCryptor keyForPassword:password
                                   salt:salt
                               settings:kRNCryptorAES256Settings.keySettings];

At this point, key has some data in it. However, I can't seem to work out how to get the public key as a string:

NSString *publicKey = [[NSString alloc] initWithData:key encoding:NSUTF8StringEncoding];

I've tried different encodings but nothing seems to work.

Here is the keyForPassword method from RNCryptor:

+ (NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt settings:(RNCryptorKeyDerivationSettings)keySettings
{
  NSMutableData *derivedKey = [NSMutableData dataWithLength:keySettings.keySize];

  // See Issue #77. V2 incorrectly calculated key for multi-byte characters.
  NSData *passwordData;
  if (keySettings.hasV2Password) {
    passwordData = [NSData dataWithBytes:[password UTF8String] length:[password length]];
  }
  else {
    passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  }

  // Use the built-in PBKDF2 if it's available. Otherwise, we have our own. Hello crazy function pointer.
  int result;
  int (*PBKDF)(CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
               const uint8_t *salt, size_t saltLen,
               CCPseudoRandomAlgorithm prf, uint rounds,
               uint8_t *derivedKey, size_t derivedKeyLen);

  PBKDF = CCKeyDerivationPBKDF ?: RN_CCKeyDerivationPBKDF;

  result = PBKDF(keySettings.PBKDFAlgorithm,         // algorithm
                 passwordData.bytes,                 // password
                 passwordData.length,                // passwordLength
                 salt.bytes,                         // salt
                 salt.length,                        // saltLen
                 keySettings.PRF,                    // PRF
                 keySettings.rounds,                 // 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 get the feeling I'm doing something majorly wrong as googling comes up with very little.


Solution

  • The key isn't a string, it's data. Just a random (sort of) series of bytes. The only real way to convert it to a string to send to a server would be to encode the bytes. A common method would be to use a base 64 encoding. Then the server could covert the base 64 encoded string back into the raw bytes of the key.