I have a string and a key, which i want to generate an HMAC SHA256 from it. Although i'm using 2 libs
IDZSwiftCommonCrypto and CryptoSwift
and this answer
Nothing really worked for me. My source of truth are those 2 websites
https://myeasywww.appspot.com/utility/free/online/Crypt_Decrypt-MD5-AES-HMAC-SHA-DES-RABBIT/en?command=UTILITY&ID=2
and
https://www.freeformatter.com/hmac-generator.html#ad-output
Which they always generate the correct hash key for my case. Any idea in what can work here? Some code samples
For IDZSwiftCommonCrypto
func getHMacSHA256(forMessage message: String, key: String) -> String? {
let hMacVal = HMAC(algorithm: HMAC.Algorithm.sha256, key: key).update(string: message)?.final()
if let encryptedData = hMacVal {
let decData = NSData(bytes: encryptedData, length: Int(encryptedData.count))
let base64String = decData.base64EncodedString(options: .lineLength64Characters)
print("base64String: \(base64String)")
return base64String
} else {
return nil
}
}
And for CryptoSwift
let password: Array<UInt8> = Array(payload.utf8)
let salt: Array<UInt8> = Array("somekey".utf8)
let signedBody = try? HKDF(password: password, salt: salt, variant: .sha256).calculate()
But nothing really works like the sources of truth.Any idea?
1 HMAC and SHA1 are not encryption. Common Crypto can be used from Swift and provide the primitives you need. – zaph Nov 17, 2014 at 13:50 The answer you link to is in Swift and @maksimov has also provided an answer. Add to the question your code that is using this and someone can probably find the problem. – zaph Nov 17, 2014 at 15:34
HMACSHA256 accepts keys of any size, and produces a hash sequence 256 bits in length. Initializes a new instance of the HMACSHA256 class with a randomly generated key. Initializes a new instance of the HMACSHA256 class with the specified key data. The hash size produced by the HMAC SHA256 algorithm, in bits.
Groovy HMAC SHA256 It is mostly java code but there are some slight differences. Adapted from Dev Takeout - Groovy HMAC/SHA256 representation.
The HMAC process mixes a secret key with the message data, hashes the result with the hash function, mixes that hash value with the secret key again, and then applies the hash function a second time. The output hash is 256 bits in length.
import CryptoKit
let secretString = "my-secret"
let key = SymmetricKey(data: Data(secretString.utf8))
let string = "An apple a day keeps anyone away, if you throw it hard enough"
let signature = HMAC<SHA256>.authenticationCode(for: Data(string.utf8), using: key)
print(Data(signature).map { String(format: "%02hhx", $0) }.joined()) // 1c161b971ab68e7acdb0b45cca7ae92d574613b77fca4bc7d5c4effab89dab67
I've been using this:
import Foundation
enum CryptoAlgorithm {
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
var HMACAlgorithm: CCHmacAlgorithm {
var result: Int = 0
switch self {
case .MD5: result = kCCHmacAlgMD5
case .SHA1: result = kCCHmacAlgSHA1
case .SHA224: result = kCCHmacAlgSHA224
case .SHA256: result = kCCHmacAlgSHA256
case .SHA384: result = kCCHmacAlgSHA384
case .SHA512: result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}
var digestLength: Int {
var result: Int32 = 0
switch self {
case .MD5: result = CC_MD5_DIGEST_LENGTH
case .SHA1: result = CC_SHA1_DIGEST_LENGTH
case .SHA224: result = CC_SHA224_DIGEST_LENGTH
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
case .SHA384: result = CC_SHA384_DIGEST_LENGTH
case .SHA512: result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
extension String {
func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
let str = self.cString(using: String.Encoding.utf8)
let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = algorithm.digestLength
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
let keyStr = key.cString(using: String.Encoding.utf8)
let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
let digest = stringFromResult(result: result, length: digestLen)
result.deallocate(capacity: digestLen)
return digest
}
private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
let hash = NSMutableString()
for i in 0..<length {
hash.appendFormat("%02x", result[i])
}
return String(hash).lowercased()
}
}
You'll need to add #import <CommonCrypto/CommonHMAC.h>
to your Objective-C bridging header.
Source: @thevalyreangroup on this github thread
You're doing it wrong with CryptoSwift.
For future readers, here's how to do it:
let result = try! HMAC(key: key, variant: .sha256).authenticate(message.bytes)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With