0Day Forums
How to hash NSString with SHA1 in Swift? - Printable Version

+- 0Day Forums (https://zeroday.vip)
+-- Forum: Coding (https://zeroday.vip/Forum-Coding)
+--- Forum: Swift (https://zeroday.vip/Forum-Swift)
+--- Thread: How to hash NSString with SHA1 in Swift? (/Thread-How-to-hash-NSString-with-SHA1-in-Swift)



How to hash NSString with SHA1 in Swift? - grietjeosbjhoss - 07-18-2023

In objective-c it looks like this:

#include <sys/xattr.h>

@implementation NSString (reverse)

-(NSString*)sha1
{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (int)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}

@end

I need something like this with Swift, is it possible?

Please, show work example.


RE: How to hash NSString with SHA1 in Swift? - orrery280 - 07-18-2023

For one-liner guy, no need to use the creepy swift extension

Swift 5.7.3

import CryptoKit

func mysha1(_ str:String) -> String {

return Insecure.SHA1.hash(data: str.data(using: String.Encoding.utf8)!).map
{ String(format: "%02x", $0) }.joined()

}


RE: How to hash NSString with SHA1 in Swift? - garbles582789 - 07-18-2023

A version for Swift 5 that uses CryptoKit on iOS 13 and falls back to CommonCrypto otherwise:

```swift
import CommonCrypto
import CryptoKit
import Foundation

private func hexString(_ iterator: Array<UInt8>.Iterator) -> String {
return iterator.map { String(format: "%02x", $0) }.joined()
}

extension Data {

public var sha1: String {
if #available(iOS 13.0, *) {
return hexString(Insecure.SHA1.hash(data: self).makeIterator())
} else {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
self.withUnsafeBytes { bytes in
_ = CC_SHA1(bytes.baseAddress, CC_LONG(self.count), &digest)
}
return hexString(digest.makeIterator())
}
}

}
```

Usage:

```
let string = "The quick brown fox jumps over the lazy dog"
let hexDigest = string.data(using: .ascii)!.sha1
assert(hexDigest == "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12")
```

Also available via Swift package manager:

[To see links please register here]




RE: How to hash NSString with SHA1 in Swift? - quashed18301 - 07-18-2023

With `CryptoKit` added in iOS13, we now have native Swift API:

```swift
import Foundation
import CryptoKit

// CryptoKit.Digest utils
extension Digest {
var bytes: [UInt8] { Array(makeIterator()) }
var data: Data { Data(bytes) }

var hexStr: String {
bytes.map { String(format: "%02X", $0) }.joined()
}
}

func example() {
guard let data = "hello world".data(using: .utf8) else { return }
let digest = Insecure.SHA1.hash(data: data)
print(digest.data) // 20 bytes
print(digest.hexStr) // 2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED
}
```


RE: How to hash NSString with SHA1 in Swift? - forklift488 - 07-18-2023

Your Objective-C code (using a `NSString` category) can be directly translated to Swift
(using a `String` extension).

First you have to create a "bridging header" and add

#import <CommonCrypto/CommonCrypto.h>

Then:

extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
for byte in digest {
output.appendFormat("%02x", byte)
}
return output as String
}
}

println("Hello World".sha1())

This can be written slightly shorter and Swifter as

extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = map(digest) { String(format: "%02hhx", $0) }
return "".join(hexBytes)
}
}

**Update for Swift 2:**

extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")
}
}

To return a Base-64 encoded string instead of a hex encoded string,
just replace

let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")

with

return NSData(bytes: digest, length: digest.count).base64EncodedStringWithOptions([])


**Update for Swift 3:**

extension String {
func sha1() -> String {
let data = self.data(using: String.Encoding.utf8)!
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1($0, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}
}

To return a Base-64 encoded string instead of a hex encoded string,
just replace

let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()

by

return Data(bytes: digest).base64EncodedString()

**Update for Swift 4:**

The bridging header file is no longer needed, one can `import CommonCrypto` instead:

import CommonCrypto

extension String {
func sha1() -> String {
let data = Data(self.utf8)
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1($0, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}
}

**Update for Swift 5:**

The `Data.withUnsafeBytes()` method now calls the closure with an `UnsafeRawBufferPointer` to, and `baseAddress` is used to pass the initial address to the C function:

import CommonCrypto

extension String {
func sha1() -> String {
let data = Data(self.utf8)
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1($0.baseAddress, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}
}



RE: How to hash NSString with SHA1 in Swift? - jannajevn - 07-18-2023

Yes, it's possible, copy this class into your project.
[

[To see links please register here]

][1]

And it will be easy like:

SHA1.hexString(from: "myPhrase" )!

**Tested for swift 3 and swift 4.**

[1]:

[To see links please register here]




RE: How to hash NSString with SHA1 in Swift? - excellency10 - 07-18-2023

We can extract logic for encrypting string using sha1 for three steps:

1. Convert string to Data object
2. Encrypt data using SHA1 function to Data
3. Convert data object to hex string

IMHO it's much more readable and this version doesn't require NSData.

extension String {

var sha1: String {
guard let data = data(using: .utf8, allowLossyConversion: false) else {
// Here you can just return empty string or execute fatalError with some description that this specific string can not be converted to data
}
return data.digestSHA1.hexString
}

}

fileprivate extension Data {

var digestSHA1: Data {
var bytes: [UInt8] = Array(repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))

withUnsafeBytes {
_ = CC_SHA1($0, CC_LONG(count), &bytes)
}

return Data(bytes: bytes)
}

var hexString: String {
return map { String(format: "%02x", UInt8($0)) }.joined()
}

}



RE: How to hash NSString with SHA1 in Swift? - regurgitation373 - 07-18-2023

To get the result as `NSData`, provided that you included `<CommonCrypto/CommonCrypto.h>` in your bridging header:

extension NSData {

func sha1() -> NSData? {
let len = Int(CC_SHA1_DIGEST_LENGTH)
let digest = UnsafeMutablePointer<UInt8>.alloc(len)
CC_SHA1(bytes, CC_LONG(length), digest)
return NSData(bytesNoCopy: UnsafeMutablePointer<Void>(digest), length: len)
}
}

Also uses proper pointer allocation. Invoke it like this:

myString.dataUsingEncoding(NSUTF8StringEncoding)?.sha1()

If you need a hex representation of `NSData` have a look at my other [answer](

[To see links please register here]

).


RE: How to hash NSString with SHA1 in Swift? - alkanet834 - 07-19-2023

Yes, it's possible: *make that objective-c code accessible from swift*

See [documentation](

[To see links please register here]

).

I would avoid rewriting it in swift if you won't get any benefit (such as using swift-specific features).

Also, in a project I am working on I used some objective-c code similar to yours to handle hashes. At beginning I started writing it in swift, then I realized that it was just easier and better to reuse old good obj-c.