【发布时间】:2017-01-04 06:29:26
【问题描述】:
我正在尝试在 OS X 和 iOS(8.1 版本)上使用openssl 之间的 SSL TCP 连接。 Exception Domains 有 192.168.0.104。
Swift iOS 代码:
class SSLSocketLite {
// The input stream.
private var inStream: NSInputStream?
// The output stream.
private var outStream: NSOutputStream?
// The host to connect to.
private var host: String
// The port to connect on.
private var port: Int
init(inHost:String, inPort:Int) {
host = inHost
port = inPort
NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inStream, outputStream: &outStream)
}
func Open() {
inStream?.open()
outStream?.open()
inStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)
outStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)
inStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
outStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
func Read() -> String! {
var buffer = Array<UInt8>(count:1024, repeatedValue: 0)
if inStream!.hasBytesAvailable {
inStream!.read(&buffer, maxLength: 1024)
let responseString = NSString(bytes: buffer, length: buffer.count, encoding: NSUTF8StringEncoding) as! String
return responseString
}
return nil
}
func Write(msg:String) {
let data:NSData = msg.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
outStream!.write(UnsafePointer(data.bytes), maxLength: data.length)
}
func Close() {
inStream?.close()
outStream?.close()
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let sslsock = SSLSocketLite(inHost: "192.168.0.104", inPort: 1678)
sslsock.Open()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
在 OS X 端,我使用以下方法创建了证书和密钥:
openssl req -x509 -newkey rsa:1024 -keyout key.key -out key.crt -days 365 -nodes
并使用以下方式启动 TCP SSL 服务器:
openssl s_server -key key.key -cert key.crt -accept 1678
在那之后,我在 iOS 端得到了CFNetwork SSLHandshake failed (-9807),在 OS X 端得到了bad gethostbyaddr。我该如何解决这个问题?
UPD:
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.异常域 -> +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 输出:
SwiftPlayground[917:31077] CFNetwork SSLHandshake 失败 (-9807)
OpenSSL s_server 输出(什么都没发生):
Using default temp DH parameters Using default temp ECDH parameters ACCEPT
【问题讨论】:
-
openssl req -x509 ...- 创建证书时使用的主机名是什么? Objective C 代码中使用的host, port是什么?另请参阅How do you sign Certificate Signing Request with your Certification Authority 和How to create a self-signed certificate with openssl?,它提供了大量有关 X.509 服务器证书的背景信息,以及各种规则的来源。 -
@jww 谢谢。我按照How do you sign Certificate Signing Request with your Certification Authority 中所说的做了一切,之后我转换了证书:
openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER,在 iOS 应用程序中添加了 servercert.der 并启动了sudo openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678。但是在 iOS 端得到了SSLHandshake failed (-9807),在 OS X 服务器端没有。我做错了什么? -
如果 X.509 和证书和主机名都正常,那么接下来转到这个:
sudo openssl s_server ...- 您使用的是 Apple 的 OpenSSL 0.9.8 吗?如果是这样,您可能必须使用 OpenSSL 1.0.1 或更高版本。 OpenSSL 1.0.2 将是一个不错的选择。 -
如果您使用的是 OpenSSL 1.0.1 或更高版本,请注意 Apple 的
SecureTransport/ECDHE-ECDSA错误。它在许多 iOS 和 OS X 主机上未打补丁。另请参阅 OpenSSL wiki 上的SSL_OP_SAFARI_ECDHE_ECDSA BUG。 -
@jww
openssl version输出:OpenSSL 0.9.8zg 14 July 2015。我使用自制软件安装了 openssl,所以我需要安装其他供应商的版本吗?您确定我之前评论中的所有命令都有效吗?在服务器端使用pem版本的servercert 和在客户端使用der可以吗?
标签: ios ssl networking tcp openssl