preface
In the era of the rapid development of the Internet, basically every day with the network. So, how to ensure the security of information in network communication? In this article, we will talk about how Alamofire, as an excellent third-party library related to network requests in iOS development, is designed and used in its security policy.
Introduction of HTTPS
Before getting to the point, let’s take a quick look at HTTPS. If you already know, you can skip this paragraph.
Why use HTTPS
In the past, we used HTTP more, so why is Apple pushing us to use HTTPS as a more secure form of request? Problems with HTTP:
- Communications are in plain text, making them easy to eavesdrop on
- Do not verify the identity of the communication parties, easy to be disguised
- Data integrity cannot be verified and may be tampered with
Using the HTTPS communication mechanism can effectively prevent these problems. HTTPS is not a new protocol at the application layer, but the HTTP communication interface is replaced by SSL and TLS. Usually HTTP communicates directly with TCP, but when SSL is used, it communicates first with SSL and then with SSL and TCP. In short, HTTPS is HTTP in the shell of the SSL protocol.
HTTP+ Data Encryption + IDENTITY Authentication + Data integrity protection =HTTPS
HTTPS Encryption
HTTPS uses the hybrid encryption mechanism, that is, shared secret key encryption (symmetric encryption) and public key encryption (asymmetric encryption). Public key encryption is used in the key exchange process, and shared key encryption is used in the communication exchange message establishment stage. Public-key encryption is more secure than shared key encryption, so why not all public-key encryption? Because compared with shared secret key encryption, processing is more complex and slower. HTTPS combines the advantages and disadvantages of the two encryption methods to achieve a hybrid encryption process. As shown in the figure:
HTTPS authentication and encryption processes
HTTPS has one-way authentication and two-way authentication. The principles are basically the same. Here is the whole process of one-way authentication.
- Client initiating
HTTPS
Request: the client sends a request to the serverSSL
Protocol version, encryption algorithm type, and random number. - Server configuration: Yes
HTTPS
The protocol server must have a set of digital certificates, which can be made by yourself or applied to the organization. The difference is that a certificate issued by the client can be accessed only after the certificate is authenticated by the client, while a certificate applied for by a trusted company can be accessed directly. The certificate is a pair of public and private keys. - Transfer certificate: This certificate is essentially a public key, but contains a lot of information, such as the certificate authority, expiration date, and so on. The server also sends messages to the client
SSL
Protocol version, encryption algorithm type, and random number - Client parsing certificates: This part of the job is done by the client
TLS
First, it verifies whether the public key is valid, such as the authority, expiration date, etc. If an exception is found, it will throw a warning indicating that there is a problem with the certificate. If there is nothing wrong with the certificate, a random value is generated and then encrypted with the certificate. - Transmit encrypted information: This part transmits the random value encrypted with the certificate. The purpose is to let the server get the random value, and the communication between the client and the server can be encrypted and decrypted by this random value.
- Service segment decryption information: after decrypting with the private key, the server gets the random value (private key) from the client, and then encrypts the content symmetrically through this value.
- Transfer encrypted information: This part of the information is the service segment encrypted with the private key, can be restored on the client.
- Client decryption message: The client decrypts the message sent by the service segment with the previously generated private key, and then obtains the decrypted content. Even if the third party listens to the data, there’s nothing they can do about it.
Alamofire safety certification
Certificate Authentication mode
We need to carry out security certification if the certificate is issued by the CA organization, and we do not need to write relevant codes for security certification. Here’s an example of Alamofire initiating an HTTPS request 🌰 :
let serverTrustPlolicies: [String: ServerTrustPolicy] = [
hostUrl: .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true)]self.sessionManager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPlolicies))
self.sessionManager? .request(urlString).response { (defaultResponse)in
print(defaultResponse)
}
Copy the code
- It is also very simple to use
HTTP
Compared to just initializingSessionManager
One was passed in whenServerTrustPolicyManager
Object, which is the manager of the certificate trust policy. - Initialize the
ServerTrustPolicyManager
Object is passed in a[String: ServerTrustPolicy]
A collection of types is saved as a parameter,key
Is the host address,value
Validation mode.
public enum ServerTrustPolicy {
case performDefaultEvaluation(validateHost: Bool)
case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags)
case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool)
case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
case disableEvaluation
case customEvaluation((_ serverTrust: SecTrust._ host: String) - >Bool)}Copy the code
Alamofire
There are six modes of security authentication policy. The three modes are most commonly used:.pinCertificates
Certificate verification mode,.pinPublicKeys
Public key authentication mode and.disableEvaluation
Do not validate schemas..performDefaultEvaluation
By default, only valid certificates can pass authentication.performRevokedEvaluation
An additional setting for deregistering certificates.pinCertificates
In certificate verification mode, the client verifies the certificate returned by the server and the local certificate. If the certificate is correct, the client continues to perform the verification..pinPublicKeys
In PublicKey authentication mode, the client verifies the PublicKey in the certificate returned by the server and the locally saved certificate. If the certificate is correct, the client continues to perform the verification..disableEvaluation
Validation under this option is always passed, unconditional trust..customEvaluation
Custom validation, which returns a Boolean result.
- This is used in the previous example
.pinCertificates
Certificate authentication mode. It has three associated values:- Parameter 1:
certificates
It stands for certificate - Argument 2:
validateCertificateChain
Indicates whether to validate the certificate chain - Parameter 3:
validateHost
Indicates whether the child address is verified
- Parameter 1:
- So, how do we find the certificates in the project?
Alamofire
Gives us a way to do itServerTrustPolicy.certificates()
Easy to use.
public static func certificates(in bundle: Bundle = Bundle.main)- > [SecCertificate] {
var certificates: [SecCertificate] = []
let paths = Set([".cer".".CER".".crt".".CRT".".der".".DER"].map { fileExtension in
bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil)
}.joined())
for path in paths {
if
let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData.let certificate = SecCertificateCreateWithData(nil, certificateData)
{
certificates.append(certificate)
}
}
return certificates
}
Copy the code
- The default is in
Bundle.main
We can also specify where to store the certificateBundle
To find. - Now that you understand the validation pattern, take a look at the validation process. When a request is made, a callback is made
URLSessionTaskDelegate
The following method of.
open func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
guard taskDidReceiveChallengeWithCompletion == nil else{ taskDidReceiveChallengeWithCompletion? (session, task, challenge, completionHandler)return
}
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
let result = taskDidReceiveChallenge(session, task, challenge)
completionHandler(result.0, result.1)}else if let delegate = self[task]? .delegate { delegate.urlSession( session, task: task, didReceive: challenge, completionHandler: completionHandler ) }else {
urlSession(session, didReceive: challenge, completionHandler: completionHandler)
}
}
Copy the code
-
If you have any value taskDidReceiveChallengeWithCompletion, direct callback the closure, this means that we can achieve our validation logic. As you can see, Alamofire is very friendly, providing both regular implementations and developer custom implementations.
-
Continue tracing the code into the delegate.urlSession method
-
It then executes the method shown in the red box, retrieves the validation mode set earlier, and then executes the Evaluate method
public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool {
var serverTrustIsValid = false
switch self {
// omit cannot code.....
case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost):
if validateCertificateChain {
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
SecTrustSetPolicies(serverTrust, policy)
SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray)
SecTrustSetAnchorCertificatesOnly(serverTrust, true)
serverTrustIsValid = trustIsValid(serverTrust)
} else {
let serverCertificatesDataArray = certificateData(for: serverTrust)
let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates)
outerLoop: for serverCertificateData in serverCertificatesDataArray {
for pinnedCertificateData in pinnedCertificatesDataArray {
if serverCertificateData == pinnedCertificateData {
serverTrustIsValid = true
break outerLoop
}
}
}
}
// omit cannot code.....
return serverTrustIsValid
}
Copy the code
- If you need to validate the certificate chain, it will do so
if
Code block, roughly as follows:SecPolicyCreateSSL
: Creates a policy and specifies whether to verify hostSecTrustSetPolicies
: Sets the policy for the object to be verifiedtrustIsValid
: Verification is performed. The system returns successfullyYES
- If you need to validate the certificate chain, the server certificate and your own certificate are processed into a binary array of certificates and compared.
- If the validation passes, the normal request for data can begin; if the validation fails, the request is terminated and an exception is thrown.
Public key authentication mode
- Public key authentication is similar to certificate authentication
.pinPublicKeys
This enumeration value, the first parameter is the public key, the other parameters are the same as the certificate authentication mode.Alamofire
It also provides us with a method to obtain public keysServerTrustPolicy.publicKeys()
Call this method directly. - So when do you use public key authentication? The advantage of using public key authentication mode is that as long as the public key remains unchanged, you can use it all the time without updating the certificate or worrying about the expiration of the certificate.
conclusion
This article briefly discusses the HTTPS encryption process, and analyzes the interface and network challenge process by how Alamofire requests HTTPS. Of course, you need to learn more if you want to fully understand how HTTPS works. I recommend a book called Diagrams of HTTP, which is very easy to read and some of the images in this article come from this book.
If you have any questions or suggestions, you are welcome to comment or write to us. Like friends can click on the following and like, the follow-up will continue to update the article.