3

What is the most updated way to get a HMAC 256 signature using CryptoKit and Swift 5? After trying different methods mentioned on HMAC SHA256 in Swift 4 and Implementing HMAC and SHA1 encryption in swift I still haven't been able to make the API request work. These two methods give me a different signature:

Using CryptoKit

import CryptoKit

let urlWithoutSignature = "https://api.binance.com/sapi/v1/capital/config/getall?timestamp=\(timeStamp)"
let secretString = "p23842nll3vc8vdfnsddfiupsd8cvsnlsdfs"
let key = SymmetricKey(data: secretString.data(using: .utf8)!)
let signature = HMAC<SHA256>.authenticationCode(for: urlWithoutSignature.data(using: .utf8)!, using: key)

let signatureString = Data(signature).map { String(format: "%02hhx", $0) }.joined()

Using a string extension

 import CommonCrypto
    
    let signatureString = urlWithoutSignature.hmac(key: secretString))
    
 extension String {

    func hmac(key: String) -> String {
      var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
      CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key, key.count, self, self.count, &digest)
      let data = Data(bytes: digest)
      return data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0))
     }
  }

How can I check that the signatures are correct? I can't compare them with the Postman one because the timestamp is always different.
The API docs

Maruta
  • 1,063
  • 11
  • 24
  • 1
    Your first example returns a hex string. Your second returns a Base64-encoded string. The output of HMAC is raw data. The question is whether that data is the same, and what encoding your API wants. – Rob Napier Apr 05 '21 at 18:47
  • Thank you, I am not sure but I think this requires the first type. I have the example code in Postman and I am running it on Xcode just changing the timestamp and the signature and it doesn't work – Maruta Apr 05 '21 at 20:10
  • 1
    On the doc (right panel), you have in fact a sample `$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j" (stdin)= c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71` That's the one you can base on to see what's wrong with your code. and you see what it crypts really, not the whole URL, just the query (not the api.binance, etc.) – Larme Apr 06 '21 at 08:27
  • thank you, actually I didn't know how to read that information on the right. I have confirmed that the signature that I am creating is correct and matches that example – Maruta Apr 06 '21 at 08:46

1 Answers1

1

let signatureString = Data(signature).base64EncodedString()

is equal to CommonCrypto's signatureString.

Kingiol
  • 1,145
  • 9
  • 9