[iOS13]SHA256の値が取得出来なかった時の対処方法

4 min

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くらいでアプリを運用しているので、

これは使えないなという判断になり諦めました!

カテゴリー:
タグ:
関連記事

コメントを残す

メールアドレスが公開されることはありません。