zoukankan      html  css  js  c++  java
  • Security编程指南

    保护app的管理数据的安全性,控制app的访问权限,提供丰富的数据加密,证书创建相关的API.

    概述

    使用Security.framework保护信息,建立信任,控制软件的访问。总的来说,安全服务支持这些目标:
    - 建立用户身份(身份验证),然后有选择地授予对资源的访问权(授权)
    - 加密数据,包括磁盘上的数据和网络连接中的移动数据
    - 确保为特定目的执行的代码的有效性。

    如图1所示,您还可以使用较低级别的加密资源来创建新的安全服务。加密是困难的,而且错误的成本通常很高,因此实现自己的加密解决方案很少是一个好主意。当你需要在你的应用中加密时,依赖安全框架。

    注意事项:

    • 始终使用满足您需求的最高级别API, Security.Framework并不总是您的最佳选择。例如,要进行安全的网络通信,首先考虑基础框架的URL加载系统,它建立在安全框架之上。只有当你的应用程序需要对安全协议函数进行较低级别的访问时,你才会直接使用安全传输API。

    密码填充

    提供自动密码登录,和三方密码登录,通过人脸识别和指纹验证,简化登录的步骤。此外密码还能通过iCloud Keychain在用户设备上安全地同步这些凭证。

    • 密码自动填充简化了iOS应用程序和网页的登录和帐户创建任务。只需点击几下,用户就可以创建并保存新密码或登录到现有帐户。用户甚至不需要知道他们的密码;系统处理一切。这种便利性增加了用户完成你的应用程序的注册过程并更快地开始使用你的应用程序的可能性。此外,通过鼓励用户选择唯一的强密码,可以提高应用程序的安全性。
    • 默认情况下,密码自动填充会将用户的登录凭据保存在当前iOS设备上iOS可以使用iCloud Keychain在用户的设备上安全地同步这些凭证密码自动填充仅为应用程序的关联域推荐凭据,用户在访问这些凭据之前必须使用人脸ID或触摸ID进行身份验证。有关隐私和安全的更多信息。
    • 密码自动填充还提供来自实现凭据提供程序扩展的第三方密码管理器的凭据。有关凭据提供程序扩展的更多信息,请参阅AuthenticationServices框架。

    启用密码自动填充: 密码自动填充使用启发式来确定用户何时登录或创建新密码,并自动提供密码快速类型栏。在大多数应用程序中,这些启发式方法为用户提供了一些密码自动填充支持,即使这些应用程序尚未更新以支持自动填充。但是,要提供最佳用户体验并确保应用程序完全支持密码自动填充,请执行以下步骤:

    • 设置Assoicate Domains
    • 在文本输入框中设置自动填充类型

      • iOS填充类型
      • 自动填充当前的密码示例,textContentType设置为.password类型;如果是第一次创建用户则需设置为.newPassword以便保存密码到keyChain
      • 特别注意,自定如的输入视图,系统不支持.

      • Web填充类型

    共享Web凭据

    • 在iOS应用程序和其网站对应应用程序之间共享凭据。
    • 密码自动填充简化了登录到域中的web服务;但是,如果需要登录到第三方服务,请改用ASWebAuthenticationSession,它在用户尚未登录时支持密码自动填充。
    • Security.SecSharedCredentialsAPI提供了存储和请求基于密码的共享凭据的函数用户在Safari中登录网站时,通常会将用户名和密码保存在iCloud钥匙链中。稍后,他们可能会运行来自同一开发人员的本机应用程序来访问同一个帐户。通过共享的web凭据,应用程序可以访问为网站存储的凭据,而无需用户重新输入用户名和密码。用户还可以在应用程序中创建新帐户、更新密码或删除帐户。然后保存这些更改并由Safari使用。
    • 访问共享的web凭据需要来自应用程序、网站和用户的权限。
    • 实现步骤:

      • 配置Associate Domains
      • 管理共享证书凭证: 使用共享web凭据为用户创建无缝体验。
        • 在许多常见情况下,您可能希望使用共享web凭据。本文包括四个方面:
          1. 登录到远程服务器
          2. 在应用程序中创建用户帐户
          3. 更改用户密码
          4. 删除用户帐户
      • 使用共享的web凭据时,需要向该过程添加两个步骤。如前所述,首先检查用户的凭据是否存储在密钥链中。如果找不到用户的凭据,请检查共享的web凭据。如果仍然找不到任何凭据,或者用户拒绝使用共享凭据,则必须提示用户输入其名称和密码。尝试让用户登录,如果登录成功,请将凭据保存到密钥链和共享web凭据中。这样可以确保用户可以访问Safari中以及应用程序中的凭据。此工作流如图2所示。
      • 注意: 使系统在共享web凭据中找到匹配项,用户仍然可以拒绝使用这些凭据。这将导致检查共享web凭据失败。因此,您必须始终有一个回退,提示用户输入其名称和密码。
      • 不要将共享web凭据用作安全用户凭据的主存储。相反,请将用户的凭据保存在密钥链中,并且仅当在密钥链中找不到登录凭据时使用共享的web凭据。

          SecRequestSharedWebCredential(NULL, NULL, ^(CFArrayRef credentials, CFErrorRef error) {
        if (error != NULL) {
        
            // If an error occurs, handle the error here.
        
            [self handleError:error];
        
            return;
        
        }
        
        BOOL success = NO;
        
        CFStringRef server = NULL;
        
        CFStringRef userName = NULL;
        
        CFStringRef password = NULL;
        
        // If credentials are found, use them.
        
        if (CFArrayGetCount(credentials) > 0) {
        
            // There will only ever be one credential dictionary
        
            CFDictionaryRef credentialDict =
        
            CFArrayGetValueAtIndex(credentials, 0);
        
            server = CFDictionaryGetValue(credentialDict, kSecAttrServer);
        
            userName = CFDictionaryGetValue(credentialDict, kSecAttrAccount);
        
            password = CFDictionaryGetValue(credentialDict, kSecSharedPassword);
        
            // Attempt to log in, 只有当用户选择正确的用户名密码才有效
        
            success = [self logIntoServer:server user:userName password:password];
        
        }
        
        if (!success) { //永远不要忘记错误情况提示
        
            [self promptForUserNameAndPassword];
        
        } else {
        
            [self saveCredentialsToKeychainForServer: server user:userName password:password];
        
        }
        
        });
        

          

        • 在应用程序中创建用户帐户: 如果用户可以在应用程序中创建新帐户,则应将用户名和密码保存到共享的web凭据中。这样,用户可以轻松地从Safari访问帐户,也可以从应用程序中访问帐户。可以使用SecAddSharedWebCredential函数将用户名和密码保存到共享web凭据中,如图所示。

          SecAddSharedWebCredential(domain, name, password, ^(CFErrorRef error) {
          if (error != NULL) {
          // Handle the error here...
          return;
          }
          // The credentials have been successfully saved.
          });
      • 更改密码: 同上面创建密码的API调用一样.通过SecAddSharedWebCredential函数生成

      • 删除密码:

    授权服务

    访问操作系统的限制区域,并控制对macOS应用程序特定功能的访问。

    Security.Authorization相关的API便于对操作系统的受限区域进行访问控制,并允许您限制用户对macOS应用程序中特定功能的访问。在以下情况下使用授权服务:

    • 限制访问自己工具的软件
    • 调用系统工具的应用程序
    • 安装特权工具或要求访问操作系统限制区域的软件安装程序
      • 如图1所示,Security Server是运行在操作系统中的守护进程,,它提供各种安全协议的可信实现,包括授权计算。反过来,安全服务器依赖于安全代理在需要身份验证时与用户交互。因此,应用程序可以验证凭据(用户名和密码),而不必直接访问它们。此授权过程还允许将来更改身份验证方式(例如添加Touch ID),而无需修改应用程序

    插件授权

    • 通过创建可以参与授权决策的插件来扩展授权服务API。

    会话安全处理

    • 在macOS中管理登录、授权和安全会话。

    钥匙链服务(KeyChain Service重点)

    • 计算机中的用户总有一些自己的小秘密需要安全存储。例如,大多数人管理大量的在线账户。记住每个密码的复杂、唯一是不可能的,但是写下来既不安全又乏味。用户通常通过跨多个帐户回收简单密码来应对这种情况,这也是不安全的。
    • keychain services API通过给应用程序提供一种机制,将小部分用户数据存储在一个称为密钥链的加密数据库中,从而帮助您解决这个问题。当您安全地记住密码时,您可以自由地让用户选择一个复杂的密码。
    • 密钥链不限于密码,如图1所示。您可以存储用户明确关心的其他机密,例如信用卡信息,甚至是短便笺。您还可以存储用户需要但可能不知道的项目。例如,使用证书、密钥和信任服务管理的加密密钥和证书使用户能够参与安全通信并与其他用户和设备建立信任。你也可以用钥匙链来储存这些物品,如下图简单介绍了4种不同类型的加密数据。
    • KeyChain的工作流程
      通过KeyChainServices提供的API,将用户的Data按照指定的Attributes指定的规则加密生成一个KeyChainItem并存储到钥匙串种

    防止不安全的网络连接

    • 通过依赖应用传输安全性在应用程序中实施安全网络链接。
    • 在水果平台上,App Transport security(ATS)的网络安全功能提高了所有应用程序和应用程序扩展的隐私和数据完整性。它通过使用可靠的证书和密码要求由传输层安全(TLS)协议保护应用程序建立的网络连接。ATS阻止不满足最低安全要求的连接

    • ATS不适用于你的应用程序对低级网络接口(如网络框架或CFNetwork)的调用。在这些情况下,您负责确保连接的安全性。你可以用这种方式建立一个安全的连接,但是错误很容易犯,而且代价高昂。通常最安全的方法是依赖URLoadingSystem

    • 确保网络服务器满足最低要求:

      • 安全服务器使用X.509数字证书建立其身份。连接客户端检查此证书以执行默认服务器信任评估,其中包括检查证书:

        • 有完整的数字签名,表明证书没有被篡改。
        • 没有过期
        • 具有与服务器的DNS名称匹配的名称。(有时也可以通过匹配父级域名)
        • 由另一个有效证书签名,该证书由另一个证书依次签名,等等,返回到可信锚证书,该证书必须由证书颁发机构(CA)颁发。锚证书必须是客户端操作系统的一部分,如iOS中可用的受信任根证书列表所示,或由用户或系统管理员安装在客户端上。
          • iOS中可用的受信任根证书的列表:(信任存储包含预装有iOS、macOS、watchOS和tvOS的受信任根证书),证书查询地址
        • ATS需要所有这些功能,然后提供扩展的安全检查:
          • 服务器证书必须使用至少2048位的Rivest Shamir AdlemanRSA密钥或至少256位的椭圆曲线加密ECC密钥进行签名。
          • 两种加密方式对比,以下来自百度百科介绍
          • 由上面可以看出: RSA的数据原理相比ECC简单,ECC加密比RSA强, RSA时由两个大的素数(质数)的乘积公开作为加密密钥,所以它的安全性依赖大数分解。ECC基于椭圆曲线上离散对数计算问题的算法生成,加密性更强,优点如下.
        • 证书必须使用安全哈希算法2(SHA-2),摘要长度(有时称为指纹)至少为256位(即SHA-256或更大)。
        • 连接必须使用传输层安全(TLS)协议版本1.2或更高版本。
        • 必须使用AES-128或AES-256对称密码交换数据,如果需要对银行卡密码之类的加密,通常需先进行sha512加盐和RSA再次加密,确保用户密码不被app明文传输.
        • 该链路必须通过椭圆曲线Diffie-Hellman临时密钥交换来支持完全前向保密(PFS)。
      • ATS是基于Https进行数据通信的,而Https是建立在TSL(Transport Layer Security)基础之上的,TSL协议采用主从式架构模型,用于在两个应用程序间透过网络创建起安全的连线,防止在交换数据时受到窃听及篡改, TSL前身是SSL协议,IETF将SSL(Secure Sockets Layer,安全套接字协议)进行标准化,1999年公布第一版TLS标准文件..

      • SSL协议未于TCP/IP协议与各种协议之间,为数据通讯提供支持 SSL协议可分为两层:

        • SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装压缩加密等基本功能的支持。
        • SSL握手协议(SSL Handshake Protocol)它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等
      • NSURLSession会自动为您处理服务器信任评估,但允许您自定义此过程,例如,将信任扩展到应用程序中嵌入的自签名证书,或绕过证书过期。也可以通过重写URLSession:didReceiveChallenge:completionHandler:.来自己实现对服务器证书的认证

        • 创建长期服务器身份验证策略:

          • 将服务器的凭据与公钥进行比较,而不是在应用程序包中存储单个证书。这将允许您为同一密钥重新颁发证书并更新服务器,而不需要更新应用程序。
          • 比较颁发证书颁发机构(CA)的密钥,而不是使用叶密钥。你可以用同样的方式部署新的证书。
          • 使用一组密钥或CA,以便可以更优雅地旋转服务器凭据。
        • 具体验证方式,可以参考AFNetworkingAlamoFire安全验证,默认验证证书的policy和Domain是否正确.

          • CompositeTrustEvaluator: 使用提供的计算器验证服务器信任。只有当所有评估者认为它是有效的。
          • PublicKeysTrustEvaluator: 验证公钥是否正确,此前也需要验证证书host,policy
          • PinnedCertificatesTrustEvaluator: 使用固定的证书验证服务器信任。服务器信任被认为是有效的,如果
          • RevocationTrustEvaluator: 使用默认和已吊销的服务器信任评估的计算器,iOS 10.1推出,开发者可以通过吊销证书来测试服务器的有效性。

    服务签名

    • 代码签名是一种macOS安全技术,用于证明应用程序是由您创建的一旦应用程序被签名,系统可以检测到应用程序的任何更改,无论更改是意外引入的还是由恶意代码引起的。您可以控制签名代码如何加载签名插件和其他签名代码,而不会使宿主代码或来宾(动态加载)代码的签名失效。 可以参考Code Signing Guide中的签名流程,通过私钥进行签名,公钥进行验签。 - 上图是一个最基本的数据签名文件,
      • 首先会通过Hash散裂生成消息摘要
      • 然后通过私钥进行加密(这里需要通过Mac生成密钥对)生成数字签名
      • 由于数字签名是基于两种互补运算来实现的,所以通过我们的公钥就能对签名的数据进行验签名。
      • 最后将生成数字签名(Digital signature),Data(原始数据),以及上面第二个步骤生密钥对中的公钥证书一起打包,这个打包文件就是我们最终对原始Data的签名后的所有数据
    • 接收放拿到这个打包文件之后利用里面的公钥证书进行验签就知道我们的原始数据有没有被更改,它与我们的数据加密和解密过程正好是相反的。
    • 同理我们就很容易理解App的签名流程了,Code Signing Guide中也详细介绍了app签名的流程。可以参考一位博主的这篇文章写的比较详细,有图解.
      • 发布到AppStore签名和解签流程比较少,iPA包直接传递到苹果服务器进行签名,通过Apple后台的私钥进行加密,它的公钥会自动安装在用户设备上,所以用户下载App的时候直接就能进行使用设备内置的Apple公钥进行解密.
      • 但是本地调安装到手机则无法满足通过苹果后台进行签名的步骤了,所以需要开发者自己再本地电脑进行签名,(这里不用Mac后台私钥进行签名是为了防止这个iPA包在所有设备都能安装,以免造成安全访问),但是又为了保证苹果对安装有控制权,所以采用了双层签名机制来实现,其实就是部分签名,既能保证部分内容要经过苹果验证,也避免了所有内通都能通过苹果验证而造成的安全问题。具体实现如下:
        • 通过开发者本机生成公钥和私钥,私钥对App进行签名,公钥使用Apple后台的私钥进行加密,将这两个加签后的文件打包成ipa
        • 在安装这个ipa时,首先利用iOS设备的公钥(Mac服务器私钥对应的公钥)对开发者自己的公钥进行验签; 然后再利用开发者自己的公钥对App进行验签,都通过之后才能安装。
        • 上面的流程只是解决了只允许经过苹果允许才能安装,这样意味着只要ipa包传给别人都能安装了,跳过AppStore都能发布,这显示时苹果不能允许的,影响到它的收入了,同时也给免费账号钻了控制,如是苹果又出了个新东西,叫做描述文件. 描述文件包含了AppId,设备ID,Enitilements,将描述文件和ipa文件放在一起,并通过Apple私钥对描述文件进行签名,这样在安装App的时候用描述文件的appIddeviceceId就能够对安装的设备进行限制了。
          ## 分发前对macOS软件进行公证
          通过提交给苹果公司公证,让用户对你的macOS软件更有信心。
    • 具体来讲就是经过苹果认证的软件,在Mac电脑安装后就不会显示未知来源的开发者,权威机构验证给用户一点信息,这也是打击盗版和木马病毒植入的一种手段,要认证开发者就不能用软件干违法的事了

    准备应用程序以使用指针身份验证

    • arm64e体系结构引入指针认证码(PACs)来检测和防止内存中指针的意外更改。添加指针身份验证对大多数应用程序是透明的,因为编译器管理进程。例如,在很少的情况下,如果应用程序直接操纵堆栈,或者如果您在C++和ObjuleC++之间传递指针,那么您可能需要调整代码以与PACS一起工作。虽然您还不能发布arm64e二进制文件,但您可以在开发过程中使用它们来测试应用程序,为它们成为Xcode标准构建过程的一部分做好准备。
    • 指针身份验证的工作原理是,在存储指针之前,提供一个特殊的CPU指令,将加密签名或PAC添加到指针的未使用的高位。另一条指令在从内存中读回指针后删除并验证签名。写入和读取之间的存储值的任何更改都会使签名无效。CPU将验证失败解释为内存损坏,并在指针中设置一个高阶位,使指针无效并导致应用程序崩溃。
    • 指针异常Exception Subtype: KERN_INVALID_ADDRESS at 0x0040000105394398 -> 0x0000000105394398 (possible pointer authentication failure)
      ## App Sandbox
    • 限制对macOS应用程序中系统资源和用户数据的访问,以防止应用程序受到破坏。
    • com.apple.security.app-sandbox,: 一个布尔值,指示应用程序是否可以使用访问控制技术来包含对系统和用户数据的损坏(如果应用程序被破坏)。
    • AppSandbox是一种在MACOS中提供的访问控制技术,在内核级执行。它被设计成在应用程序被破坏的情况下包含对系统和用户数据的破坏通过Mac应用商店分发的应用程序必须采用应用程序沙盒。在Mac应用商店外使用开发者ID签名和分发的应用程序也可以(在大多数情况下应该)使用应用程序沙盒。
      • App Sandbox使您能够描述应用程序如何与系统交互。然后,系统会授予你的应用程序完成任务所需的访问权限,而不是更多。
      • Appsandbox允许用户通过打开和保存对话框、拖放和其他熟悉的用户交互,透明地授予你的应 用额外的访问权限。
      • 在iOS程序中,Home文件夹就是应用程序的沙盒,如下所示
      • 完整路径如下'/Library/Developer/CoreSimulator/Devices/31CAD1CF-C9C0-41B0-8FE4-0D072F0C1D48/data/Containers/Data/Application/E0F8D322-1B4C-4C48-86B7-E583A228B0E6',
      • 分别为Documents,Library,SystemData,tmp
        • Documents: 文档目录,主要记录需要持久保存的用户重要文档,iTunes备份和恢复的时候,会包括此目录
        • Library: 包括CachesPreferences,Preferences包含应用程序的偏好设置文件,由系统自动创建,如第一次安装时系统就会自动生成一个默认plist文件,用户记录app的默认行为。Caches用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
        • tmp 目录:这个目录用于存放临时文件,系统会不定期删除这里的文件。
        • App.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。(Xcode 6以后似乎.app不保存在沙盒中)

    参考链接

    AppSandBox
    X.509
    Apple内置证书)
    RSA
    ECC
    Code sign Guide

  • 相关阅读:
    5.16欢乐赛
    卢卡斯定理
    noip2017 宝藏
    [JSOI2009]计数问题
    HDU 1160 FatMouse's Speed
    HDU 1260 Tickets
    HDU 1176 免费馅饼
    HDU 1114 Piggy-Bank
    HDU 1074 Doing Homework
    HDU 1069 Monkey and Banana
  • 原文地址:https://www.cnblogs.com/wwoo/p/security-bian-cheng-zhi-nan.html
Copyright © 2011-2022 走看看