iOS13にした所、SHA256の値がなんかおかしい・・・
値が変わっているのはわかるんだけど、どうしたら前みたいに取得できるのかわからない。
そんな疑問に答えていきます。
この記事でわかる事
- iOS13でのSHA256値の取り方
目次
iOS12以前での取得方法
-(NSString *)sha256: (NSString *) text
{
const char *s = [text cStringUsingEncoding: NSASCIIStringEncoding];
NSData *data = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH]={0};
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSData *out = [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
NSString *resultString = [out description];
resultString = [resultString stringByReplacingOccurrencesOfString:@" " withString:@""];
resultString = [resultString stringByReplacingOccurrencesOfString:@"<" withString:@""];
resultString = [resultString stringByReplacingOccurrencesOfString:@">" withString:@""];
return resultString;
}
かなり前から使っているObjective-Cのコードです
結果は
7c9949409a14b38c69f09791b1bf2a0b89954fc857d4c3f117ea0a08ad3aa3ab
取得できています。
iOS13でSHA256値がどのように変わったか
同じコードをiOS13で動かした場合どうなるか見てみましょう
{length=32,bytes=0x7c9949409a14b38c69f09791b1bf2a0b…17ea0a08ad3aa3ab}
lengthがついたり、前の結果とはかなり違う感じになっていました
このままでは使いにくいので次のような対応をしました
どう対応したか(Swift版)
Swiftでの対応は以下となります
import Foundation
enum CryptoAlgorithm {
case MD5, SHA256
var digestLength: Int {
var result: Int32 = 0
switch self {
case .MD5: result = CC_MD5_DIGEST_LENGTH
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
}
return Int(result)
}
}
extension String {
var md5: String { return digest(string: self, algorithm: .MD5) }
var sha256: String { return digest(string: self, algorithm: .SHA256) }
func digest(string: String, algorithm: CryptoAlgorithm) -> String {
var result: [CUnsignedChar]
let digestLength = Int(algorithm.digestLength)
if let cdata = string.cString(using: String.Encoding.utf8) {
result = Array(repeating: 0, count: digestLength)
switch algorithm {
case .MD5: CC_MD5(cdata, CC_LONG(cdata.count-1), &result)
case .SHA256: CC_SHA256(cdata, CC_LONG(cdata.count-1), &result)
}
} else {
fatalError("Nil returned when processing input strings as UTF8")
}
return (0..<digestLength).reduce("") { $0 + String(format: "%02hhx", result[$1])}
}
}
呼び出し側
let text = "foo bar buz"
print(" MD5: \(text.md5)")
print("SHA256: \(text.sha256)")
実行結果
MD5: 0844c8a9954059836ec1e494fccddb5f
SHA256: 004467f99020d53e57fb79a99bcb8fd5ee646a2bb8542f0110266d796acbd665
おまけ
iOS13からApple CryptoKitというのが追加されています
Apple CryptoKit
https://developer.apple.com/documentation/cryptokit
iOS13の時だけこれ使えばいけると思っていれてみました。
import CryptoKit
let hash = SHA256.hash(data: data)
これだけで使えるなんて、楽だなぁと思って実行しました
結果も問題なくOKだったのでこれでいけると思ったのですが
アーカイブしてみると・・・no such module ‘CryptoKit’ のエラーでアーカイブできません
色々試してみて解消の方法が
iOS Deployment Targetを13にするとアーカイブできました
今はまだiOS Deployment Targetが10や11くらいでアプリを運用しているので、
これは使えないなという判断になり諦めました!