Swift에서 SHA1로 NSString을 해시하는 방법은 무엇입니까?
Objective-c에서는 다음과 같이 보입니다.
#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
Swift로 이와 같은 것이 필요합니다. 가능합니까?
작품 예를 보여주세요.
Objective-C 코드 ( NSString
카테고리 사용)를 Swift로 직접 변환 할 수 있습니다 ( String
확장 프로그램 사용).
먼저 "브리징 헤더"를 만들고
#import <CommonCrypto/CommonCrypto.h>
그때:
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())
이것은 약간 짧고 신속하게 작성할 수 있습니다.
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)
}
}
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("")
}
}
16 진수로 인코딩 된 문자열 대신 Base-64로 인코딩 된 문자열을 반환하려면
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")
와
return NSData(bytes: digest, length: digest.count).base64EncodedStringWithOptions([])
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()
}
}
16 진수로 인코딩 된 문자열 대신 Base-64로 인코딩 된 문자열을 반환하려면
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
으로
return Data(bytes: digest).base64EncodedString()
Swift 4 업데이트 :
브리징 헤더 파일은 더 이상 필요하지 않으며 import CommonCrypto
대신 다음을 수행 할 수 있습니다 .
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()
}
}
Swift 5 업데이트 :
이 Data.withUnsafeBytes()
메서드는 이제 UnsafeRawBufferPointer
to를 baseAddress
사용 하여 클로저를 호출 하고 C 함수에 초기 주소를 전달하는 데 사용됩니다.
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()
}
}
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.
Yes, it's possible, copy this class into your project. https://github.com/idrougge/sha1-swift
And it will be easy like:
SHA1.hexString(from: "myPhrase" )!
Tested for swift 3 and swift 4.
With CryptoKit
added in iOS13, we now have native Swift API:
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
}
We can extract logic for encrypting string using sha1 for three steps:
- Convert string to Data object
- Encrypt data using SHA1 function to Data
- 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()
}
}
Yes, it's possible: make that objective-c code accessible from swift
See documentation.
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.
ReferenceURL : https://stackoverflow.com/questions/25761344/how-to-hash-nsstring-with-sha1-in-swift
'IT Share you' 카테고리의 다른 글
Mongo에서 대소 문자를 구분하지 않는 검색 (0) | 2021.01.09 |
---|---|
프로그래밍 방식으로 textSize 설정 (0) | 2021.01.09 |
FormData (HTML5 Object)를 JSON으로 변환하는 방법 (0) | 2021.01.09 |
Git 치명적 : 프로토콜 'https'가 지원되지 않습니다. (0) | 2021.01.09 |
Rails 콘솔에서 이메일 보내기 (0) | 2021.01.09 |