0
votes

I'm trying to RSA encrypt an NSData using a public key. The public key is in this format:

<RSAKeyValue>
  <Modulus>yOTe0L1/NcbXdZYwliS82MiTE8VD5WD23S4RDsdbJOFzCLbsyb4d+K1M5fC+xDfCkji1zQjPiiiToZ7JSj/2ww==</Modulus>
  <Exponent>AWAB</Exponent>
</RSAKeyValue>

After extracting the modulus and exponent from the XML string, how do I get a SecKeyRef out of those to be used as publicKey in the method below?

+ (NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey
{
    size_t cipherBufferSize = SecKeyGetBlockSize(publicKey); 
    uint8_t *cipherBuffer = malloc(cipherBufferSize); 
    uint8_t *nonce = (uint8_t *)[plainTextString UTF8String]; 
    SecKeyEncrypt(publicKey,
        kSecPaddingOAEP, 
        nonce, 
        strlen( (char*)nonce ), 
        &cipherBuffer[0], 
        &cipherBufferSize);
    NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize]; 
    return [encryptedData base64EncodedString];
}

I can't seem to find a definite answer anywhere.

3

3 Answers

1
votes

Wow, no wonder it's so hard to find an answer to this. I spent 2 days down the crypto-rabbit hole, and it's not pretty.

The easy way

Use Chilkat iOS RSA Library. One major downside: cost $189! :O

The hard way

Parse the XML, use SCZ-BasicEncodingRules-iOS to generate a public key data out of the modulus and exponent. If that works, create a dummy keychain using that public key (follow sample code here), extract the public key now in SecKeyRef format and pass it to the encryptRSA method in the question. Finally, cleanup, remove the dummy keychain. Sounds good in theory, but I have never tested this thoroughly, if you do, let me know!

0
votes

I have used the below method for encryption using public key without using any third party libs, guess it may help who is looking for the same after they implemented it just as I did :D

+(NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey
{
    size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
    uint8_t *cipherBuffer = malloc(cipherBufferSize);
    uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
    SecKeyEncrypt(publicKey,
                  kSecPaddingPKCS1,
                  nonce,
                  strlen( (char*)nonce ),
                  &cipherBuffer[0],
                  &cipherBufferSize);
    NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
    return [encryptedData base64EncodedStringWithOptions:0];
}
-3
votes

I think this will help u! you can create a java file like fellow: this java funtion will generate a public key to base64String

public static RSAPublicKey getPublicKey(String modulus, String exponent) {
    try {
        BigInteger b1 = new BigInteger(modulus,16);
        BigInteger b2 = new BigInteger(exponent,16);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
        return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

public static  String  encodePublicKey(byte[] encoded) throws Exception{
    BASE64Encoder base64Encoder= new BASE64Encoder();
    String s=base64Encoder.encode(encoded);
    return s;

u should use like :encodePublicKey(publicKey.getEncoded());

Got it!