如何使用 Objective C 安全地存储数据? (Mac/可可开发)

发布于 2024-09-14 01:23:06 字数 188 浏览 4 评论 0原文

我正在尝试创建我的可可应用程序的试用部分。我已经设置了所有许可(包括密钥)等。

但我想知道如何存储例如用户第一次在安全的地方运行程序的时间,用户无法轻松找到它和/或编辑它。

我正在摆弄 NSUserDefaults standardUserDefaults,但用户可以轻松地在 Library > 中找到并编辑该数据。偏好。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我反对让它变得超级安全。我们曾经激活过服务器,但后来完全放弃了。以下是一些原因:

  • 即使是最“安全”的存储方法也可能被破解
  • 即使对于利基产品,也可能会开发出破解方法,无论您的方法多么安全,都没有办法解决
  • 。 很少有、非常昂贵、非常安全的方法。所有其他都已被破解
  • 它不利于公平和诚实的用户,使他们更难修复导致问题的问题
  • 如果用户确实破解了您的软件或规避了您的安全性,他也可能永远不会购买80
  • % 的用户甚至不知道首选项文件是什么
  • 95% 的用户不考虑删除它以延长试用期的可能性
  • 大规模重置试用期的简单方法 减轻您对出于任何原因想要进行第二次试用的用户的支持
  • 信任用户是一个很好的卖点
  • 高级用户往往会反对保护太多的软件

我很确定有一些例外,但极少数从这些想法中。我想说:不要在注册安全上浪费时间,而是给

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

给不了的爱 2024-09-21 01:23:06

您不能使用文件系统上的文件。任何想要摆弄/破解它的人都会足够聪明,知道如何通过基本的、标准的 OSX 功能来跟踪文件访问。所以添加的文件就出来了。不仅如此,在卸载应用程序时创建不删除的文件也是不好的行为。人们不应该在删除试用应用程序后消耗资源。

如上所述,乱搞你的包也是一个坏主意。这给您留下了三个基本选择。

1)不要太担心。使用使用标准位置和方法的基本过期系统。您仍然可以在存储的数据中使用加密,但要知道这也会被破坏。接受侵犯版权的情况,除非您的应用程序完全不受欢迎。

2)使用网络调用并在服务器上进行验证。这将要求应用程序始终能够访问您的服务才能运行。一般来说,这不是一个好主意。如果您的服务器宕机了怎么办?如果他们离线怎么办?如果您和他们之间发生网络问题怎么办?所有这些情况都会发生。当他们这样做时,你可能会失去客户,除非你的应用程序需要连接到已经运行的服务器(就像 Twitter 或 Facebook 那样)。

3) 乱搞应用程序包或留下孤立文件,成为“坏公民”。如果您这样做,至少要确保它们的名称清晰,以便它们与您的应用程序明显相关。

最后要记住的关键一点是,用户的计算机没有安全保障。这是他们的。这意味着他们可以进行物理访问,这几乎使任何阻止他们挖掘的尝试都无效。你也可以这样看:你的市场越注重技术,你就越不可能比我们所有人都聪明,你的“安全”被破解的可能性就越小。如果您正在为非技术受众进行设计,那么您可以想象,一般来说,他们不会费心去破解或寻找它。

您可以将资源用于改进应用程序,或者让自己对试用期过后不再使用该应用程序的人有更好的感觉。其中一种可以增加您的销售额,另一种则不会。

[编辑]
我还应该指出,破解这些东西的最常见(如果不是最常见)的方法之一是修改二进制文件。因此,通过捆绑清理来破坏代码签名,您实际上会向该方法开放自己,因为您将破坏您所拥有的更好的保护之一。大多数破解都涉及修改二进制文件,以便执行检查的例程始终返回成功的身份验证。

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.

静若繁花 2024-09-21 01:23:06

Allan Odgaard 有一篇相当不错的文章关于如何使用 OpenSSL 生成/存储 Cocoa 软件的许可证密钥。可能值得一读。

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.

浮生未歇 2024-09-21 01:23:06

如果必须,一种简单且常见的方法是使用嵌入在应用程序中的密钥来加密磁盘上包含敏感数据的文件。挑战在于如何确保密钥的安全。

查看常见加密< /a> 摘要库。

这将保护几乎所有临时用户。不过,只要有足够的动机,黑客就可以找到一种规避方法。

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.

绝影如岚 2024-09-21 01:23:06

尝试将名称以句点开头的文件存储在某个文件夹中,然后设置该文件的隐藏标志。

放置隐藏文件的好地方是用户文件夹 (~/) 底部的一个名称模糊的文件,那里有许多模糊的隐藏文件,因此很难知道哪些可以删除,哪些不能删除。示例路径:~/.xdarwinprofile 或听起来同样官方的东西。

这是一些应该可以隐藏文件的代码:

#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;
}

我根据这个问题的答案修改了这段代码,您可能会在那里找到更多有用的信息:
如何使用目标使文件在 Finder 中不可见-c

我还没有测试过这段代码,但它应该可以工作。事实上,该代码可能是不必要的,只需在文件名前面加一个点即可保存文件。

如果您具有管理员权限,则可以对文件执行 sudo chmod 并将其设置为只读(如果您愿意),但您不应该让您的应用程序询问用户的密码。

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.

情独悲 2024-09-21 01:23:06

这个解决方案对我来说非常有效。试试这个:https://github.com/nielsmouthaan/SecureNSUserDefaults。它将在您的 UserDefaults 文件中存储加密的 bool/string/float/integer。希望这就是您想要的。确保下载 CocoaSecurity 并将其添加到您的项目中(请参阅 SecureNSUserDefaults GitHub 页面获取下载链接)。 CocoaSecurity 是 SecureNSUSerDefaults 的必需元素,因此您无需将其导入到任何文件中。您还必须下载 Base64,这是 CocoaSecurity 的必需元素。您还需要将 Base64 添加到项目中,但不需要将其导入到任何文件中。

用法

头文件导入到您想要使用加密方法的任何位置。

#import <SecureNSUserDefaults/NSUserDefaults+SecureAdditions.h>

然后,设置加密密钥,可能在您的 awakeFromNib 方法中

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

我建议生成一个由数字和字母组成的随机字符串。
然后,您必须将信息存储在 UserDefaults 文件中。

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

要检索字符串,请使用以下方法:

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

我希望这会有所帮助!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文