美文网首页
8.安全服务

8.安全服务

作者: LucXion | 来源:发表于2021-10-29 18:43 被阅读0次

沙盒

  • .app捆绑目录(.app bundle),Xcode最终构建出来并复制到设备上的包。内容全部经过数字签名,无法修改,包含开发者Resource目录。要修改作为捆绑安装的文件,需要先将它复制到其他地方,通常是Library中。

  • Document,用户可见数据,可以通过设置info.plist的UIFileSharingEnable,将文件可以通过共享出现在桌面上。

  • Library,不能被用户直接看到的文件,会自动备份,可以通过NSURL setResourceValue:forKey:error:方法为文件加上NSURLIsExcluedFromBackupKey.

    • Library/Cache,不会被备份,但会在应用升级中保留下来,可以将不想复制到桌面的大部分内容保存在这里。
  • temp,不会备份,也不会在升级的过程中保留。系统可能在程序不运行时删除temp。

iTunes对如何处理和这四个顶级目录同级的其他文件并没有明确说明。说以为了更好的组织,新建的文件应该放在这四个顶级目录下

公钥和私钥

  • 服务器生成公钥和私钥,并把公钥公布给客户端

  • 客户端通过公钥对数据进行加密,并发送给服务器,服务器拿到数据后通过私钥解密获取信息, 外界即便截获数据,但没有对应的私钥进行解密,那么就无法读取信息。

  • 服务器 数字签名:用hash函数生成摘要,并用私钥进行加密。

  • 客户端通过私钥对数字签名进行解密,验证服务器。对信息使用hash函数,与摘要信息对比,判断信息是否被修改。

  • 数字证书:服务器公钥+证书中心私钥共同生成数字证书,同数字签名一块发送给客户端。客户端通过证书中心公钥对数字证书解密获取服务器公钥。

购买商业证书来加密应用和服务器之间的网络协议并不能提高安全性。商业证书只对由浏览器或其他不可控软件访问的网站有用。自行生成证书并将证书放在应用中甚至比商业证书还要安全。

检验证书有效性

证书包含有关其所含公钥的大量元数据,公钥只是一个很大的数字,自身并没有意义,元数据赋予了数字的实际含义。有效性指的是证书包含的元数据一致且适用请求。

元数据最重要的就是主题(subject),主题就是完全限制域名,有效性的第一步就是做名称匹配。有些服务器带的主题是类似 *.example.com的通配符证书,iOS会接收这些证书,证书使用的是字符串匹配,因此在某些情况下还是需要做处理,比如通过IP地址连接服务器。

/*
 通过IP地址连接 encrypted.google.com 服务器,我们收到的证书主题为 *.google.com,下面代码可以接收所有主题名称含google.com的所有受信任证书。
 需要加入 Security.framework
 */
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    NSURLProtectionSpace *protSpace = challenge.protectionSpace;
    SecTrustRef trust = protSpace.serverTrust;
    SecTrustResultType result = kSecTrustResultFatalTrustFailure;
    
    // 通过 SecTrustEvaluate 得到一个可恢复错误
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess && result == kSecTrustResultRecoverableTrustFailure) {
        //证书无效,但开发人员可以接受,可能已过期、不匹配、缺乏可信度(自签证书)
        SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0);
        CFStringRef subject = SecCertificateCopySubjectSummary(cert);
        
        NSLog(@"Trying to access %@. Got %@. ",protSpace.host,subject);
        // 判断证书主题是否足够接近
        CFRange range = CFStringFind(subject, CFSTR(".google.com"), kCFCompareAnchored||kCFCompareBackwards);
        if (range.location != kCFNotFound) {
            // 将证书当做一个简单的 X.509证书来重新测试,而不是当做SSL握手的一部分(这种情况在测试时一般会忽略主机名)
            status = RNSecTrustEvaluateAsX509(trust, &result);
        }
        CFRelease(subject);
    }
    if (status == errSecSuccess) {
        switch (result) {
            case kSecTrustResultInvalid:// 验证过程无法完成,很可能是开发人员代码有问题
            case kSecTrustResultDeny:// 证书有效,但用户明确拒绝
            case kSecTrustResultRecoverableTrustFailure:
            case kSecTrustResultFatalTrustFailure://证书有问题或已损坏
            case kSecTrustResultOtherError:// 验证过程无法完成,可能是苹果问题
                NSLog(@"failing due to result :%u",result);
                [challenge.sender cancelAuthenticationChallenge:challenge];
                break;
                
            case kSecTrustResultProceed://证书有效,用户明确接受
                //证书有效,但用户没有明确的拒绝或接受,开发人员接受就可以了
            case kSecTrustResultUnspecified:{
                
                NSLog(@"successing with result :%u",result);
                NSURLCredential *cred;
                cred = [NSURLCredential credentialForTrust:trust];
                [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
            }
                break;
            default:
                NSAssert(NO, @"unexpected result from trust evalution:%u",result);
                break;
        }
    }else {
        NSLog(@"Complete Failure with code %d",(int)status);
        [challenge.sender cancelAuthenticationChallenge:challenge];
    }
}


/// 复制并创建一个新的 trust,使用更简单的X.509策略,只检查有效性和可信度,不会像原来的SSL握手一样验证主机名
/// @param trust
/// @param result
static OSStatus RNSecTrustEvaluateAsX509(SecTrustRef trust,SecTrustResultType *result){
    OSStatus status = errSecSuccess;
    SecPolicyRef policy = SecPolicyCreateBasicX509();
    
    SecTrustRef newTrust;
    CFIndex numOfCerts = SecTrustGetCertificateCount(trust);
    NSMutableArray *certs = [NSMutableArray array];
    for (int i = 0; i < numOfCerts; i++) {
        SecCertificateRef cert;
        cert = SecTrustGetCertificateAtIndex(trust, i);
        [certs addObject:(__bridge id _Nonnull)(cert)];
    }
    status = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)(certs), policy, &newTrust);
    
    if (status == errSecSuccess) {
        status = SecTrustEvaluate(newTrust, result);
    }
    CFRelease(policy);
    CFRelease(newTrust);
    return status;
}

// 证书如果因过期而无效,可以通过SecTrustSetVerifyDate指定一个任意时间来测试该证书

#pragma mark- NSURLConnectionDelegate
//- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//    // 可以决定是否通过该服务器的认证,如果需要通过,则需要提供凭据(credential)
//    SecTrustRef trust = challenge.protectionSpace.serverTrust;
//    NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
//    // 连接到持有非损坏证书的任何服务器来进行验证,不管证书是否有效或受信任
//    [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
//}

判断证书的可信度

要想证书受信任,它必须是由trust对象的锚证书列表中的某个证书签名。锚证书 指系统明确信任的证书。

证书是自行生成的,你可以将公钥添加到应用中,并配置trust对象只接受该证书或由它签发的证书。

测试:可以通过钥匙串创建一个自签名的根证书

将该证书添加到钥匙串中,再在钥匙串中选中并拖到桌面导出,该文件只包含公钥。默认情况下,钥匙串不会导出私钥。将这个公钥拖入到工程中。测试收到的证书是由你的证书签名的:

//    NSURLAuthenticationChallenge *)challenge
    NSURLProtectionSpace *protSpace = challenge.protectionSpace;
    SecTrustRef trust = protSpace.serverTrust; // 需要验证的 trust对象
    NSError *error;
    NSString *path = [[NSBundle mainBundle] pathForResource:@"MyCert" ofType:@"cer"];
    NSData *cerData = [NSData dataWithContentsOfFile:path options:0 error:&error];
    
    SecCertificateRef certificate;
    certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerData);
    NSArray *certs = @[(__bridge  id)certificate];
    SecTrustSetAnchorCertificates(trust, (__bridge  CFArrayRef)certs);
    
    CFRelease(certificate);

文件保护

    NSData *data;
    NSString *path;
    NSError *writeError;
    
    // 创建一个受保护的文件
    [data writeToFile:path options:NSDataWritingFileProtectionComplete error:&writeError] || [data writeToFile:path options:NSDataWritingFileProtectionCompleteUnlessOpen error:&writeError];
    /*
     NSDataWritingFileProtectionNone:未受保护,可随时读写
     NSDataWritingFileProtectionComplete:最高级别保护,锁屏10s后开启,会导致后台运行时无法读写文件
     NSDataWritingFileProtectionCompleteUnlessOpen:锁屏10s后开启保护,除非文件处于打开状态,如果处于打开状态允许继续访问
     NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication:设备启动、用户首次解锁该设备时受保护,之后文件就不受保护了,直到设备重启
     */

/// 提高文件保护级别
/// @param dir <#dir description#>
/// @param error <#error description#>
- (void)upgradeFilesInDirectory:(NSString*)dir error:(NSError **)error {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:dir];
    for (NSString *path in dirEnum) {
        // 目录下的文件
        NSDictionary *attrs = [dirEnum fileAttributes];
        // 如果不是最高保护级别,那么重新设置保护级别
        if (![[attrs objectForKey:NSFileProtectionKey] isEqual:NSFileProtectionComplete]) {
            // 如果有别的属性,注意迁移
            attrs = @{NSFileProtectionKey:NSFileProtectionComplete};
            [fileManager setAttributes:attrs ofItemAtPath:path error:error];
        }
    }
}

// 判断受保护数据是否可用 
#pragma mark- UIApplicationDelegate
- (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application {
}
- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application {
}

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(fileProtectChange) name:UIApplicationProtectedDataDidBecomeAvailable object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(fileProtectChange) name:UIApplicationProtectedDataWillBecomeUnavailable object:nil];

[[UIApplication sharedApplication] isProtectedDataAvailable];

访问组

跨应用凭据共享方案

// 目标:应用B 通过访问组获取 应用A存储的凭据(如密码)
// 1.应用A中存凭据
/// 在运行时获取应用前缀,确保前缀有效
- (NSString*)bundleSeedID {
    // 创建一个钥匙串条目
    NSDictionary *query = @{
        (__bridge  id)kSecClass:(__bridge id)kSecClassGenericPassword,
        (__bridge  id)kSecAttrAccount:@"BundleSeedIDQuery",
        (__bridge id)kSecAttrService:@"",
        (__bridge id)kSecReturnAttributes:(id)kCFBooleanTrue
    };
    
    CFDictionaryRef result = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFTypeRef)query, (CFTypeRef *)&result);
    
    if (status == errSecItemNotFound) {
        status = SecItemAdd((__bridge CFTypeRef)query, (CFTypeRef *)&result);
    }
    if (status != errSecSuccess) {
        return nil;
    }
    // 检查它被分配到了哪个访问组
    NSString *accessGroup = CFDictionaryGetValue(result, kSecAttrAccessGroup);
    NSArray *components = [accessGroup componentsSeparatedByString:@"."];
    NSString *bundleSeedID = components.firstObject;
    CFRelease(result);
    
    return bundleSeedID;
}

// 存
 NSString *accessgroup = [NSString stringWithFormat:@"%@.%@",[self bundleSeedID],@"One"];
 [SGKeychain setPassword:@"pass" username:@"name" serviceName:@"service" accessGroup:accessgroup updateExisting:YES error:nil];

// B应用中,配置keychain Share
// Signing&Capabilities   添加 Keychain Sharing,加入应用A的访问组
// 取
NSString *accessgroup = [NSString stringWithFormat:@"%@.%@",[self bundleSeedID],@"One"];
    NSString *password = [SGKeychain passwordForUsername:@"name" serviceName:@"service" accessGroup:accessgroup error:nil];

相关文章

  • 8.安全服务

    沙盒 .app捆绑目录(.app bundle),Xcode最终构建出来并复制到设备上的包。内容全部经过数字签名,...

  • 信息安全服务资质介绍

    今天小编给大家普及一下信息安全服务都有哪些资质? 信息安全服务资质是信息安全服务机构提供安全服务的一种资格,包括法...

  • 02-02-07 网络安全攻防

    OSI安全体系结构OSI安全体系结构定义了系统应当提供的五类安全服务,以及提供这些服务的八类安全机制;五类安全服务...

  • 中标新闻|某大型互联网集团云安全咨询服务项目

    谷安天下将承担该大型互联网集团云安全类服务,包括云安全运维服务、等保咨询服务、风险评估服务、数据安全治理服务、IT...

  • (11) 单例设计模式(2)

    7. 懒汉式(线程安全,同步代码块) 8. 双重检查 8.1 代码实现 8.2 优缺点说明 Double-Chec...

  • web安全(web应用安全)

    摘自极客学院 甲方和乙方: 甲方:腾讯阿里等,需要安全服务的公司 乙方:提供安全服务、产品而服务型安全公司(绿盟、...

  • 8.线程安全策略

    一、不可变对象1.不可变对象需要满足的条件: 对象创建后其状态就不能修改 对象所有域都是final类型 对象是正确...

  • 微服务网关安全 | 微服务安全的挑战

    微服务安全面临的挑战 更多的入口点,更高的安全风险; 性能问题; 服务间通讯安全; 跨多个微服务的请求难移追踪; ...

  • 云安全服务

    • SecaaS,安全即服务 – 开放服务接口,唾手可得和更加简单的安全服务 – 按需申请和使用 – 提供配套的监...

  • 云 云

    绿盟云 自身是云服务 提供的是安全服务 用户在本地不必再架构安全系统(物理)以及部署运维,按需购买安全云服务即可(...

网友评论

      本文标题:8.安全服务

      本文链接:https://www.haomeiwen.com/subject/dyxwaltx.html