Sha256 in Swift

SHA256 in swift

You have to convert explicitly between Int and CC_LONG, because Swift does not
do implicit conversions, as in (Objective-)C.

You also have to define hash as an array of the required size.

func sha256(data : NSData) -> NSData {
var hash = [UInt8](count: Int(CC_SHA256_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA256(data.bytes, CC_LONG(data.length), &hash)
let res = NSData(bytes: hash, length: Int(CC_SHA256_DIGEST_LENGTH))
return res
}

Alternatively, you can use NSMutableData to allocate the needed buffer:

func sha256(data : NSData) -> NSData {
let res = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))
CC_SHA256(data.bytes, CC_LONG(data.length), UnsafeMutablePointer(res.mutableBytes))
return res
}

Update for Swift 3 and 4:

func sha256(data : Data) -> Data {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA256($0, CC_LONG(data.count), &hash)
}
return Data(bytes: hash)
}

Update for Swift 5:

func sha256(data : Data) -> Data {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash)
}
return Data(hash)
}

How to Hash sha256 in swift 4 with a secret key?

I admit that it can be confusing to get everything together but the final solution is quite simple:

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.map { String(format: "%02hhx", $0) }.joined()
}

}

Example:

let result = "test".hmac(key: "test")

Result:

88cd2108b5347d973cf39cdf9053d7dd42704876d8c9a9bd8e2d168259d3ddf7

Creating SHA256 hash with swift4

You can use like this :

func ccSha256(data: Data) -> Data {
var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH))

_ = digest.withUnsafeMutableBytes { (digestBytes) in
data.withUnsafeBytes { (stringBytes) in
CC_SHA256(stringBytes, CC_LONG(data.count), digestBytes)
}
}
return digest
}

You can call like this :

let str = "givesomestringtoencode"
let data = ccSha256(data: str.data(using: .utf8)!)
print("sha256 String: \(data.map { String(format: "%02hhx", $0) }.joined())")

Add the below in bridging header file:

#import <CommonCrypto/CommonHMAC.h>

SHA256 Swift to Objective C equivalence

Working with raw bytes in Objective-C is generally a little more straightforward than Swift. An implementation like this should be equivalent.

#define RSA_2048_ASN1_HDR_LEN 24

- (NSString *)sha256:(NSData *)data {
NSMutableData *keyWithHeader = [NSMutableData dataWithBytes:rsa2048Asn1Header length:RSA_2048_ASN1_HDR_LEN];
[keyWithHeader appendData:data];
UInt8 hash[CC_SHA256_DIGEST_LENGTH] = { 0 };
CC_SHA256(keyWithHeader.bytes, (CC_LONG) keyWithHeader.length, hash);
return [[NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH] base64EncodedStringWithOptions:0];
}

Note that you'll also need to import the common crypto library into your Objective-C file as well:

#import <CommonCrypto/CommonDigest.h>

HMAC SHA256 in Swift 4

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

SHA256: different output in Swift and Java?

Short answer

It seems your SHA-256 hash algorithm implementation done in the Swift language is correct.

Long answer

The Java example you are referring to does not just contain the SHA-256 hash algorithm implementation, but also contains the HMAC-SHA-512 algorithm implementation to calculate the signature (?).

All in all, if there is a need of the SHA-256 algorithm only, please check the following draft Java implementation:

package com.thecompany.test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class Program {
public static void main(final String[] args) throws NoSuchAlgorithmException {
// Input.
final String input = "1234nonce=1234";

// Processing.
final byte[] output = sha256(input);

// Output.
System.out.printf("Signed output: %s.%n", Arrays.toString(output));

final List<Integer> unsignedOutput = unsignedIntStream(output)
.boxed()
.collect(Collectors.toList());
System.out.printf("Unsigned output: %s.%n", unsignedOutput);
}

private static IntStream unsignedIntStream(final byte[] array) {
return IntStream
.range(0, array.length)
.map(index -> Byte.toUnsignedInt(array[index]));
}

private static byte[] sha256(final String text) throws NoSuchAlgorithmException {
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
return digest.digest(text.getBytes(StandardCharsets.UTF_8));
}
}

The program produces the following output:

Signed output: [-38, -49, -114, 73, 87, -21, -46, 73, -55, 67, 19, 33, 57, -110, 69, 48, 51, 56, 0, -44, -84, 114, 118, 31, 102, 19, -81, 51, -103, -26, -113, 67].
Unsigned output: [218, 207, 142, 73, 87, 235, 210, 73, 201, 67, 19, 33, 57, 146, 69, 48, 51, 56, 0, 212, 172, 114, 118, 31, 102, 19, 175, 51, 153, 230, 143, 67].

Hope this helps.

How to use common crypto and/or calculate sha256 in swift 2 & 3

Add a bridging header and add the import to it:

#import <CommonCrypto/CommonDigest.h>

Swift 3:

func sha256(string: String) -> Data? {
guard let messageData = string.data(using:String.Encoding.utf8) else { return nil }
var digestData = Data(count: Int(CC_SHA256_DIGEST_LENGTH))

_ = digestData.withUnsafeMutableBytes {digestBytes in
messageData.withUnsafeBytes {messageBytes in
CC_SHA256(messageBytes, CC_LONG(messageData.count), digestBytes)
}
}
return digestData
}

// Test

let shaData = sha256(string:"Here is the test string")
let shaHex = shaData!.map { String(format: "%02hhx", $0) }.joined()
print("shaHex: \(shaHex)")

shaHex: 6f5c446883a3049caf8368b4bad2d2ff045a39d467ee20a8d34d5698e649fe21

Swift 2:

func sha256(string string: String) -> NSData {
let digest = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!
if let data :NSData = string.dataUsingEncoding(NSUTF8StringEncoding) {
CC_SHA256(data.bytes, CC_LONG(data.length),
UnsafeMutablePointer<UInt8>(digest.mutableBytes))
}
return digest
}

//Test:

let digest = sha256(string:"Here is the test string")
print("digest: \(digest)")

Output:

digest: 6f5c4468 83a3049c af8368b4 bad2d2ff 045a39d4 67ee20a8 d34d5698 e649fe21

Example from sunsetted documentation section:

HMAC with MD5, SHA1, SHA224, SHA256, SHA384, SHA512 (Swift 3+)

These functions will hash either String or Data input with one of eight cryptographic hash algorithms.

The name parameter specifies the hash function name as a String
Supported functions are MD5, SHA1, SHA224, SHA256, SHA384 and SHA512

This example requires Common Crypto

It is necessary to have a bridging header to the project:

#import <CommonCrypto/CommonCrypto.h>

Add the Security.framework to the project.

These functions takes a hash name, message to be hashed, a key and return a digest:



hashName: name of a hash function as String
message: message as Data
key: key as Data
returns: digest as Data
func hmac(hashName:String, message:Data, key:Data) -> Data? {
let algos = ["SHA1": (kCCHmacAlgSHA1, CC_SHA1_DIGEST_LENGTH),
"MD5": (kCCHmacAlgMD5, CC_MD5_DIGEST_LENGTH),
"SHA224": (kCCHmacAlgSHA224, CC_SHA224_DIGEST_LENGTH),
"SHA256": (kCCHmacAlgSHA256, CC_SHA256_DIGEST_LENGTH),
"SHA384": (kCCHmacAlgSHA384, CC_SHA384_DIGEST_LENGTH),
"SHA512": (kCCHmacAlgSHA512, CC_SHA512_DIGEST_LENGTH)]
guard let (hashAlgorithm, length) = algos[hashName] else { return nil }
var macData = Data(count: Int(length))

macData.withUnsafeMutableBytes {macBytes in
message.withUnsafeBytes {messageBytes in
key.withUnsafeBytes {keyBytes in
CCHmac(CCHmacAlgorithm(hashAlgorithm),
keyBytes, key.count,
messageBytes, message.count,
macBytes)
}
}
}
return macData

}


hashName: name of a hash function as String
message: message as String
key: key as String
returns: digest as Data
func hmac(hashName:String, message:String, key:String) -> Data? {
let messageData = message.data(using:.utf8)!
let keyData = key.data(using:.utf8)!
return hmac(hashName:hashName, message:messageData, key:keyData)
}


hashName: name of a hash function as String
message: message as String
key: key as Data
returns: digest as Data
func hmac(hashName:String, message:String, key:Data) -> Data? {
let messageData = message.data(using:.utf8)!
return hmac(hashName:hashName, message:messageData, key:key)
}

// Examples

let clearString = "clearData0123456"
let keyString = "keyData8901234562"
let clearData = clearString.data(using:.utf8)!
let keyData = keyString.data(using:.utf8)!
print("clearString: \(clearString)")
print("keyString: \(keyString)")
print("clearData: \(clearData as NSData)")
print("keyData: \(keyData as NSData)")

let hmacData1 = hmac(hashName:"SHA1", message:clearData, key:keyData)
print("hmacData1: \(hmacData1! as NSData)")

let hmacData2 = hmac(hashName:"SHA1", message:clearString, key:keyString)
print("hmacData2: \(hmacData2! as NSData)")

let hmacData3 = hmac(hashName:"SHA1", message:clearString, key:keyData)
print("hmacData3: \(hmacData3! as NSData)")

Output:

clearString: clearData0123456
keyString: keyData8901234562
clearData: <636c6561 72446174 61303132 33343536>
keyData: <6b657944 61746138 39303132 33343536 32>

hmacData1: <bb358f41 79b68c08 8e93191a da7dabbc 138f2ae6>
hmacData2: <bb358f41 79b68c08 8e93191a da7dabbc 138f2ae6>
hmacData3: <bb358f41 79b68c08 8e93191a da7dabbc 138f2ae6>

MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 (Swift 3+)

These functions will hash either String or Data input with one of eight cryptographic hash algorithms.

The name parameter specifies the hash function name as a String

Supported functions are MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384 and SHA512
a
This example requires Common Crypto

It is necessary to have a bridging header to the project:

#import <CommonCrypto/CommonCrypto.h>

Add the Security.framework to the project.



This function takes a hash name and String to be hashed and returns a Data:


name: A name of a hash function as a String
string: The String to be hashed
returns: the hashed result as Data
func hash(name:String, string:String) -> Data? {
let data = string.data(using:.utf8)!
return hash(name:name, data:data)
}

Examples:

let clearString = "clearData0123456"
let clearData = clearString.data(using:.utf8)!
print("clearString: \(clearString)")
print("clearData: \(clearData as NSData)")

let hashSHA256 = hash(name:"SHA256", string:clearString)
print("hashSHA256: \(hashSHA256! as NSData)")

let hashMD5 = hash(name:"MD5", data:clearData)
print("hashMD5: \(hashMD5! as NSData)")

Output:

clearString: clearData0123456
clearData: <636c6561 72446174 61303132 33343536>

hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>


Related Topics



Leave a reply



Submit