How to protect Digital Content (PDF) inside my iOS app?

早过忘川 提交于 2019-12-03 07:12:30
Heiberg

Let's assume that you somehow scramble your PDF before putting it on your download server and the app descrambles it before showing it to the user.

In the app you can then perform the following:

  1. Load the scrambled PDF file into an NSData object.
  2. Make an NSMutableData object and descramble your PDF data into that buffer using whatever algorithm you have chosen.
  3. Now you have a usable PDF document in memory but only a scrambled version on disk. If you need to create a CGPDFDocumentRef you can do that by first creating a dataprovider using your descrambled NSMutableData object which is toll-free bridged to CFData by a simple cast

Something like

NSMutableData *data = descrambled PDF;
CFDataRef myPDFData = (CFDataRef)data;
CGDataProviderRef provider = CGDataProviderCreateWithCFData(myPDFData);
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(provider);

(Credit for that snippet goes to this answer.)

Since the app must be able to descramble the PDF and user has access to both the app and the scrambled PDF file anything you do to prevent them from extracting it will basically amount to security by obscurity. Therefore I wouldn't bother with a complex encryption algorithm. You can probably just do something simple like XOR the data with a secret string hidden in your app binary.

Defeating this approach will require an attacker to disassemble your binary, and if someone is that determined you can't win, as evidenced by the sad state of current video game DRM.

By the way: In the spirit of obscurity you might also want to name your scrambled downloaded PDFs something less obvious than valuabledocument.pdf. But real security it ain't.

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 handy thing about XOR is that doing it twice will give you back your original data, so scrambling and descrambling is the same code.

I am avoiding the term encryption here, because this is really just obfuscating the data to keep it from casual observers.

You can protect your files by encrypting them. Look at the apple reference on Protecting Data Using On-Disk Encryption.

Take look at this article: http://aptogo.co.uk/2010/07/protecting-resources/

The author details encrypting app bundle resources, and then decrypting the files into memory so only the scrambled version ever resides on disk.

They use a custom NSURLProtocol for encrypting on the fly. Pretty nice summary.

You shouldn't be worried about someone getting a hold of the .ipa file and extracting the PDFs that way (since your app downloads the PDFs and they PDFs do not ship with the .ipa file).

There are, however, tools to let users browse the files within apps that are on their devices. For example, checkout iExplorer. You should note that users could potentially open any file -- so storing a password in a sqlite database is not a good idea. Using something like SFHKeychainUtils would be a more secure approach.

As far as setting a username/password for a PDF goes, here is some sample code (you can learn more from the CGPDFContext Reference):

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: @"letMeIn", kCGPDFContextOwnerPassword, @"r3adm3", kCGPDFContextUserPassword, nil];
[myPDFDocument writeToFile: @"/some/path" withOptions: options];

I would also suggest storing the file encrypted on the disk. You could use NSData+AES to do this. Here is another implementation of NSData+AES. When reading from the disk, you could hold the unencrypted NSData in memory and display a PDF from that instead of reading an unencrypted PDF from the disk.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!