How does one generate a public key from a modulus and exponent in iOS?

Discussion in 'iOS Programming' started by chrono1081, Jun 12, 2015.

  1. chrono1081 macrumors 604

    chrono1081

    Joined:
    Jan 26, 2008
    Location:
    Isla Nublar
    #1
    Hi guys,

    I've been wracking my brain for weeks on RSA encryption and it turns out the key I had isn't the key at all, its an exponent and I need to use the exponent and modulus I have to generate a key, however it doesn't seem (from what I've found) that Apple has a way of doing that in iOS.

    Does anyone happen to know if indeed it does or how I would go about doing this? Any help is hugely appreciated.
     
  2. mjohnson1212 macrumors member

    Joined:
    Nov 15, 2007
    #2
    I use openssl for this because the Apple APIs didn't provide a way to do that.
    Also at the time I had to implement this Apple's APIs did not support OAEP padding which is what the .net code that was decrypting this was expecting.

    This code is pre-ARC and RSAPublic key is just a class that contains NSData for the modulus and exponent. The modulus and exponent in my case are provided in string format from .net and I base64 decode them to get my NSData.

    It uses the crypto library from openssl.

    Code:
    + (NSData *)RSAEncryptDataWithKey:(RSAPublicKey *)rsaPublicKey plainText:(NSData *)plainText error:(NSError **)anError
    {
        BIGNUM * bn_mod = NULL;
        BIGNUM * bn_exp = NULL;
      
        // Convert to modulus and exponent to BIG.
        bn_mod = BN_bin2bn([rsaPublicKey.modulus bytes], (int)[rsaPublicKey.modulus length], NULL);
        bn_exp = BN_bin2bn([rsaPublicKey.exponent bytes], (int)[rsaPublicKey.exponent length], NULL);
      
        // Create a new RSA key.
        RSA *rsaKey = RSA_new();
        if (rsaKey == NULL)
        {
            if (anError != NULL)
            {
                unsigned long opensslError = ERR_peek_last_error();
                *anError = [ErrorUtil errorWithUnderlyingCategory:@"openssl" underlyingErrorCode:opensslError category:@"Encryption" errorCode:-1 description:@"RSA_new failed"];
            }
          
            return nil;
        }
      
        // Assign the modulus.
        rsaKey->n = bn_mod;
        // Assign the exponent.
        rsaKey->e = bn_exp;
        rsaKey->d = NULL;
        rsaKey->p = NULL;
        rsaKey->q = NULL;
      
        // Calculate the length of the cipher text.
        int maxRsaSize = RSA_size(rsaKey);
      
        // Create a NSMutableData with the calculated size.
        NSMutableData *cipherData = [[[NSMutableData alloc] initWithLength:maxRsaSize] autorelease];
        if (cipherData == nil)
        {
            if (anError != NULL)
            {
                *anError = [ErrorUtil errorWithCategory:@"Memory" errorCode:-1 description:@"NSMutableData initWithLength failed"];
            }
            RSA_free(rsaKey);
            return nil;
        }
      
        // Encrypt the plain text using RSA public encryption using the passed in Key. Use OAEP padding because thats what the .net side expects.
        int ret = RSA_public_encrypt((int)[plainText length], (unsigned char*)[plainText bytes], [cipherData mutableBytes], rsaKey, RSA_PKCS1_OAEP_PADDING);
        if (ret == -1)
        {
            if (anError != NULL)
            {
                unsigned long opensslError = ERR_peek_last_error();
                *anError = [ErrorUtil errorWithUnderlyingCategory:@"openssl" underlyingErrorCode:opensslError category:@"Encryption" errorCode:ret description:@"RSA_public_encrypt failed"];
            }
          
            RSA_free(rsaKey);
            return nil;
        }
      
        // Free the RSA key.
        RSA_free(rsaKey);
      
        return cipherData;
    }
    
     
  3. chrono1081 thread starter macrumors 604

    chrono1081

    Joined:
    Jan 26, 2008
    Location:
    Isla Nublar
    #3

    Thanks so much! I'll give this a try.
    I wonder why Apple doesn't have an easier way to do this.
     

Share This Page