Amazon API 叩くのに HMAC-SHA256 が必要でその過程の部分のメモ。
極力他ライブラリを使わない方向。CryptoSwift とか便利だとは思います。
CommonCrypto はいつ廃止されるかは知らないですが、ひとまずは最初から入っているもの、ということで(多分)。
大まかな作業順番。
- BridgingHeader.h で CommonCrypto/CommomHMAC.h を定義
- プロジェクトに BridgingHeader.h を追加する
- Xcode 9.0 のプロジェクト設定で Objective-C Bridging Header の設定に 1. のファイルを指定する
- ソース側で HMAC-SHA256 を計算するコードを書く
- 呼び出し側で呼び出す
具体的な手順。
1. BridgingHeader.h
#ifndef BridgingHeader_h
#define BridgingHeader_h
#import "CommonCrypto/CommonHMAC.h"
#endif /* BridgingHeader_h */
参考サイト
Swift: Bridging-Header 作成・設定方法- http://www.sirochro.com/note/swift-bridging-header-generate/
2. プロジェクトを開いた状態で [File] → [Add Files to …] から BridgingHeader.h を追加
3. プロジェクト設定に追加 [Build Settings] → [Swift Compiler – General] → [Objective-C Bridging Header]
だいぶ下の方の設定。
4. HMAC-SHA256 の関数を書く
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 {
var result: [CUnsignedChar]
if let ckey = key.cString(using: String.Encoding.utf8), let cdata = self.cString(using: String.Encoding.utf8) {
result = Array(repeating: 0, count: Int(algorithm.digestLength))
CCHmac(algorithm.HMACAlgorithm, ckey, ckey.count-1, cdata, cdata.count-1, &result)
} else {
fatalError("Nil returned when processing input strings as UTF8")
}
//return Data(bytes: result, count: result.count).base64EncodedString()
/**/
let hash = NSMutableString()
for val in result {
hash.appendFormat("%02hhx", val)
}
return hash as String
/**/
}
}
5. HMAC-SHA256 で指定した文字列の HMAC を求める
var targetString: String = "foobarbaz"
let secretKey: String = "ThisIsSecretKey"
let hashedValue = targetString.hmac(algorithm: .SHA256, key: secretKey)
print("HMAC-SHA256: [\(hashedValue)]")
上記 hmac 内のコメントアウトしている部分は Amazon API 用。その部分にたどり着くまで丸二日浪費・・・(涙
NSMutableString() からの行はネットで検索したら大抵引っかかるサンプルコードで紹介されているもの。普通はこっち?
Swift から始めたので [CUnsignedChar] とか cString とかよくわかっていないです。
上記サンプルは一応動いていたコードをベースにいくつか抽出していますが、動作しなかったらごめんなさい。
HMAC 調べていた時に見つけた投稿。HMACの解法への道しるべになる・・・か?と思い。
https://forums.developer.apple.com/thread/85873
この Apple Staff なんか偉そうやな、、Tricky なのを先に何とかしてくれ、、、いえ、してください。と思った。