1

I need to write a function to generate a new RSA private key natively on OS X and be able to print out prime numbers, modulus, etc. I don't want to use nor store anything in the Keychain, just write a simple command line tool.

It used to be very easy in C/Objective-C using OpenSSL to generate a new key with:

RSA *keypair = RSA_generate_key(1024, 3, NULL, NULL);

But OpenSSL is deprecated, so my question is how to write an equivalent in Swift using the native CommonCrypto framework. It is not very well documented and I could find anything that works for me so far.

Can anyone please share a code snippet that does this? Thanks

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Anubis
  • 653
  • 1
  • 7
  • 16

1 Answers1

2

The CommonRSACryptor headers can be found at :

http://opensource.apple.com/source/CommonCrypto/CommonCrypto-60026/Source/CommonCryptoSPI/CommonRSACryptor.h

You can create a bridging header with the following code:

typedef int32_t CCCryptorStatus;
typedef struct _CCRSACryptor *CCRSACryptorRef;
CCCryptorStatus CCRSACryptorGeneratePair(size_t keysize, uint32_t e, CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey);
CCCryptorStatus CCRSACryptorExport(CCRSACryptorRef key, void *out, size_t *outLen);
void CCRSACryptorRelease(CCRSACryptorRef key);

After that you can use the CCRSACryptorGeneratePair, CCRSACryptorExport, CCRSACryptorRelease functions from Swift.

var privateKey: CCRSACryptorRef = nil
var publicKey: CCRSACryptorRef = nil
var status = CCRSACryptorGeneratePair(keySize, 65537, &publicKey, &privateKey)
guard status == noErr else {
    throw error("CCRSACryptorGeneratePair failed \(status)")
}
defer { CCRSACryptorRelease(privateKey) }
defer { CCRSACryptorRelease(publicKey) }

var privKeyDataLength = 8192
let privKeyData = NSMutableData(length: privKeyDataLength)!
var pubKeyDataLength = 8192
let pubKeyData = NSMutableData(length: pubKeyDataLength)!

status = CCRSACryptorExport(privateKey, privKeyData.mutableBytes, &privKeyDataLength)
guard status == noErr else {
    throw error("CCRSACryptorExport privateKey failed \(status)")
}
status = CCRSACryptorExport(publicKey, pubKeyData.mutableBytes, &pubKeyDataLength)
guard status == noErr else {
    throw error("CCRSACryptorExport publicKey failed \(status)")
}

privKeyData.length = privKeyDataLength
pubKeyData.length = pubKeyDataLength

The SwCrypt library does the same thing.

soyer
  • 316
  • 2
  • 10