0
点赞
收藏
分享

微信扫一扫

DTLS 苹果Network框架Object-C代码

老榆 2022-02-18 阅读 39

【前言】

        这只是之前闲着写了个demo,能连上github的go版本的带证书 DTLS服务端,并不保证完全正确,并不保证数据收发正常,思路仅供参考,具体请自行修改调试,仅测试到握手通过,其他的部分未测试,现在放上来供大家参考。

.m文件

#import <Foundation/Foundation.h>
#import <Network/Network.h>
#import "YHDTLSManager.h"



NSErrorDomain const ConnectError = @"连接异常";
NSErrorDomain const ReceiveError = @"接收数据异常";
NSErrorDomain const SendError = @"发送数据异常";

@interface YHDTLSManager()
@property (nonatomic, strong) nw_parameters_t params;
@property (nonatomic, strong) nw_connection_t connection;
@property (nonatomic, strong) dispatch_queue_t connectQueue;
@property (nonatomic, copy) DTLSDataHandle receiveData;
@end

@implementation YHDTLSManager

+(instancetype)shareinstance   {
    static YHDTLSManager * yhdtls;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        yhdtls = [[YHDTLSManager alloc] init];
    });
    return yhdtls;
}

-(void)setConnectInfoWithCertName:(NSString*)cert
{
    self.params = nw_parameters_create_secure_udp(^(nw_protocol_options_t  _Nonnull options) {
        sec_protocol_options_t option = nw_tls_copy_sec_protocol_options(options);
        NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]];
        CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(pkcs12data);
        CFStringRef password = CFSTR("12345678");
        const void *keys[] = { kSecImportExportPassphrase };
        const void *values[] = { password };
        CFDictionaryRef refoptions = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
        CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
        OSStatus securityError = SecPKCS12Import(inPKCS12Data, refoptions, &items);
        CFRelease(refoptions);
        CFRelease(password);
        CFRelease(inPKCS12Data);
        NSLog(@"securityError:%d",(int)securityError);
        if(securityError == errSecSuccess)
            NSLog(@"Success opening p12 certificate.");
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        sec_protocol_options_append_tls_ciphersuite(option, tls_ciphersuite_ECDHE_RSA_WITH_AES_256_CBC_SHA);
        sec_protocol_options_set_verify_block(option, ^(sec_protocol_metadata_t  _Nonnull metadata, sec_trust_t  _Nonnull trust_ref, sec_protocol_verify_complete_t  _Nonnull complete){
            SecTrustRef trust = sec_trust_copy_ref(trust_ref);
            struct __CFError *err;
            NSMutableArray *certificates = [NSMutableArray array];

            NSData *cerData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"check" ofType:@"cer"]];

            SecCertificateRef cerRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerData);
            if(cerRef != nil){
              [certificates addObject:(__bridge_transfer id)cerRef];
            }{
                NSLog(@"cerRef is nil");
            }
            SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)certificates);
            SecTrustSetAnchorCertificatesOnly(trust, false);
            if(!SecTrustEvaluateWithError(trust, &err)){
            NSLog(@"ERROR :%@",err);
                complete(true);
            }else{
            complete(true);
            };
        }, dispatch_get_main_queue());
        sec_protocol_options_set_tls_ocsp_enabled(option, FALSE);
    SecIdentityRef myIdent = (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                                                      kSecImportItemIdentity);

        sec_protocol_options_set_tls_false_start_enabled(option, TRUE);
        sec_protocol_options_set_peer_authentication_required(option, TRUE);
        sec_protocol_options_set_challenge_block(option, ^(sec_protocol_metadata_t metadata, sec_protocol_challenge_complete_t complete){
        complete(sec_identity_create(myIdent));
    }, self.connectQueue);
        sec_protocol_options_set_local_identity(option, sec_identity_create(myIdent));
        sec_protocol_options_set_min_tls_protocol_version(option, tls_protocol_version_DTLSv12);
        sec_protocol_options_set_max_tls_protocol_version(option, tls_protocol_version_DTLSv12);
    }, ^(nw_protocol_options_t  _Nonnull options) {
        NW_PARAMETERS_DEFAULT_CONFIGURATION;
    });
}
- (void)linkServerWithHost:(NSString *)host
                     port:(NSString *)port
                    queue:(dispatch_queue_t)queue{
    if (host == nil || [host isEqualToString:@""]) {
        return;
    }
    if (port == nil || [port isEqualToString:@""]) {
        return;
    }
    nw_endpoint_t endpoint = nw_endpoint_create_host([host UTF8String], [port UTF8String]);
    self.connection = nw_connection_create(endpoint, self.params);
    nw_connection_set_queue(self.connection, queue);
    nw_connection_start(self.connection);
}


- (void)disConnect   {
    dispatch_async(self.connectQueue, ^{
        nw_connection_cancel(self.connection);
    });
}

- (void)sendData:(NSData *)data
               complete:(DTLSSessionCompletedHandle)complete  {
    dispatch_data_t data_t = [self dispatchDataFromNsdata:data];
    nw_connection_send(self.connection, data_t, NW_CONNECTION_FINAL_MESSAGE_CONTEXT, true, ^(nw_error_t  _Nullable error) {
        NSError *nserror;
        if (error != nil) {
            nserror = [[NSError alloc] initWithDomain:SendError code:nw_error_get_error_code(error) userInfo:@{@"nw_connection_send: nw_error_get_error_domain": @(nw_error_get_error_domain(error))}];
        }
        NSLog(@"DTLS发送数据:%@",data);
        if (complete) {
            complete(nserror);
        }
    });
}

- (void)receiveData:(DTLSDataHandle)receiveHandle    {
    self.receiveData = receiveHandle;
    [self receiveMsg];
}



- (void)receiveMsg  {
    __weak typeof (self)weakSelf = self;
    nw_connection_receive_message(self.connection, ^(dispatch_data_t  _Nullable content, nw_content_context_t  _Nullable context, bool is_complete, nw_error_t  _Nullable error) {
        NSLog(@"DTLS接收数据:content=%@, context=%@, is_complete=%d, error=%@",content, context, is_complete, error);
        NSLog(@"DTLS接收数据:content=%@, context=%@, is_complete=%d, error=%@",content, context, is_complete, error);
        __strong typeof (weakSelf)strongSelf = weakSelf;
        if (error == nil && content != nil) {
            NSData *data = [strongSelf nsdataFromDispatchData:content];
            if (data != nil) {
                strongSelf.receiveData(data,nil);
                [self receiveMsg];
            } else {
                NSError *nserror = [[NSError alloc] initWithDomain:ReceiveError code:nw_error_get_error_code(error) userInfo:@{@"nw_connection_receive_message: nw_error_get_error_domain": @(nw_error_get_error_domain(error))}];
                if (strongSelf.receiveData) {
                    strongSelf.receiveData(nil, nserror);
                }
            }
        }else{
            NSError *nserror = [[NSError alloc] initWithDomain:ReceiveError code:nw_error_get_error_code(error) userInfo:@{@"nw_connection_receive_message: nw_error_get_error_domain": @(nw_error_get_error_domain(error))}];
            if (strongSelf.receiveData) {
                strongSelf.receiveData(nil, nserror);
            }
        }
    });
}

- (dispatch_data_t)dispatchDataFromNsdata:(NSData *)nsdata  {
    if (nsdata == nil) {
        return nil;
    }
    Byte byte[nsdata.length];
    [nsdata getBytes:byte length:nsdata.length];
    dispatch_data_t data = dispatch_data_create(byte, nsdata.length, nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
    return data;
}

- (NSData *)nsdataFromDispatchData:(dispatch_data_t)dispatchData  {
    if (dispatchData == nil) {
        return nil;
    }
    const void *buffer = NULL;
    size_t size = 0;
    dispatch_data_t new_data_file = dispatch_data_create_map(dispatchData, &buffer, &size);
    if(new_data_file) {
        
    }
    NSData *nsdata = [[NSData alloc] initWithBytes:buffer length:size];
    return nsdata;
}


@end

.h文件

#import <Foundation/Foundation.h>
#import <Network/Network.h>
NS_ASSUME_NONNULL_BEGIN

typedef void (^DTLSDataHandle)(NSData *_Nullable data, NSError *_Nullable error);

typedef void (^DTLSSessionCompletedHandle)(NSError *_Nullable error);



@interface YHDTLSManager : NSObject
+(instancetype)shareinstance    ;
//设置连接信息
-(void)setConnectInfoWithCertName:(NSString*)cert  ;
//连接服务器
- (void)linkServerWithHost:(NSString *)host
                     port:(NSString *)port
                    queue:(dispatch_queue_t)queue;

//断开链接
- (void)disConnect    ;

//发送数据
- (void)sendData:(NSData *)data
               complete:(DTLSSessionCompletedHandle)complete    ;

//接收数据回调
- (void)receiveData:(DTLSDataHandle)receiveHandle    ;

@end


NS_ASSUME_NONNULL_END
举报

相关推荐

0 条评论