Created
January 27, 2019 10:38
-
-
Save dkrusky/9a2388a51f957065131439524ca077ca to your computer and use it in GitHub Desktop.
hmac
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// API details | |
String APIKey = "xxxxxxx"; | |
String APISecret = "xxxxxxx"; | |
String APIEndpoint = "https://www.domain.com/api/"; | |
String APIVersion = "1.0"; | |
// an example API call | |
String action = "/client/authenticate/user/pass/0/xxxx" | |
// build complete API call | |
String callWithTimestamp = APIEndpoint + APIVersion + "/" + action + "?" + Instant.now().getEpochSecond(); | |
// get signature from endpoint request | |
String signature = hmac( APISecret, callWithTimestamp); | |
/** | |
build the request and make the call to 'callWithTimestamp' value, using the 'signature' value as the X-Signature header | |
make sure you are using the appropriate HTTP method as per the API documentation (GET to read data, PUT/POST to store data, etc) | |
**/ | |
// helper method to generate hmac SHA256 + hex encoded UTF-8 signature | |
public String hmac(String key, String data) throws Exception { | |
Mac mac = Mac.getInstance("HmacSHA256"); | |
SecretKeySpec sk = new SecretKeySpec(key.getBytes("UTF-8"),mac.getAlgorithm()); | |
mac.init(sk); | |
return Hex.encodeHexString(mac.doFinal(data.getBytes("UTF-8"))); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import CommonCrypto | |
class API { | |
let APIKey = "xxxxxxx" | |
let APISecret = "xxxxxxx" | |
let APIVersion = "1.0" | |
let APIEndpoint = "https://www.domain.com/api/" | |
//APPError enum which shows all possible errors | |
enum APPError: Error { | |
case networkError(Error) | |
case dataNotFound | |
case jsonParsingError(Error) | |
case invalidStatusCode(Int) | |
} | |
//Result enum to show success or failure | |
enum Result<T> { | |
case success(T) | |
case failure(APPError) | |
} | |
//dataRequest which sends request to given URL and convert to Decodable Object | |
func get<T: Decodable>(with action: String, objectType: T.Type, completion: @escaping (Result<T>) -> Void) { | |
//create the url with NSURL | |
let timestamp = String(Int(Date().timeIntervalSince1970)) | |
let callWithTimestamp = APIEndpoint + APIVersion + "/" + action + "?" + timestamp | |
let signature = callWithTimestamp.hmac(key: APISecret) | |
let dataURL = URL(string: callWithTimestamp)! //change the url | |
//create the session object | |
let session = URLSession.shared | |
//now create the URLRequest object using the url object | |
var request = URLRequest(url: dataURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60) | |
request.httpMethod = "GET" | |
request.setValue(APIKey, forHTTPHeaderField: "x-api-key") | |
request.setValue(signature, forHTTPHeaderField: "x-signature") | |
//create dataTask using the session object to send data to the server | |
let task = session.dataTask(with: request, completionHandler: { data, response, error in | |
guard error == nil else { | |
completion(Result.failure(APPError.networkError(error!))) | |
return | |
} | |
guard let data = data else { | |
completion(Result.failure(APPError.dataNotFound)) | |
return | |
} | |
do { | |
//create decodable object from data | |
let decodedObject = try JSONDecoder().decode(objectType.self, from: data) | |
completion(Result.success(decodedObject)) | |
} catch let error { | |
completion(Result.failure(APPError.jsonParsingError(error as! DecodingError))) | |
} | |
}) | |
task.resume() | |
} | |
} | |
// helper method to generate hmac SHA256 + hex encoded UTF-8 signature | |
extension String { | |
func hmac(key: String) -> String { | |
let cKey = key.cString(using: String.Encoding.utf8) | |
let cData = self.cString(using: String.Encoding.utf8) | |
var result = [CUnsignedChar](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) | |
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result) | |
let hmacData:NSData = NSData(bytes: result, length: (Int(CC_SHA256_DIGEST_LENGTH))) | |
var bytes = [UInt8](repeating: 0, count: hmacData.length) | |
hmacData.getBytes(&bytes, length: hmacData.length) | |
var hexString = "" | |
for byte in bytes { | |
hexString += String(format:"%02hhx", UInt8(byte)) | |
} | |
return hexString | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment