How do I store data securely with objective C? (Mac/Cocoa Dev)

*爱你&永不变心* 提交于 2019-12-10 04:10:08

问题


I'm trying to create a Trial part of my cocoa application. I have the licensing all set up (including keys) etc.

But I was wondering how I could store e.g the first the time the user ran the program in a secure place, where the user can't easily find it and/or edit it.

I was having a fiddle with NSUserDefaults standardUserDefaults, but the user can easily find and edit that data in Library > Preferences.


回答1:


I'd argue against making it super-secure. We once had a server activation but completely went away from it. Here are some of the reasons:

  • Even the most "secure" storage method can be broken
  • Even for a niche product a crack might be developed, no way around, no matter how secure your method
  • There are few, very expensive, very secure methods. All others have been cracked
  • It goes against fair and honest users, making it harder for them to fix things causing problems
  • If a user does crack your software or circumvents your security, he'll probably also never have bought it
  • 80% of the users don't even know what a preference file is
  • 95% of all users don't think of the possibility to delete it in order to extend the trial
  • A simple way to reset trial periods massively eases your support for users you want to give a second trial for whatever reason
  • Trusting users is a good selling point
  • Power users tend to turn against software with too much protection

I'm pretty sure that there are some, but extremely few, exceptions from these thoughts. I'd say: don't waste your time on registration security but give




回答2:


You can't use a file on the filesystem. Anyone who would be looking to fiddle/crack it will be smart enough to know how to track file access through basic, standard OSX features. So a file being added is out. Not only that but it is bad behavior to create files you don't remove when the app is uninstalled. People shouldn't have to have resources consumed after deleting your trial app.

As noted above, messing about in your bundle is a bad idea as well. This leaves you with three fundamental options.

1) Don't worry about it too much. Use a basic expiration system that uses the standard locations and methods. You can still use encryption in the data you store, but know that that too will be broken. Accept that copyright violation will occur unless your app is wholly unpopular.

2) Use a network call and do the validation on the server. This would require the app always be able to reach your service to be run. This is not a good idea in general. What if your servers are down? What if they are off-line? What if a network issue between you and them happens? All of those scenarios are going to happen. When they do you will likely lose customers unless your app requires a connection to your servers already to operate (like say Twitter or Facebook does).

3) Be a "bad citizen" by mucking around with the application bundle or leaving orphan files around. If you do this latter, at least make sure they are clearly named so that they relate to your application obviously.

Ultimately the key thing to remember is that you have no security on a user's machine. It is theirs. That means they have physical access which pretty much nullifies any attempt to prevent them from digging. You can also look at it this way: the more technically minded your market is, the less likely you are going to be smarter than all of us and your "security" will be cracked. If you are designing for a non-technical audience then you can figure that generally speaking they won't be bothering with cracking it, or looking for one.

You can spend your resources on making the app better, or giving yourself a better feeling about people not using it past the trial period. One of those can increase your sales, and one will not.

[edit] Also I should point out that one of the most common (if not the most common) means of cracking these things is to modify the binary. So by breaking code signing via bundle mucking you would actually open yourself to that method because you would have broken one of the better protections you have. Most cracks involve binaries being modified such that the routine that does the checks always returns a successful authentication.




回答3:


Allan Odgaard has a pretty decent writeup on how to use OpenSSL to generate/store license keys for Cocoa software. Might be worth a read.




回答4:


If you must, a simple and common way is to use a key that is embedded in the application which encrypts a file on the disk that contains the sensitive data. The challenge is how to make the key secure.

Look into the Common Crypto digest library.

This will protect from almost all casual users. Though hackers can, with enough motiviation, figure out a way to circumvent.




回答5:


Try storing a file that's name begins with a period in some folder and then setting the file's hidden flag.

a good place to put the hidden file would be an obscurely named file in the base of the users folder (~/), there are many obscure hidden files there so it is hard to know which one's you can and can't delete. example path: ~/.xdarwinprofile or something equally official sounding.

here is some code that should work to hide the file:

#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <sys/attr.h>
#include <sys/errno.h>
#include <unistd.h>
#include <sys/vnode.h>

typedef struct attrlist attrlist_t;

struct FInfoAttrBuf {
    u_int32_t length;
    fsobj_type_t objType;

    union {
        char rawBytes[32];

        struct {
            FileInfo info;
            ExtendedFileInfo extInfo;
        } file;

        struct {
            FolderInfo info;
            ExtendedFolderInfo extInfo;
        } folder;
    } finderInfo;
};
typedef struct FInfoAttrBuf FInfoAttrBuf;


- (int)SetFileInvisibility:(NSString *)filePath state:(BOOL)isInvisible) {
    attrlist_t attrList;
    FInfoAttrBuf attrBuf;

    char *path = [filePath cStringUsingEncoding: NSUTF8StringEncoding];

    memset(&attrList, 0, sizeof(attrList));
    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
    attrList.commonattr  = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO;

    int err = getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0);
    if (err != 0)
        return errno;

    // attrBuf.objType = (VREG | VDIR), inconsequential for invisibility

    UInt16 flags = CFSwapInt16BigToHost(attrBuf.finderInfo.file.info.finderFlags);

    if (isInvisible)
        flags |= kIsInvisible;
    else
        flags &= (~kIsInvisible);

    attrBuf.finderInfo.file.info.finderFlags = CFSwapInt16HostToBig(flags);

    attrList.commonattr = ATTR_CMN_FNDRINFO;
    err = setattrlist(path, &attrList, attrBuf.finderInfo.rawBytes, sizeof(attrBuf.finderInfo.rawBytes), 0);

    return err;
}

I modified this code from the answer to this question, you may find more helpful information there: How to make a file invisible in Finder using objective-c

I have not tested this code but it should work. In fact, it is possible the code is unnecessary and just saving the file with a dot in front of the filename will work.

If you have administrator privileges you can execute a sudo chmod on the file and set it to read only if you want, but you shouldn't make your app ask the user for their password.




回答6:


This solution worked for me very well. Try this: https://github.com/nielsmouthaan/SecureNSUserDefaults. It will store encrypted bool/string/float/integer in your UserDefaults file. Hopefully this is what you want. Make sure you download and add CocoaSecurity (See the SecureNSUserDefaults GitHub page for the download link) to your project. CocoaSecurity is a required element of SecureNSUSerDefaults, so you do not need to import it into any of your files. You must also download Base64, which is a required element of CocoaSecurity. You also need to add Base64 to your project, but do not need to import it into any of your files.

USAGE

Import the header file anywhere you want to use the encryption method.

#import <SecureNSUserDefaults/NSUserDefaults+SecureAdditions.h>

Then, set an encryption key, probably in your awakeFromNib method:

[[NSUserDefaults standardUserDefaults] setSecret:@"your_secret_goes_here"];

I recommend generating a random string of numbers and letters. Then, you must store the information in your UserDefaults file.

[[NSUserDefaults standardUserDefaults]
    setSecretObject:@"your_secret_object"
    forKey:@"the_key_your_object_will be_stored_under"];

To retrieve the string, use this method:

NSString *retrievedData = [[NSUserDefaults standardUserDefaults]     
    secretStringForKey:@"the_key_your_object_will be_stored_under"];

I hope this helps!



来源:https://stackoverflow.com/questions/3475295/how-do-i-store-data-securely-with-objective-c-mac-cocoa-dev

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