1

Hi I am new for developing the ios application. I have a modulus and an exponent and i need to generate SecKey and then use this to encrypt some data (RSA encryption). Please any one help in swift.

shallowThought
  • 19,212
  • 9
  • 65
  • 112
vara
  • 816
  • 3
  • 12
  • 29
  • 3
    You should not implement crypto algorithms or key generation by yourself (not being _an expert_ in cryptography). Where security matters, use mature and well-known libraries and tools. – werediver Jan 12 '17 at 13:23
  • can you gave some sample example? – vara Jan 13 '17 at 07:11

3 Answers3

1

You should not implement crypto algorithms or key generation by yourself (not being an expert in cryptography). Where security matters, use mature and well-known libraries and tools.

On iOS it's worth checking out SecKey API (SecKeyEncrypt(_:_:_:_:_:_:) and so on). It was mentioned at WWDC 2016 Session 706 starting at 16:10.

You may find useful investigating the CryptoCompatibility example project which "shows common cryptographic operations using Apple APIs."

As a cross-platform solution you can use OpenSSL which also provides RSA API.

werediver
  • 4,667
  • 1
  • 29
  • 49
  • It seems the question was not about how to generate keys, but how to take the generated modulus and exponent data and convert it into a useable format. – Aaron Ash Jun 22 '18 at 14:43
  • @AaronAsh In fact, this answer suggests a potentially better direction to look to for a solution of the the author's problem, which from the original question appears to me to be of an [XY kind](https://en.wikipedia.org/wiki/XY_problem). If it doesn't help you, asking a new question might be a good option. – werediver Jun 22 '18 at 15:03
0

A few similar questions have been asked/answered already, here's one where you can take a modulus and exponent and get a .PEM format out of it: Generate RSA Public Key from Modulus and Exponent

Here's another, although this one uses OpenSSL: https://stackoverflow.com/a/31010530/209855

Additionally, you've probably run into some people recommending https://github.com/StCredZero/SCZ-BasicEncodingRules-iOS like here https://stackoverflow.com/a/10643894/209855

But if you're like me, nothing actually worked or gave you exactly what you wanted.

If you read through the issues on that github repo, you'll find something broke around iOS 8 and it no longer generates the correct data.

However, someone posted a fix for this: https://github.com/Meniny/Meniny.github.io/blob/5895a2d51502881a7d6cda418beafa546874dfa7/_posts/2017-08-12-RSA_public_key_with_modulus_and_exponent.md I'll reproduce the code here, in case it disappears in the future.

+ (NSData * __nullable)generateRSAPublicKeyWithModulus:(NSData * __nonnull)modulus exponent:(NSData * __nonnull)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;
}

And last but not least, to generate the RSA Public Key from a Modulus and Exponent in Swift 3:

public func encrypt(_ string: String, modulus: String, exponent: String) -> String? {
  if let modData = Data(base64Encoded: modulus),
    let expData = Data(base64Encoded: exponent),
    let keyData = PublicKeyRSA.generatePublicKey(withModulus: modData, exponent: expData) {
      /// encrypt...
  }
}
Aaron Ash
  • 1,412
  • 13
  • 24
  • PublicKeyRSA.generatePublicKey gave this error: "Use of unresolved identifier 'PublicKeyRSA'" – utarid Jul 28 '18 at 13:46
  • Put the `generateRSAPublicKeyWithModulus` key in some Objective-C file you can call from swift, and call it. I just used it from Objective-C. You probably need to setup a bridging header. – Aaron Ash Aug 01 '18 at 13:05
0

PublicKeyRSA.generatePublicKey is returning the data in bytes, not returning the public key. We have to use the public keys to encrypt our data.

  • You might want to ask a question on Stack Overflow and add a link to this question in your question. On that question, explain specifically why this question does not solve your problem. – TonyStark4ever Apr 13 '20 at 20:56