MehtaiPhoneApps MehtaiPhoneApps - 11 months ago 84
iOS Question

SecKeyEncrypt SecPaddingNone iOS

I am trying to do Raw RSA Encryption on iOS. Please do not try and talk me out of it.

I am basically doing encryption with two keys. The first step, using key A, uses SecPaddingPKCS1 and gives me an output of 256 bytes. After that, using Key B, I use SecPaddingNone. I assume that my output will remain 256 bytes, but it becomes 512 bytes. I am not sure what I am doing wrong, does anyone know? Am I thinking about this wrong?

I use the SwiftyRSA library to perform the encryption.


Edit Code:

The encryptData function has been copied over from SwiftyRSA. Assume that

is 256 bytes, and is the result of the first encryption by Key A.

let dataString = text.dataUsingEncoding(NSUTF8StringEncoding)
let certificateLabel = "certificate"
let certificateRef = self.getCertificateFromKeyChain(certificateLabel)
let certificateData = self.getDataFromCertificate(certificateRef)
let cryptoImportExportManager = CryptoExportImportManager()
let publicKeyRef = cryptoImportExportManager.importPublicKeyReferenceFromDERCertificate(certificateData)
let encryptedData = self.encryptData(data, publicKey: publicKeyRef!, padding: SecPadding.None)

Let me know if I need to add more code.



This is was a bug in SwiftyRSA; RSA returns blocksize (in this case 256) bytes after encryption. If you encrypt more than blocksize bytes then the data is split into multiple chunks, each of which is encrypted, so you will get a multiple of blocksize bytes back.

When PKCS1 padding is used the effective blocksize is reduced by 11 bytes, which means that encrypting 256 bytes will return two blocks or 512 bytes (since 256 is > 256-11 or 245).

When no padding is used, the blocksize doesn't need to be reduced by 11, but SwiftyRSA still does this. I have tested without the 11 byte reduction using no padding and the second encryption, without padding, returns 256 bytes as expected. The regression tests still pass and I have confirmed that openssl can correctly decrypt the double encrypted data (first with padding and then encrypted a second time with no padding).

This has now been fixed in the Git repo, but if you want to patch your local source as a work-around, the fix is to change encryptData as follows:

// Encrypts data with a RSA key
public func encryptData(data: NSData, publicKey: SecKeyRef, padding: SecP public func encryptData(data: NSData, publicKey: SecKeyRef, padding: SecPadding) throws -> NSData {
    let blockSize = SecKeyGetBlockSize(publicKey)

    let maxChunkSize = (padding == .None) ? blockSize : blockSize - 11