RSA public key generation — Swift

Azure key vault sends e and n parameters which equals RSA modulus(n) and RSA public exponent(e). It’s easy to create with 3rd party libraries, but output value wouldn’t be valid without modulus and exponent.

I need to create RSA public key of these two parts.Then I have to create RSA OAEP.
Has anyone encountered a similar problem? Any idea how to achieve this?

  • 3DES result in Java produces different result from 3DES iOS version
  • Encrypt in Objective-C / Decrypt in Ruby using anything
  • Azure Push Notification Error from IOS Xcode
  • CFNetwork SSLHandshake failed (-9807) on iOS simulator with localhost
  • AES-256 encryption & Apple iTunes export restrictions
  • XOR Encryption in Swift IOS
  • I have tried to use SCZ-BasicEncodingRules-iOS, but it output incorrect code.

    Here is code:

    let moduleString: String = "mK-g0TLMqtefmosgBSTQi3dWh8h-rn4lQA8sQgNs_Gkf5TvgKWtYGJ4jRGUU-eK2bmyAAomVUojYBBlRYBkTRekm99DlD9T6U9yI3v11pZVl3yQgVXBEkiTZug3Inn_IAOGPQ3Q5OT6fEj1sRRxmMv93CQukQguSKuU4v2tmElgvyhg_eKIQbNx0JRCI4-1Z5GazxNjtwk7tWcA6PAbV0zZe2AaW0TlYVil_U8NckgHBguBoTHqVAbzb-MNa-HRa4QlBmdemcSaiDr5GikoOdmQ1-Lu6koqUkepx16pgqPvVw3o_NuXAZCS37c7bfgtXWTJcAIjiQaEyRcIV2bXsUQ"
    
        let exponent: String = "AQAB"
    
        let moduleData: NSData! = (moduleString
            as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let expData: NSData! = (exponent
            as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let arrayaaa: NSArray = [moduleData, expData]
        let key: NSData = arrayaaa.berData()
    

    Solutions Collect From Internet About “RSA public key generation — Swift”

    So, I have found a solution. Unfortunately SCZ-BasicEncodingRules-iOS has wrong decoding algorithm for iOS 8 and above. It outputs key with incorrect prefix.

    If you faced with the same issue, here is a solution that helped me, but it’s Objective-C code. Original source:

       + (NSData *)generateRSAPublicKeyWithModulus:(NSData*)modulus exponent:(NSData*)exponent
    {
        const uint8_t DEFAULT_EXPONENT[] = {0x01, 0x00, 0x01,}; //default: 65537
        const uint8_t UNSIGNED_FLAG_FOR_BYTE = 0x81;
        const uint8_t UNSIGNED_FLAG_FOR_BYTE2 = 0x82;
        const uint8_t UNSIGNED_FLAG_FOR_BIGNUM = 0x00;
        const uint8_t SEQUENCE_TAG = 0x30;
        const uint8_t INTEGER_TAG = 0x02;
    
        uint8_t* modulusBytes = (uint8_t*)[modulus bytes];
        uint8_t* exponentBytes = (uint8_t*)(exponent == nil ? DEFAULT_EXPONENT : [exponent bytes]);
    
        //(1) calculate lengths
        //- length of modulus
        int lenMod = (int)[modulus length];
        if(modulusBytes[0] >= 0x80)
            lenMod ++;  //place for UNSIGNED_FLAG_FOR_BIGNUM
        int lenModHeader = 2 + (lenMod >= 0x80 ? 1 : 0) + (lenMod >= 0x0100 ? 1 : 0);
        //- length of exponent
        int lenExp = exponent == nil ? sizeof(DEFAULT_EXPONENT) : (int)[exponent length];
        int lenExpHeader = 2;
        //- length of body
        int lenBody = lenModHeader + lenMod + lenExpHeader + lenExp;
        //- length of total
        int lenTotal = 2 + (lenBody >= 0x80 ? 1 : 0) + (lenBody >= 0x0100 ? 1 : 0) + lenBody;
    
        int index = 0;
        uint8_t* byteBuffer = malloc(sizeof(uint8_t) * lenTotal);
        memset(byteBuffer, 0x00, sizeof(uint8_t) * lenTotal);
    
        //(2) fill up byte buffer
        //- sequence tag
        byteBuffer[index ++] = SEQUENCE_TAG;
        //- total length
        if(lenBody >= 0x80)
            byteBuffer[index ++] = (lenBody >= 0x0100 ? UNSIGNED_FLAG_FOR_BYTE2 : UNSIGNED_FLAG_FOR_BYTE);
        if(lenBody >= 0x0100)
        {
            byteBuffer[index ++] = (uint8_t)(lenBody / 0x0100);
            byteBuffer[index ++] = lenBody % 0x0100;
        }
        else
            byteBuffer[index ++] = lenBody;
        //- integer tag
        byteBuffer[index ++] = INTEGER_TAG;
        //- modulus length
        if(lenMod >= 0x80)
            byteBuffer[index ++] = (lenMod >= 0x0100 ? UNSIGNED_FLAG_FOR_BYTE2 : UNSIGNED_FLAG_FOR_BYTE);
        if(lenMod >= 0x0100)
        {
            byteBuffer[index ++] = (int)(lenMod / 0x0100);
            byteBuffer[index ++] = lenMod % 0x0100;
        }
        else
            byteBuffer[index ++] = lenMod;
        //- modulus value
        if(modulusBytes[0] >= 0x80)
            byteBuffer[index ++] = UNSIGNED_FLAG_FOR_BIGNUM;
        memcpy(byteBuffer + index, modulusBytes, sizeof(uint8_t) * [modulus length]);
        index += [modulus length];
        //- exponent length
        byteBuffer[index ++] = INTEGER_TAG;
        byteBuffer[index ++] = lenExp;
        //- exponent value
        memcpy(byteBuffer + index, exponentBytes, sizeof(uint8_t) * lenExp);
        index += lenExp;
    
        if(index != lenTotal)
            NSLog(@"lengths mismatch: index = %d, lenTotal = %d", index, lenTotal);
    
        NSMutableData* buffer = [NSMutableData dataWithBytes:byteBuffer length:lenTotal];
        free(byteBuffer);
    
        return buffer;
    }
    

    This algorithm matches with standard Java KeyFactory generation class.