How to monitor network Traffic ios

how to check network reachability in ios and how to change network settings ios 7 and how to reset network settings ios 7 and how to disable network ios simulator
Dr.KiranArora Profile Pic
Published Date:27-10-2017
Your Website URL(Optional)
Securing Network Traffi c You can fi nd the code downloads for this chapter at WroxTitle/Professional-iOS-Network-Programming-Connecting-the-Enterprise-to- the-iPhone-and-iPad.productCd-1118362403.html on the Download Code tab. The code for this chapter is in the Chapter 6 download and is divided into two major sections: ➤ An Xcode project that includes a rudimentary mobile banking application that communicates with a simple web service ➤ A set of PHP scripts to serve as a web service for the mobile banking app, which handles authentication, fetching account details, and transferring funds c06.indd 119 c06.indd 119120 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ The average cost of a mobile-related data breach in 2011 was 194 per-record with an average total organizational cost of 5.5 million per incident (“2011 Cost of Data Breach Study.” Ponemon Institute© Research Report, March 2012, en/us/about/media/pdfs/b-ponemon-2011-cost-of-data-breach-us.en-us.pdf). Given the highly networked nature of this world, it is of utmost importance that security be reviewed and addressed at every step of an application’s development lifecycle. To aid development of security-related requirements, Apple provides the Security framework and CommonCrypto interfaces to developers for use in their applications. The Security framework is a set of C APIs for managing certifi cates, trust policies, and access to the device’s secure data store. CommonCrypto includes a set of interfaces to encrypt and decrypt data, generate common crypto- graphic hashes (for example, MD5 and SHA1), calculate a message authentication code, and derive password or passphrase-based keys. This chapter covers how to use the Security framework with NSURLConnection to verify client and server identity. It also examines common authentication patterns and provides an example of encrypting transmitted data. Finally, it discusses how to decrypt server responses and securely store credentials using the device keychain. The sample mobile banking app included in the chapter downloads helps illustrate the various points discussed in this chapter. The app contains a server-side component, which is developed in PHP for simplicity. PHP is relatively straightforward and should be easy to understand even if you lack previous experience with it. Important server-side snippets have been included throughout the chapter and the entire server-side source is available in the Chapter 6 download folder online. VERIFYING SERVER COMMUNICATION It is likely that users of your applications will be on the go; these are mobile applications after all, and you can rarely guarantee that any connection to the Internet is secure and rid of prying eyes. Most coffee shops offer free Wi-Fi to their patrons, but these networks are perfect for eavesdropping on one of your unsuspecting users. It is the developer’s responsibility to ensure that users communicate only with the server(s) that you intend. It is a best practice to use NSURLProtectionSpace to verify that users of your mobile banking application communicate with your secure banking servers, especially when issuing requests that manipulate data on the back end. NSURLProtectionSpace represents a server or realm that requires authentication and is a property of all inbound NSURLAuthenticationChallenges. The following code snippet illustrates how to create a protection space, which you can compare with the information contained in the challenge: NSURLProtectionSpace defaultSpace = NSURLProtectionSpace alloc initWithHost:"" port:443 protocol:NSURLProtectionSpaceHTTPS realm:"mobile" authenticationMethod:NSURLAuthenticationMethodDefault; c06.indd 120 c06.indd 120 13/09/12 2:42 PM 13/09/12 2:42 PMVerifying Server Communication 121 ❘ Notice that you specifi ed port 443, which corresponds to the NSURLProtectionSpaceHTTPS protocol. Table 6-1 lists additional supported protocols and their common port values. If you are not sure which port is confi gured on your server, you can log any properties of the inbound challenge to the console. TABLE 6-1: Supported NSURLProtectionSpace Protocols PROTOCOL CONSTANT DEFAULT PORT NSURLProtectionSpaceHTTP 80 or 8080 NSURLProtectionSpaceHTTPS 443 NSURLProtectionSpaceFTP 21 or 22 The application specifi es an authentication method of NSURLAuthenticationMethodDefault. The default for the NSURLProtectionSpaceHTTP protocol is Basic authentication, so in this case, specifying nil or NSURLAuthenticationMethodHTTPBasic is the same as specifying NSURLAuthenticationMethodDefault. Following is a list of all supported authentication methods: ➤ NSURLAuthenticationMethodDefault ➤ NSURLAuthenticationMethodHTTPBasic ➤ NSURLAuthenticationMethodHTTPDigest ➤ NSURLAuthenticationMethodHTMLForm ➤ NSURLAuthenticationMethodNTLM ➤ NSURLAuthenticationMethodNegotiate ➤ NSURLAuthenticationMethodClientCertificate ➤ NSURLAuthenticationMethodServerTrust Now that you have created a protection space with your server’s attributes, you need to ensure that it is used to verify your connections. When your code requests a resource from the server that requires authentication, the server responds with an HTTP status code of 401 - Access Denied . NSURLConnection receives this response and immediately sends a willSendRequestFor AuthenticationChallenge: delegate message with a copy of the authentication challenge. Figure 6-1 covers the basic challenge-response process. c06.indd 121 c06.indd 121 13/09/12 2:42 PM 13/09/12 2:42 PM122 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ Custom Code NSURLConnection HTTPServer NSMutableURLRequest: Method: GET GET: balance.html URL: balance.html 1 2 401 Access Denied, willSendRequestFor WWW-Authenticate: Basic realm=“mobile” AuthenticationChallenge: 4 3 NSURI Credential NSURLCredential 5 6 Status: 200 Contents: balance.html NSData Object 8 6 FIGURE 6-1 Implementing willSendRequestForAuthenticationChallenge: provides you with an opportunity to examine the challenge, determine if you want to respond to the server’s authentication challenge, and issue the appropriate challenge response. Authentication Challenge responses are instances of NSURLCredential, which can be created for trusts, username/password combinations, and client certifi cates, which are discussed in detail in the next section. When creating an NSURLCredential for server trust, it’s the responsibility of your delegate to evaluate the trust. The following example outlines one possible implementation of protection space verifi cation within willSendRequestForAuthenticationChallenge:. - (void)connection:(NSURLConnection )connection willSendRequestForAuthenticationChallenge: (NSURLAuthenticationChallenge )challenge // create an array of protection spaces for confirmation NSURLProtectionSpace defaultSpace = NSURLProtectionSpace alloc initWithHost:"" port:443 protocol:NSURLProtectionSpaceHTTPS realm:"mobilebanking" authenticationMethod:NSURLAuthenticationMethodDefault; NSURLProtectionSpace trustSpace = NSURLProtectionSpace alloc initWithHost:"" port:443 protocol:NSURLProtectionSpaceHTTPS realm:"mobilebanking" authenticationMethod:NSURLAuthenticationMethodClientCertificate; c06.indd 122 c06.indd 122 13/09/12 2:42 PM 13/09/12 2:42 PMVerifying Server Communication 123 ❘ NSArray validSpaces = NSArray arrayWithObjects:defaultSpace, trustSpace, nil; // validate that the authentication challenge // came from a whitelisted protection space if (validSpaces containsObject:challenge.protectionSpace) // dispatch alert view message to the main thread NSString msg = "We're unable to establish a secure connection. Please check your network connection and try again."; dispatch_async(dispatch_get_main_queue(), UIAlertView alloc initWithTitle:"Unsecure Connection" message:msg delegate:nil cancelButtonTitle:"OK" otherButtonTitles:nil show; ); // cancel authentication attempt challenge.sender cancelAuthenticationChallenge:challenge; ... This section has already covered how to create a protection space, but the preceding code snippet covers adding an additional protection space, which provides some fl exibility to the back end. When you have determined the protection spaces to support, create them and add them to an array for comparison against inbound authentication challenges. In practice, you should defi ne valid protection spaces as part of the model layer so that they can be reused across all your network operations. If the protection space from an authentication challenge does not match any of your supported spaces, you should inform the user and cancel the authentication challenge. The code in the previous code example issues a UIAlertView to the main thread via Grand Central Dispatch. This is necessary because each logical unit of network activity that the application performs is created as a subclass of NSOperation, which is typically processed on a background thread. However, the Mobile Banking example application issues the request asynchronously on the main thread so that the application may respond to the willSendRequestForAuthentication Challenge: delegate method. The use of Grand Central Dispatch in this scenario is a safety precaution. Chapter 7, “Optimizing Request Performance,” covers a more appropriate networking pattern and offers an effi cient method for notifying view controllers of issues that require user action. Now that you have implemented your server verifi cation, how does it protect users of the app? This particular verifi cation ensures that the app is communicating only with the servers that you have specifi ed. Should they fi nd themselves on a malicious network where traffi c is being rerouted to a third-party’s server, for example, the protection space verifi cation would fail due to mismatched hosts, and further communication would be halted. More importantly, login credentials, bank account numbers, and so on would never be transmitted. Sophisticated iOS applications often communicate with a web service, and those services may need to change quickly. Unfortunately, consumer iOS application changes require submission and c06.indd 123 c06.indd 123 13/09/12 2:42 PM 13/09/12 2:42 PM124 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ approval by Apple, which can be unpredictable. Your organization does not want to be in a situation where web service authentication must be changed immediately, possibly rendering your application inoperable. To mitigate this risk, the application should include protection spaces that allow for communication to back up authentication servers or some other alternative. The inclusion of multiple protection spaces allows you a certain amount of fl exibility but is ultimately a security decision that each organization needs to evaluate. Another approach that allows fl exibility on the back end is choosing to verify only certain properties of an authentication challenge, such as the host, port, and protocol match a predefi ned set. For example, one could verify that the challenge was issued from a particular host using SSL over port 443, shown in the following code. If any of the conditions are not satisfi ed, the code immediately issues an alert to the user indicating that it was unable to establish a secure connection. if ( isEqualToString:"" challenge.protectionSpace.port == 443 challenge.protectionSpace.protocol isEqualToString:NSURLProtectionSpaceHTTPS) // if ANY of our challenge verifications fail, alert the user dispatch_async(dispatch_get_main_queue(), NSString msg = "We're unable to establish a secure connection." UIAlertView alloc initWithTitle:"Unsecure Connection" message:msg delegate:nil cancelButtonTitle:"OK" otherButtonTitles:nil show; ); // cancel authentication challenge.sender cancelAuthenticationChallenge:challenge; Server verifi cation is important, but it alone is not suffi cient to protect against all attacks. For example, it does not protect against a man-in-the-middle attack in which someone is eavesdropping on network communication. To ensure the security of your users’ data, additional security measures such as message integrity and data encryption must be carefully reviewed and considered. AUTHENTICATING WITH HTTP Authentication is the process to confi rm the identity of the person trying to access a system. It is paramount that the example mobile banking service tier discerns between a real user and an imposter. This section covers common authentication patterns and how to handle those challenges within your iOS applications. The banking application has two authentication modes: standard and expedited. Standard authentica- tion simply prompts users to enter their username and password, whereas expedited authentication allows users to register a device and authenticate using a PIN without typing a username and password each time. To maintain security with expedited authentication, if the user chooses to register the device c06.indd 124 c06.indd 124 13/09/12 2:42 PM 13/09/12 2:42 PMAuthenticating with HTTP 125 ❘ on a given authentication request, the server response will include an additional attribute, the user’s certifi cate. The application stores this certifi cate and checks for it on subsequent launches to determine which authentication view should display. The standard authentication mode of your banking application uses HTTP Basic authentication, whereas expedited authentication uses a client-certifi cate downloaded from the web service. The fol- lowing sections discuss each of these approaches. HTTP Basic, HTTP Digest, and NTLM Authentication The great thing about Basic, Digest, and NTLM authentication is that they are all username/ password-based authentication. This means that you can handle all three authentication challenge types with the same logic. You tend to see Basic and Digest authentication more than NTLM, but NTLM is still used. HTTP Basic authentication was defi ned by RFC 1945 ( and, as the name suggests, is basic. Username and password information are passed in plaintext making it susceptible to interception and manipulation. However, these weaknesses can be accept- able when paired with SSL, and that combination is a common authentication pattern. HTTP Digest authentication was originally defi ned by RFC 2069 ( rfc2069) as a more secure form of authentication that is used by applying an MD5 hash to the password before it is transmitted and pairing it with a cryptographic nonce. A nonce is a random or pseudo-random number used to sign a message, but each individual value can be used only one time. Because each nonce value is used only once and then marked as expired, it prevents replay attacks that re-send a previously encrypted message. HTTP Basic and HTTP Digest authentication have since been combined into a single standard, RFC 2617 ( NTLM is a Microsoft security protocol that provides authentication, integrity, and confi dentiality services. NTLM authentication is a challenge-response protocol similar to HTTP Basic and HTTP Digest authentication. It has largely been supplanted by the Kerberos system but continues to be used to authenticate users remotely over the web. Kerberos is an authentication protocol developed by MIT based on the idea of “tickets” that allow secure identifi cation over nonsecure networks. Luckily, NSURLConnection handles most of the nonce and hash legwork for the various authentication methods, allowing you to simply specify credentials in the form of an NSURLCredential object. NSURLCredential fi ts most authentication requirements because it can represent credentials created from username/password combinations, client certi ficates, and server trusts. Credentials have a variety of persistence options: Do Not Persist, Persist for the Current Session Only, or Persist Permanently. Applications are granted access only to the credentials they create versus those to which the user grants access, as is the case in traditional Mac development. The response logic is the same for HTTP Basic, HTTP Digest, and NTLM authentication. Listing 6-1 covers the additions required to willSendRequestForAuthenticationChallenge: to respond to an authentication challenge with your username and password. fo c06.indd 125 c06.indd 125 13/09/12 2:42 PM 13/09/12 2:42 PM126 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ LISTING 6-1: Handling Basic Authentication Challenges (/App/Mobile-Banking/ AuthenticateOperation.m) - (void)connection:(NSURLConnection )connection willSendRequestForAuthenticationChallenge: (NSURLAuthenticationChallenge )challenge ... // respond to basic authentication requests // DIGEST and NTLM authentication follow this pattern if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic) // proceed with authentication if (challenge.previousFailureCount == 0) NSURLCredential creds = NSURLCredential alloc initWithUser:_username password:_password persistence:NSURLCredentialPersistenceForSession; challenge.sender useCredential:creds forAuthenticationChallenge:challenge; // authentication has previously failed. // depending on authentication configuration, too // many attempts here could lead to a poor user // experience via locked accounts else // cancel the authentication attempt challenge sender cancelAuthenticationChallenge:challenge; // alert the user that his credentials are invalid // this would typically be handled in a cleaner // manner such as updating the styled login view NSString msg = "Invalid username / password."; dispatch_async(dispatch_get_main_queue(), UIAlertView alloc initWithTitle:"Invalid Credentials" message:msg delegate:nil cancelButtonTitle:"OK" otherButtonTitles:nil show; ); ... fo c06.indd 126 c06.indd 126 13/09/12 2:42 PM 13/09/12 2:42 PMAuthenticating with HTTP 127 ❘ After confi rming that the challenge is for HTTP Basic or another supported challenge type, you should ensure that the challenge hasn’t previously failed and create your NSURLCredential object using the username and password entered. If the challenge previously failed, alert the user and can- cel the challenge. This is important because willSendRequestForAuthenticationChallenge: can be called multiple times. Depending on your confi guration, if the user’s credentials are invalid with- out this check in place, it’s possible that an account could be locked after a single invalid credential submission. If the inbound challenge authentication method is not a type the app can handle, do not issue a response. This informs NSURLConnection that the application does not handle that particu- lar authentication method. Client-Certifi cate Authentication Now that the user has successfully authenticated, assume the user registered the device during this particular authentication request. During device registration, the application must store the certifi - cate returned from the authentication service. The following provides an example of what a success- ful service tier response may look like when it includes certifi cate data. "result": "SUCCESS", "additional_info": "Authentication Successful", "certificate": "BASE64 Encoded Certificate Returned certifi cate data in the previous snippet is encoded in the PKCS 12 (.p12) fi le format, a commonly used standard published by RSA Laboratories, for exchanging certifi cate data with client applications. Listing 6-2 and Listing 6-3 outline how to decode Base 64 .p12 data, extract the iden- tity and certifi cate information, and store credentials for future authentication requests. LISTING 6-2: A uthentication Response Handling with Certifi cate Data (/App/Mobile-Banking/ AuthenticateOperation.m) - (void)connectionDidFinishLoading:(NSURLConnection )connection ... // unpack service response NSError error = nil; NSDictionary response = NSJSONSerialization JSONObjectWithData:self.responseData options:0 error:&error; ... // create our client certificate if necessary, // and store in the credential store if (_registerDevice == YES) NSString certString = response objectForKey:"certificate"; NSData certData = NSData dataWithBase64EncodedString:certString; // retrieve the identity and certificate for our decoded data continues c06.indd 127 c06.indd 127 13/09/12 2:42 PM 13/09/12 2:42 PM128 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ LISTING 6-2 (continued) SecIdentityRef identity = NULL; SecCertificateRef certificate = NULL; Utils identity:&identity andCertificate:&certificate fromPKCS12Data:certData withPassphrase:"test"; // store the certificate for future authentication challenges if (identity = NULL) // store the certificate and identity in // the keychain as the default NSURLProtectionSpace certSpace = NSURLProtectionSpace alloc initWithHost:"" port:443 protocol:NSURLProtectionSpaceHTTPS realm:"mobilebanking" authenticationMethod: NSURLAuthenticationMethodClientCertificate; NSArray certArray = NSArray arrayWithObject: (__bridge id)certificate; NSURLCredential credential = NSURLCredential credentialWithIdentity:identity certificates:certArray persistence: NSURLCredentialPersistencePermanent; NSURLCredentialStorage sharedCredentialStorage setDefaultCredential:credential forProtectionSpace:certSpace; ... The majority of Listing 6-2 is straightforward with the possible exception of retrieving the identity and certifi cate from the .p12 certi ficate data returned by the service. Listing 6-3 details how to use the SecPKCS12Import() function within the Security Framework to import an identity and trust and then extract the certifi cate. LISTING 6-3: O btaining Identity and Certifi cate from .p12 Data (/App/Mobile-Banking/Utils.m) + (void)identity:(SecIdentityRef)identity andCertificate:(SecCertificateRef)certificate fromPKCS12Data:(NSData)certData c06.indd 128 c06.indd 128 13/09/12 2:42 PM 13/09/12 2:42 PMAuthenticating with HTTP 129 ❘ withPassphrase:(NSString)passphrase // bridge the import data to foundation objects CFStringRef importPassphrase = (__bridge CFStringRef)passphrase; CFDataRef importData = (__bridge CFDataRef)certData; // create dictionary of options for the PKCS12 import const void keys = kSecImportExportPassphrase ; const void values = importPassphrase ; CFDictionaryRef importOptions = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); // create array to store our import results CFArrayRef importResults = CFArrayCreate(NULL, 0, 0, NULL); OSStatus pkcs12ImportStatus = errSecSuccess; pkcs12ImportStatus = SecPKCS12Import(importData, importOptions, &importResults); // check if import was successful if (pkcs12ImportStatus == errSecSuccess) CFDictionaryRef identityAndTrust = CFArrayGetValueAtIndex (importResults, 0); // retrieve the identity from the certificate imported const void tempIdentity = NULL; tempIdentity = CFDictionaryGetValue (identityAndTrust, kSecImportItemIdentity); identity = (SecIdentityRef)tempIdentity; // extract the certificate from the identity SecCertificateRef tempCertificate = NULL; OSStatus certificateStatus = errSecSuccess; certificateStatus = SecIdentityCopyCertificate (identity, &tempCertificate); certificate = (SecCertificateRef)tempCertificate; // clean up if (importOptions) CFRelease(importOptions); As part of the SSL handshake between the server and the application, willSendRequestFor AuthenticationChallenge: will receive multiple callbacks with Server Trust and Client Certifi cate authentication challenges. You must determine which of these challenges your application needs to handle. The following example expands on Listing 6-1 to determine whether the application should issue a client certifi cate or standard user credentials for authentication. c06.indd 129 c06.indd 129 13/09/12 2:42 PM 13/09/12 2:42 PM130 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ // if this is a client certificate authentication request AND // the user has already registered this device, attempt to issue // the certificate to the service tier if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate && devicePreviouslyRegistered) // proceed with authentication if (challenge.previousFailureCount == 0) // retrieve the default credential specifically for // client certificate challenges NSURLCredential credential = NSURLCredentialStorage sharedCredentialStorage defaultCredentialForProtectionSpace: Model sharedModel clientCertificateProtectionSpace; if (credential) challenge.sender useCredential:credential forAuthenticationChallenge:challenge; // authentication has previously failed. // depending on authentication configuration, too many attempts // here could lead to a poor user experience via locked accounts else // cancel the authentication attempt challenge sender cancelAuthenticationChallenge:challenge; // alert the user that his credentials are invalid // this would typically be handled in a cleaner // manner such as updating the styled login view // either the user has not registered this device or // this is not a client certificate challenge else ... // perform authentication based on Listing 6-1 // if nothing catches this challenge, // attempt to connect without credentials challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge; Within your service tier, you can retrieve the attributes of a certifi cate using the openssl_x509_ parse() function, as outlined in the following code snippet. After you obtain the certifi cate attri- butes, there are a number of service tier authentication options available to you. One option is to verify the Issuer and then look up the private key from a list of known keys for the user. Another option would be to incorporate a PIN mechanism within the application, which is verifi ed prior to issuing the client certifi cate to the authentication challenge. c06.indd 130 c06.indd 130 13/09/12 2:42 PM 13/09/12 2:42 PMMessage Integrity with Hashing and Encryption 131 ❘ if (array_key_exists('SSL_CLIENT_CERT', _SERVER)) clientCertData = openssl_x509_parse(_SERVER'SSL_CLIENT_CERT'); // using certificate attributes and encrypted PIN // verify identity and issue authentication tokens else // issue failed authentication message NSURLConnection intercepts server responses with untrusted certifi cates; this includes self-signed SSL certifi cates. If you test the authentication mechanisms discussed in this section with a self- signed SSL certifi cate, the majority of the network based code will not be executed. However, email- ing your server certifi cate (.cer fi le extension) to an e-mail account confi gured on the device allows you to click and install it. When installed, NSURLConnection requests can recognize your server certifi cate as trusted and proceed with processing. MESSAGE INTEGRITY WITH HASHING AND ENCRYPTION Now that the app has verifi ed that it is communicating with the correct server and has successfully authenticated, it can begin issuing service requests on the user’s behalf. The app must ensure that the data it transmits is properly secure and unmodifi ed during delivery. This section covers techniques to satisfy both requirements with cryptographic hashes, message authentication codes (MAC), and remove encryption. These topics are implemented in the funds transfer functionality in the example Mobile Banking application (available for download on the companion website). The funds transfer request utilizes a combination of cryptographic hashes and encryption to ensure that the message is unreadable and delivered in an unaltered state. Although a number of payload samples are generated and discussed in this section, each follows the de fined JSON payload structure outlined in the following code example. "mac": "Message Authentication Code", "iv": "Initialization Vector", "payload": "toAccount": "123123456456", "fromAccount": "654654321321", "amount": 23.23, "transferDate": "2012-02-27", "transferNotes": "Book advance to savings." The payload property will be the only encrypted element in the request body. For the service tier to properly decrypt the payload, it requires the Initialization Vector (IV) used to encrypt the data within the application. Typically the IV is sent along with the data it was used to encrypt. Although it might seem like this weakens the message’s security, it does not because the IV alone is not enough to decrypt the message. After the service tier has decrypted the payload, it generates a MAC using the same predefi ned set of payload attributes and compares it to the MAC from the inbound request c06.indd 131 c06.indd 131 13/09/12 2:42 PM 13/09/12 2:42 PM132 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ to verify message integrity. If the message were altered in any way during its journey, the codes will not match and the tainted message results in an error. The attribute set the example application uses in this section’s example is the concatenation of the To Account, From Account, Amount, and Transfer Date, as seen later when discussing Message Authentication Codes. Figure 6-2 contains an overview of the steps taking place during the request-response transaction and how each component is used throughout the encryption and decryption process on each side of the transaction. Important values for encryption and decryption as well as the MAC algorithm are known by both parties in the transaction. Also, the Request Body section aligns with the JSON payload structure defi ned in the previous example. iOS Application Service Tier Payload Encrypted Payload Shared Encryption Shared Request Body Key Encryption Key Encryption Decryption Encrypted Payload Process Process Generate Initialization Vector IV Shared HMAC Key Generate Generate MAC Service MAC MAC Shared MAC HMAC Key values equal? Untainted message, If Equal: continue processing Not Equal: Something is wrong, abort FIGURE 6-2 Hashing Cryptographic hashes, or digests, generate fi xed-size bit sequences for a given block of data. These hash values make comparing and sorting blocks of data easy. A few common uses of hashes include tracking fi le changes, downloading checksums, obfuscating data for database storage, and a rudi- mentary method to verify integrity of request data. A more robust approach uses MACs, which is covered in detail later in this section. The iOS CommonCrypto library provides support for MD5, SHA-1, and SHA-256 digests as well as a few other less commonly used routines. The examples covered in this chapter focus only on MD5, SHA-1, and SHA-256; however, the process to generate hash values is the same for all CommonCrypto digest routines. Hashes can be created manually through a series of function calls to create a digest context, update the context with the data to be processed, and retrieve the value of the digest calculation, or you can use convenience functions provided for each digest routine. c06.indd 132 c06.indd 132 13/09/12 2:42 PM 13/09/12 2:42 PMMessage Integrity with Hashing and Encryption 133 ❘ To simplify practical use within your applications, create a category on NSString to implement your hash methods. NSString+Hashing.h/.m houses all your hash related category methods. Its inter- face defi nition is shown in Listing 6-4. LISTING 6-4: N SString Hashing Category Defi nition (/App/Mobile-Banking/NSString+Hashing.h) import CommonCrypto/CommonDigest.h enum NJHashTypeMD5 = 0, NJHashTypeSHA1, NJHashTypeSHA256, ; typedef NSUInteger NJHashType; interface NSString (Hashing) - (NSString)md5; - (NSString)sha1; - (NSString)sha256; - (NSString)hashWithType:(NJHashType)type; end Listing 6-5 outlines the core logic within your hashing category. Each of the convenience methods, md5, sha1, and sha256 call hashWithType:. Although there are some predefi ned hash enumerations throughout CommonCrypto libraries that the application could potentially use, none of the enumerations are defi ned within the context of digest calculations. Rather than relying on an enumeration that may change in the future, the application uses this custom one that also provides the added benefi t of restrict- ing the digest routines it supports. LISTING 6-5: Core Digest Calculation Logic Within hashWithType (/App/Mobile-Banking/ NSString+Hashing.m) - (NSString)hashWithType:(NJHashType)type // Create pointer to the string as UTF8 – this is NULL terminated const char ptr = self UTF8String; // Create buffer with length for chosen digest NSInteger bufferSize; switch (type) case NJHashTypeMD5: // 16 bytes bufferSize = CC_MD5_DIGEST_LENGTH; break; case NJHashTypeSHA1: // 20 bytes bufferSize = CC_SHA1_DIGEST_LENGTH; continues c06.indd 133 c06.indd 133 13/09/12 2:42 PM 13/09/12 2:42 PM134 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ LISTING 6-5 (continued) break; case NJHashTypeSHA256: // 32 bytes bufferSize = CC_SHA256_DIGEST_LENGTH; break; default: return nil; break; unsigned char bufferbufferSize; // Perform hash calculation and store in buffer switch (type) case NJHashTypeMD5: CC_MD5(ptr, strlen(ptr), buffer); break; case NJHashTypeSHA1: CC_SHA1(ptr, strlen(ptr), buffer); break; case NJHashTypeSHA256: CC_SHA256(ptr, strlen(ptr), buffer); break; default: return nil; break; // Convert buffer value to pretty printed NSString // this will match the servers hash calculation NSMutableString hashString = NSMutableString stringWithCapacity:bufferSize 2; for(int i = 0; i bufferSize; i++) hashString appendFormat:"%02x",bufferi; return hashString; The only portion of the hashWithType: implementation that may not be straightforward is the fi nal step. The fi nal step shown in Listing 6-5 loops through the byte output of the digest calculation and converts it to hexadecimal, a readable output. With the core hash logic complete and consolidated to a single method, implementing each convenience method requires only a single line of code each, as shown in Listing 6-6. c06.indd 134 c06.indd 134 13/09/12 2:42 PM 13/09/12 2:42 PMMessage Integrity with Hashing and Encryption 135 ❘ LISTING 6-6: H ashing Convenience Method Implementations (/App/Mobile-Banking/ NSString+Hashing.m) - (NSString)md5 return self hashWithType:NJHashTypeMD5; - (NSString)sha1 return self hashWithType:NJHashTypeSHA1; - (NSString)sha256 return self hashWithType:NJHashTypeSHA256; This approach has the added benefi t of being easily extended to support additional digest calcula- tions. The following example demonstrates calling each convenience method and the output it gen- erates. The National Institute of Standards and Technology (NIST) provides test vectors to validate digest calculation output at . NSLog("MD5: %", "test string" md5); NSLog("SHA1: %", "test string" sha1); NSLog("SHA256: %", "test string" sha256); Output: MD5: 6f8db599de986fab7a21625b7916589c SHA1: 661295c9cbf9d6b2f6428414504a8deed3020641 SHA256: d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b Generating hashes in the service tier is similar because PHP supports each of the digest routines implemented in Listing 6-6, plus a few dozen others. The standard function to generate a hash value is hash(), which accepts the algorithm to perform and the value to perform it on. In addition, PHP includes convenience functions for the generation of MD5 and SHA1 hashes. Generating hash val- ues for each of the digests in PHP can be done like so: echo "MD5: ".md5("test string")."/br"; echo "SHA1: ".sha1("test string")."/br"; echo "SHA256: ".hash("sha256", "test string")."/br"; Output: MD5: 6f8db599de986fab7a21625b7916589c SHA1: 661295c9cbf9d6b2f6428414504a8deed3020641 SHA256: d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b The previous examples covered hashing string objects, but it is also just as easy to generate hashes of NSData NSData objects by creating a similar category on . However, if you have advanced hashing requirements or intend to compare hash values within your iOS application, you may want to consider creating a custom class, which can be written to optimize initialization and make hash c06.indd 135 c06.indd 135 13/09/12 2:42 PM 13/09/12 2:42 PM136 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ comparison easier by overriding isEqualTo:. Whereas using a hashing algorithm enables you detect content changes, Message Authentication Codes are paired with a key, making them more secure. Message Authentication Codes A message authentication code (MAC) is a mechanism for detecting payload modifi cation and veri- fying authenticity by creating a hash of the inbound request data (or a pre-arranged subset of the request data) and comparing it with a precomputed MAC that is delivered with the payload. MACs are similar to the hash functions previously discussed but are more secure because they are paired with a secret key. As depicted in Figure 6-2, your application will compute a MAC that is sent with your request. This inbound MAC is then compared with a MAC computed in the service tier using the same key and dataset. If the MAC values are not equal, it is safe to assume that the message has been modifi ed. Another approach would be to generate a MAC of the cipher text. While this accomplishes the same goal, it also allows you to determine if the message has been modifi ed prior to executing a potentially expensive decryption process. Although there are other MAC algorithms, examples in this section focus on Hash-Based Message Authentication Code (HMAC) because it is natively supported in iOS and most service-tier plat- forms. Often referred to as a keyed message authentication code, HMAC was defi ned by RFC2104 ( HMAC can use any hash function, typically either MD5 or SHA-1, but its strength depends on the strength of both the underlying hash function and the secret key. Although there are known weaknesses with the MD5 hash algorithm and SHA-1 is considered cryptographically stronger, those weaknesses do not compromise their use in HMACs. The iOS HMAC implementation supports use of the MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 digest algorithms. The HMAC output length is always the same as the digest length of the hashing algorithm used. As with the other hash functions discussed previously, HMACs can be generated manually or using a convenience method, and the following examples demonstrate how to use the convenience method. The HMAC example builds on the NSString+Hashing category you created earlier. To start, the category needs an additional method de finition and two additional libraries imported, as outlined in Listing 6-7. LISTING 6-7: HMAC Hash Addition (/App/Mobile-Banking/NSString+Hashing.h) ... import CommonCrypto/CommonHMAC.h import CommonCrypto/CommonCryptor.h interface NSString (Hashing) ... - (NSString)hmacWithKey:(NSString)key; end Importing CommonCryptor may seem out of place, but you need access to key size constant kCCKeySizeAES256 in your implementation of hmacWithKey:, as outlined in Listing 6-8. c06.indd 136 c06.indd 136 13/09/12 2:42 PM 13/09/12 2:42 PMMessage Integrity with Hashing and Encryption 137 ❘ LISTING 6-8: h macWithKey: Implementation (/App/Mobile-Banking/NSString+Hashing.m) - (NSString)hmacWithKey:(NSString)key // Pointer to UTF8 representations of strings const char ptr = self UTF8String; const char keyPtr = key UTF8String; // Implemented with SHA256, create appropriate buffer (32 bytes) unsigned char bufferCC_SHA256_DIGEST_LENGTH; // Create hash value CCHmac(kCCHmacAlgSHA256, // algorithm keyPtr, kCCKeySizeAES256, // key and key length ptr, strlen( ptr ), // data to hash and length buffer); // output buffer // Convert HMAC buffer value to pretty printed NSString NSMutableString output = NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH 2; for(int i = 0; i CC_SHA256_DIGEST_LENGTH; i++) output appendFormat:"%02x",bufferi; return output; Listing 6-8 includes the implementation of hmacWithKey:, which is similar to the hashWithType: method covered previously. The only two differences are the addition of a key and the restriction to use only the SHA-256 digest algorithm. UTF8 representations of your key and input data are c reated and passed to the CCHmac() function to create the HMAC. That function populates buffer with the HMAC value, and hmacWithKey: returns it as a string. You are probably wondering where the key value comes from and how it was chosen. Keys are essential to cryptographic security, and the importance of key strength cannot be overstated Without a properly secure and randomized key, you are opening the app up to numerous attacks. Depending on the data you attempt to protect, you could also be opening yourself up to potential lawsuits for cases such as data breaches and HIPAA violations. Recall the security overview from Figure 6-2: The encryption (E-Key) and MAC (M-Key) keys are the only two components of each step that are not transmitted with the request. The secrecy of those keys is your only hope at secur- ing the transmitted data Because keys are the lynchpin of the security model, you must choose one methodically. The key’s fi nal length should match the key length for the encryption algorithm (or HMAC). Anything shorter than the algorithm’s key length is NULL-padded until it reaches the full length, and thus weakens its randomness with each character it is short. If you must use user input data as the foundation for a key, salt the value by pre-pending a random or pseudo-random value to the input. If you need the ability to regenerate this key, make sure you store the salt used with your fi nal key value. Lastly, c06.indd 137 c06.indd 137 13/09/12 2:42 PM 13/09/12 2:42 PM138 CHAPTER 6 SECURING NETWORK TRAFFIC ❘ run the salted value through several thousand hash calculations using one of the routines discussed earlier, such as MD5 or SHA-1, and strip the appropriate number of bytes for use as your key. If your application requires user input as the basis for your encryption key, consider using the CCKeyDerivationPBKDF () function from the CommonCrypto / CommonKeyDerivation library. CCKeyDerivationPBKDF () returns a key value for the salt, derivation algorithm, rounds of deriva- tion, and output key length you specify. You can also use SecRandomCopyBytes() to generate a random array of bytes. Although it is common for developers to output various processing details to the log, you should never print the generated key to the console. Log fi les can be easily retrieved from the device, which could present a serious security fl aw if found by an attacker. One downside to preshared keys is that the application needs to plan for key versioning. It is inevi- table that you will come across a situation where you must modify your shared secret key, which requires you to deploy a new version of your application and then update the service tier. However, iOS users do not always diligently install app updates, and there is no mechanism to force them to do so. How do you handle users of the previous version of your application? You need to ensure that user transactions from your previous version will continue to be properly decrypted, verifi ed, and processed by the service. Key versioning solves this problem without needing to issue an app update; however, it must be included in the app’s development from the start. Following is an example of how to generate an HMAC using the method created in Listing 6-8. import "NSString+Hashing.h" ... // create mac input with to account, from account, amount, and transfer date NSString macCandidate = NSString stringWithFormat:"%%%%", "1234", // to account "4321", // from account "2300.00", // amount "2012-12-25 00:00:00"; // transfer date // generate mac NSString mac = macCandidate hmacWithKey:"065a62448fb75fce3764dcbe68f9908d"; ... Output: 51e66ca8fd8eb4bbe02fc6421e0dda1deb94f0c9518996a55bc7a4c242f1c8a9 This example uses a subset of the funds transfer payload as the MAC candidate; however, you can also use the entire payload. The concatenation order and attributes for the MAC candidate, which is the value you will hash, must be shared with the service tier to ensure proper decryption. If either the client or service tier operates under different assumptions, then the message integrity check will fail and nothing will be processed. Now that the MAC is transmitted and the service tier has decrypted the payload, the service must generate the comparison MAC. The following code snippet demonstrates how to generate an HMAC in PHP using the same concatenated input string used on the client side. The hash_hmac() PHP function accepts similar input as the HMac() function in iOS and allows you to specify the algorithm to use, the content to hash, and the key to be used. c06.indd 138 c06.indd 138 13/09/12 2:42 PM 13/09/12 2:42 PM