【问题标题】:How do I store data securely with objective C? (Mac/Cocoa Dev)如何使用 Objective C 安全地存储数据? (Mac/可可开发)
【发布时间】:2011-03-29 08:46:52
【问题描述】:

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

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

我对 NSUserDefaults standardUserDefaults 感到很困惑,但用户可以在 Library > Preferences 中轻松找到并编辑该数据。

【问题讨论】:

  • 将其存储在应用程序包中可能稍微难以让用户规避。这取决于您希望保护的效果如何。
  • 它一定很好,因为我不希望用户在试用期结束后能够使用该应用程序
  • 我只是在看 NSUserDefaults encodeObject:forKey:,也许它们就足够了?
  • @Daniel:问题在于用户可以删除所有默认值。
  • 不要更改应用程序包中的内容。它会破坏代码设计(这将阻止您使用安全框架和钥匙串的某些功能),并且通常它向用户表明某些东西正在篡改您的应用程序,例如恶意软件。

标签: objective-c trial


【解决方案1】:

我反对让它变得超级安全。我们曾经有一个服务器激活,但完全没有它。以下是一些原因:

  • 即使是最“安全”的存储方法也可能被破解
  • 即使是小众产品,也可能会出现破解,不管你的方法多么安全
  • 很少,非常昂贵,非常安全的方法。其他都被破解了
  • 这违背了公平和诚实的用户,使他们更难解决导致问题的问题
  • 如果用户确实破解了您的软件或绕过了您的安全措施,他也可能永远不会购买它
  • 80% 的用户甚至不知道首选项文件是什么
  • 95% 的用户不认为可以将其删除以延长试用期
  • 一种大量重置试用期的简单方法可以让您更轻松地为用户提供支持,无论出于何种原因,您都希望进行第二次试用
  • 信任用户是一个很好的卖点
  • 高级用户倾向于反对保护过多的软件

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

【讨论】:

  • 我同意,不要浪费太多资源让您的应用超级安全。黑客会找到绕过它的方法。
  • aquaticmac.com 是一个很好的安全解决方案。 aquaticmac.com/cocoa.php 在 NSData 上也有很好的扩展来进行加密。如果您想覆盖 %99 的用户,我建议使用具有明显名称的隐藏文件方法,即“.
【解决方案2】:

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

如上所述,在你的包中搞乱也是一个坏主意。这为您提供了三个基本选项。

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

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

3) 通过乱搞应用程序包或留下孤立文件来成为“坏公民”。如果您在后者中执行此操作,至少要确保它们被明确命名,以便它们与您的应用程序明显相关。

最终要记住的关键是您在用户的机器上没有安全措施。这是他们的。这意味着他们可以进行物理访问,这几乎可以消除任何阻止他们挖掘的企图。你也可以这样看:你的市场越有技术意识,你就越不可能比我们所有人都聪明,你的“安全”就会被破解。如果您正在为非技术受众设计,那么您可以发现,一般来说,他们不会费心破解它或寻找一个。

您可以将资源用于改进应用,或者让自己更好地了解人们在试用期过后没有使用它。其中一种可以增加您的销售额,而另一种则不会。

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

【讨论】:

    【解决方案3】:

    Allan Odgaard 有一个相当不错的writeup,介绍了如何使用 OpenSSL 生成/存储 Cocoa 软件的许可证密钥。可能值得一读。

    【讨论】:

      【解决方案4】:

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

      查看Common Crypto 摘要库。

      这将保护几乎所有临时用户。尽管黑客只要有足够的动机,就可以想办法规避。

      【讨论】:

        【解决方案5】:

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

        放置隐藏文件的好地方是用户文件夹(~/)底部的一个不起眼的文件,那里有很多不起眼的隐藏文件,所以很难知道哪个可以,哪个不可以删除。示例路径:~/.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;
        }
        

        我从这个问题的答案修改了这段代码,您可能会在那里找到更多有用的信息: How to make a file invisible in Finder using objective-c

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

        如果您有管理员权限,您可以对文件执行 sudo chmod 并在需要时将其设置为只读,但您不应让您的应用要求用户输入密码。

        【讨论】:

          【解决方案6】:

          这个解决方案非常适合我。试试这个:https://github.com/nielsmouthaan/SecureNSUserDefaults。它将加密的 bool/string/float/integer 存储在您的 UserDefaults 文件中。希望这是你想要的。确保下载并添加 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"];
          

          我希望这会有所帮助!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-10-14
            • 2012-02-01
            • 2016-05-09
            • 1970-01-01
            • 2022-11-11
            • 2023-04-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多