Skip to content

Instantly share code, notes, and snippets.

@dkrusky
Created January 27, 2019 10:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dkrusky/9a2388a51f957065131439524ca077ca to your computer and use it in GitHub Desktop.
Save dkrusky/9a2388a51f957065131439524ca077ca to your computer and use it in GitHub Desktop.
hmac
// 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")));
}
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