以下の暗号化・復号化メソッドをswift3対応させたのですが、  
戻り値をStringに変換する際にクラッシュするようになりました。

swift2.2

```

    func AES128Crypt(data data:NSData,  keyData:NSData, operation:Int) -> NSData? {
    
        let keyBytes = UnsafePointer<UInt8>(keyData.bytes)
    
        let dataLength = Int(data.length)
        let dataBytes = UnsafePointer<UInt8>(data.bytes)
    
        let cryptData: NSMutableData! = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
        let cryptPointer = UnsafeMutablePointer<UInt8>(cryptData.mutableBytes)
        let cryptLength = size_t(cryptData.length)
    
        let keyLength = size_t(kCCKeySizeAES128)
        let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
    
        var numBytesEncrypted :size_t = 0
    
        let cryptStatus = CCCrypt(CCOperation(operation), algoritm,
                                  options,
                                  keyBytes, keyLength,
                                  nil,
                                  dataBytes, dataLength,
                                  cryptPointer, cryptLength,
                                  &numBytesEncrypted)
    
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
    
            cryptData.length = Int(numBytesEncrypted)
    
        } else {
            print("\(#line) Error: \(cryptStatus)")
        }
    
        return cryptData
    }
    
```

swift3対応後

```

    func AES128Crypt(data:Data,  keyData:Data, operation:Int) -> Data? {
    
        let keyBytes = (keyData as NSData).bytes.bindMemory(to: UInt8.self, capacity: keyData.count)
    
        let dataLength = Int(data.count)
        let dataBytes = (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count)
    
        let cryptData: NSMutableData! = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
        //以下を変更
        let cryptInt = Int(bitPattern: cryptData.mutableBytes)
        guard let cryptPointer = UnsafeMutablePointer<UInt8>(bitPattern: cryptInt) else {
            print("\(#line) Error: cryptPointer is nil")
            return nil
        }
        //変更終了
        let cryptLength = size_t(cryptData.length)
    
        let keyLength = size_t(kCCKeySizeAES128)
        let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
    
        var numBytesEncrypted :size_t = 0
    
        let cryptStatus = CCCrypt(CCOperation(operation), algoritm,
                                  options,
                                  keyBytes, keyLength,
                                  nil,
                                  dataBytes, dataLength,
                                  cryptPointer, cryptLength,
                                  &numBytesEncrypted)
    
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
    
            cryptData.length = Int(numBytesEncrypted)
    
        } else {
            print("\(#line) Error: \(cryptStatus)")
        }
    
        return cryptData as Data?
    }
    
```

エラー発生箇所

```

    let encryptStr = String(data: encryptData, encoding: String.Encoding.utf8)!
    
```

エラーメッセージ

```

    Thread 1: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
    
```

エラーが示す箇所

```

    -> 0x7ef9e0 <+124>: trap
    
```

エラーが発生する原因は`String(data: encryptData, encoding:
String.Encoding.utf8)`の戻り値がnilなのにアンラップした為なのですが、  
戻り値が格納されている`encryptData`の中身はあるのに変換できない原因がわからないでいます。

またシミュレーターで動作確認を行っている際には気づかなかったので、  
実機のみで発生すると思われます。

この場合、暗号化の処理が正しくないのかと思っていたのですが、  
ネットを見ていると別の要因もあるという話もあったので、見当違いのことをしているのかと思い質問しました。  
swift3の対応には間違いはあるでしょうか？
CC BY-SA 3.0
2016-09-30T01:54:09.893
29255
2016-09-30T11:47:03.860
2016-09-30T06:25:56.277
14782
14782
question
swift ios swift3
AES128暗号化・復号化のswift3対応について
コメントに書いた「できればサンプル‌​として使える`data`,
`keyData`を含めて」なんていう部分を難しく考えすぎると、すごく大変なことのように思えるかもしれませんので、「あまりお勧めできない書き方」を修正して、(あなたの「swift3対応後」のコードを見ずに)元の「swift2.2」のコードをSwift
3に書き直したものを示しておきます。

「実機のみで発生すると思われます」との記載がありましたので、Debug構成、Release構成の両方で試しましたが、問題なく動いているコードです。

```

    func AES128Crypt(data: Data, keyData: Data, operation: Int) -> Data {
    
        let dataLength = data.count
    
        var cryptData = Data(count: dataLength + kCCBlockSizeAES128)
        let cryptLength = cryptData.count
    
        let keyLength = kCCKeySizeAES128
        let algoritm = CCAlgorithm(kCCAlgorithmAES128)
        let options = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
    
        var numBytesEncrypted: Int = 0
    
        let cryptStatus = keyData.withUnsafeBytes {keyBytes in
            data.withUnsafeBytes {dataBytes in
                cryptData.withUnsafeMutableBytes {cryptPointer in
                    CCCrypt(CCOperation(operation), algoritm,
                            options,
                            keyBytes, keyLength,
                            nil,
                            dataBytes, dataLength,
                            cryptPointer, cryptLength,
                            &numBytesEncrypted)
                }
            }
        }
    
        if cryptStatus == CCCryptorStatus(kCCSuccess) {
    
            cryptData.count = numBytesEncrypted
    
        } else {
            print("\(#line) Error: \(cryptStatus)")
        }
    
        return cryptData
    }
    
```

このコードでも同じ状況が発生するなら、`String.init(data:encoding:)`の使い方(それまでのいろいろな`data`の使い方)に問題がある可能性が高いですし、このコードに差し替えて問題が発生しなくなれば、`Data`,
`NSData`の使い方に問題があったのだと思われます。

何か新情報があれば更新しますので、是非お試しの上ご連絡ください。
CC BY-SA 3.0
2016-09-30T11:47:03.860
29270
2016-09-30T11:47:03.860
13972
29255
answer