1
我试图实现相互TLS连接。这里是流量:使用客户端证书和secp512r1失败的TLS 1.2连接
- 我生成CSR请求(使用椭圆曲线密钥,secp512r1)
- 发送签名请求到服务器并接收的公钥证书作为响应
- 我让P12证书使用步骤2中收到的公钥证书和我的ECC secp512r1私钥。我把它保存为文档“ca.p12”文件
- ,当我得到
NSURLAuthenticationMethodClientCertificate
挑战我使用的凭据从此证书 - 获取
Error Domain=NSURLErrorDomain Code=-1200
“发生SSL错误,无法进行到服务器的安全连接解决它“。
虽然检查服务器和客户端之间的流量似乎是客户端问题。
问题:
- 确实iOS的9/10支持椭圆曲线按键,secp512r1在TLS握手?
- 我错过了什么?
任何想法,建议真的很感激。谢谢。
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
//server trust works fine
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
if (self.shouldTrustProtectionSpace(space: challenge.protectionSpace)) {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
}
//This one causes the issue
else if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
let identityAndTrust: IdentityAndTrust = self.extractIdentity()
let urlCredential: URLCredential = URLCredential(
identity: identityAndTrust.identityRef,
certificates: identityAndTrust.certArray as? [AnyObject],
persistence: URLCredential.Persistence.forSession)
completionHandler(.useCredential, urlCredential)
}
}
struct IdentityAndTrust {
var identityRef: SecIdentity
var trust: SecTrust
var certArray: AnyObject
}
func extractIdentity() -> IdentityAndTrust {
var identityAndTrust: IdentityAndTrust!
var securityError: OSStatus = errSecSuccess
var path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
path = path + "/ca.p12"
//let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
let PKCS12Data = NSData(contentsOfFile:path)!
let key: NSString = kSecImportExportPassphrase as NSString
let options: NSDictionary = [key : "123"]
//create variable for holding security information
//var privateKeyRef: SecKeyRef? = nil
var items: CFArray?
securityError = SecPKCS12Import(PKCS12Data, options, &items)
if securityError == errSecSuccess {
let certItems: CFArray = items as CFArray!
let certItemsArray: Array = certItems as Array
let dict: AnyObject? = certItemsArray.first
if let certEntry: Dictionary = dict as? Dictionary<String, AnyObject> {
// grab the identity
let identityPointer: AnyObject? = certEntry["identity"]
let secIdentityRef: SecIdentity = identityPointer as! SecIdentity!
print("\(identityPointer) :::: \(secIdentityRef)")
// grab the trust
let trustPointer: AnyObject? = certEntry["trust"]
let trustRef: SecTrust = trustPointer as! SecTrust
print("\(trustPointer) :::: \(trustRef)")
// grab the certificate chain
var certRef: SecCertificate?
SecIdentityCopyCertificate(secIdentityRef, &certRef)
let certArray: NSMutableArray = NSMutableArray()
let reader = DmailReader.sharedReader
let caCertString = reader.getCACert()
let cerData = X509Utility.der(fromData: caCertString)
let convertedData = cerData as! CFData
let caCert = SecCertificateCreateWithData(nil, convertedData)
certArray.add(certRef as SecCertificate!)
certArray.add(caCert!)
identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray)
}
}
return identityAndTrust
}
根据PKIX(网络的PKI),在链应该(必须?)的所有证书使用'secp512r1'。另外,服务器必须支持'secp512r1'。要查看'secp512r1'是否是问题,请使用'secp256k1'测试。它是最常见的曲线,并提供了该领域最多的互操作性。 – jww
@jww不幸的是,我不能使用secp256进行测试,因为服务器只支持secp512r –
嗯,问题是Apple的SecureTransport可能是越野车。苹果以其软件质量差而闻名(参见[goto fail](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug)解释/非正式补丁/),[SSL_OP_SAFARI_ECDHE_ECDSA_BUG](https://wiki.openssl.org/index.php/SSL_OP_SAFARI_ECDHE_ECDSA_BUG)等)。我认为你需要隔离secp512r1曲线的客户端证书来发现问题所在。使用secp256k1会测试客户端证书。你能用'openssl s_client'或其他工具来测试客户端证书吗? – jww