libb2sでBLAKE2s

BLEKE2sはハッシュ化を行うアルゴリズムです。BLE通信を行う際にBLAKE2sで暗号化を行うことになったのでiOSでBLAKE2sを対応しているライブラリを探したのですが全然見つからず、最後に見つけたのがlibb2sでした。

現在はcarthageには対応していないようなのでcocoaPodでいれる必要がありそうです。

BLAKE2sで暗号化してみる

出力先を領域をあらかじめ確保しておく必要があります。

確保しておかない場合値を書き込む領域がそもそも存在しないのでエラーにはなりませんがnilの状態になります。

override func viewDidLoad() {
    super.viewDidLoad()
    
    //暗号化したいbyteデータ
    let bytes: [Int8] = [49,50,51,52,53,54,55,56,57]

    //出力されるメモリ領域をあらかじめ確保しておく必要がある
    var outData =  Data([1,1,1,1])
    print("before:\(outData.hexEncodedString())")
    
    let po = outData.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) -> UnsafeMutablePointer<UInt8> in
        return ptr
    }
    blake2s(po, bytes, nil, 4, bytes.count, 0)
    print("after:\(outData.hexEncodedString())")
}

デバッグログ

コンソールを確認するとこんな感じでハッシュ化してくれていました。

before:01010101
after:6ade0c07

StringとDataのExtension

extension String {
    func hexStringtoAscii() -> String {
        let pattern = "(0x)?([0-9a-f]{2})"
        let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)
        let nsString = self as NSString
        let range = NSRange(location: 0, length: nsString.length)
        let matches = regex.matches(in: self, options: [], range: range)
        let characters = matches.map {
            Character(UnicodeScalar(UInt32(nsString.substring(with: $0.range(at: 2)), radix: 16)!)!)
        }
        return String(characters)
    }
}
extension Data {
    struct HexEncodingOptions: OptionSet {
        let rawValue: Int
        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
    }
    
    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
        return map { String(format: format, $0) }.joined()
    }
}


※2019/4/25日追記

Swift5でポインタ周りが少し変わったようです。ポインタがクロージャを抜けると解放されるようになった為、下記のようにblake2sを行う場所をクロージャ内に移さないと正しくhash化されなくなりました。

let outData =  Data([1,1,1,1])
print("before:\(outData.hexEncodedString())")

var data = outData
_ = data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) -> UnsafeMutablePointer<UInt8> in
    blake2s(ptr, bytes, nil, 4, bytes.count, 0)
    return ptr
}
print("after:\(data.hexEncodedString())")
Swift

次の記事

SpriteKitで図形を描画する