Suppose that you somehow linked your PDF file before you put it on your download server, and the application descrambles it before showing it to the user.
In the application, you can do the following:
- Load the scrambled PDF file into an
NSData object. - Create an
NSMutableData object and decrypt your PDF data into this buffer using any algorithm you choose. - You now have a useful PDF document in mind, but only a scrambled version on disk. If you need to create a
CGPDFDocumentRef , you can do this by first creating a dataprovider using your descrambled NSMutableData object, which connects CFData to CFData with a simple application
Something like
NSMutableData *data = descrambled PDF; CFDataRef myPDFData = (CFDataRef)data; CGDataProviderRef provider = CGDataProviderCreateWithCFData(myPDFData); CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(provider);
(Credit for this fragment goes into this answer .)
Since the application must be able to descramble the PDF file, and the user has access to both the application and the scrambled PDF file, everything you do to prevent them from being extracted will basically be obscurity. Therefore, I would not worry about a complex encryption algorithm. Perhaps you can just do something simple, such as XOR, data with a secret string hidden in a binary application.
Defeating this approach will require an attacker to disassemble your binary, and if someone is determined, you cannot win, as evidenced by the sad state of the DRM video game.
By the way: in the spirit of ambiguity, you can also call your scrambled downloaded PDF files something less obvious than valuabledocument.pdf . But real security is not the case.
Edit to illustrate XOR'ing data :
Feed your scrambled NSData to something like this ...
// Fill this out with whatever you want. Use the same string // and algorithm to scramble the files on the server. static unsigned char secretString[SECRET_STRING_LENGTH]; - (NSData *)scrambleOrDescrambleData:(NSData*)input { unsigned char *outputBytes = malloc(input.length); memcpy(outputBytes, input.bytes, input.length); for (int i = 0; i < input.length; i++) { outputBytes[i] = outputBytes[i] ^ secretString[i % SECRET_STRING_LENGTH]; } NSData *outputData = [[NSData alloc] initWithBytes:outputBytes length:input.length]; free(outputBytes); return outputData; }
The convenient thing about XOR is that doing this twice will give you back the original data, so scrambling and descrambling is the same code.
I avoid the term encryption here because it is really just confusing data in order to save it from random observers.