CFNetwork SSLHandshake在iOS模拟器上使用localhost失败(-9807)

时间:2016-08-31 02:28:41

标签: ios objective-c ssl encryption openssl

我正在尝试使用TCP SSL连接openssl s_server和iOS客户端,但获取CFNetwork SSLHandshake failed (-9807)

Objective-C代码(from here):

- (void)viewDidLoad {
    [super viewDidLoad];

    printf("method started \n");

    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSData *iosTrustedCertDerData =
    [NSData dataWithContentsOfFile:[bundle pathForResource:@"servercert"
                                                    ofType:@"der"]];

    OSStatus            err = noErr;
    SecCertificateRef   cert;

    cert = SecCertificateCreateWithData(NULL, (CFDataRef) iosTrustedCertDerData);
    assert(cert != NULL);

    CFTypeRef result;

    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                          (id)kSecClassCertificate, kSecClass,
                          cert, kSecValueRef,
                          nil];

    err = SecItemAdd((CFDictionaryRef)dict, &result);
    assert(err == noErr || err == errSecDuplicateItem);

    printf("adding finished \n");


    if ((err == noErr) ||
        (err == errSecDuplicateItem)) {

        printf("success \n");

        CFReadStreamRef readStream;
        CFWriteStreamRef writeStream;
        CFStreamCreatePairWithSocketToHost(NULL,
                                           (CFStringRef)@"localhost",
                                           1678,
                                           &readStream,
                                           &writeStream);
        CFReadStreamSetProperty(readStream,
                                kCFStreamPropertySocketSecurityLevel,
                                kCFStreamSocketSecurityLevelTLSv1);
        CFReadStreamOpen(readStream);
        CFWriteStreamOpen(writeStream);

        UInt8 buf[] = "Hello from iOS";
        int bytesWritten = CFWriteStreamWrite(writeStream, buf, strlen((char*)buf));

    } else {
        printf("error!");
    }

    CFRelease(cert);
}

创建证书并启动服务器的命令序列(请注意11步:在服务器端我使用pem证书,在客户端使用我的证书),我得到的文件样本this answer

1。touch openssl-ca.cnf

2.在openssl-ca.cnf中粘贴样本。只有一行改变了:

commonName_default = localhost

3。openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

4。touch openssl-server.cnf

5.在openssl-server.cnf中粘贴样本。只改变了两行:

commonName_default = localhost

DNS.1 = localhost

6。openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM

7.在openssl-ca.cnf中增加了2 + 1个部分:

[ CA_default ]
    ...
    base_dir    = .
    certificate = $base_dir/cacert.pem  # The CA certifcate
    private_key = $base_dir/cakey.pem   # The CA private key
    new_certs_dir   = $base_dir     # Location for new certs after signing
    database    = $base_dir/index.txt   # Database index file
    serial      = $base_dir/serial.txt  # The current serial number

    unique_subject  = no            # Set to 'no' to allow creation of
                    # several certificates with same subject.

...

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

8。touch index.txt

9。echo '01' > serial.txt

10。openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr

11。openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER

12.在iOS项目中添加了servercert.der

13。let sslsock = SSLSocketLite(inHost: "localhost", inPort: 1678)

14.Exception Domains - > + localhost

15。openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678

openssl-ca.cnf的最终版本:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

[ CA_default ]

default_days    = 1000          # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md  = sha256        # use public key default MD
preserve    = no            # keep passed DN ordering

x509_extensions = ca_extensions     # The extensions to add to the cert

email_in_dn = no            # Don't concat the email in the DN
copy_extensions = copy          # Required to copy SANs from CSR to cert

base_dir    = .
certificate = $base_dir/cacert.pem  # The CA certifcate
private_key = $base_dir/cakey.pem   # The CA private key
new_certs_dir   = $base_dir     # Location for new certs after signing
database    = $base_dir/index.txt   # Database index file
serial      = $base_dir/serial.txt  # The current serial number

unique_subject  = no            # Set to 'no' to allow creation of
                # several certificates with same subject.
####################################################################
[ req ]
default_bits        = 4096
default_keyfile     = cakey.pem
distinguished_name  = ca_distinguished_name
x509_extensions     = ca_extensions
string_mask         = utf8only

####################################################################
[ ca_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = Maryland

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

organizationalUnitName  = Organizational Unit (eg, division)
organizationalUnitName_default  = Server Research Department

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ ca_extensions ]

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

openssl-server.cnf的最终版本:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits        = 2048
default_keyfile     = serverkey.pem
distinguished_name  = server_distinguished_name
req_extensions      = server_req_extensions
string_mask         = utf8only

####################################################################
[ server_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = MD

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ server_req_extensions ]

subjectKeyIdentifier        = hash
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]

DNS.1       = localhost

iOS输出:

  

方法开始了   添加完成   成功
  2016-08-30 19:17:06.619   ssltest [5418:141544] CFNetwork SSLHandshake失败(-9807)

OpenSSL s_server输出(没有发生):

  

使用默认的临时DH参数

     

ACCEPT

我错过了什么?我该如何解决?

也许有人可以与localhost中的commonName地址共享工作证书?使用此功能,我将了解问题究竟是什么:cert和我的pemder转换或iOS应用。

0 个答案:

没有答案