27193

[code]

    Alamofire.request(.POST, "http://sample.com/api/login", parameters: param)
            .responseJSON { (responce) in
                guard let object = responce.result.value else {
                    return
                }
                let json = JSON(object)
                let aaa = json["result"].string!
                let bbb = aaa.dataUsingEncoding(NSUTF8StringEncoding)
                let ccc = bbb?.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
                let ddd = ccc!.dataUsingEncoding(NSUTF8StringEncoding)
                let eee = dataTool.decrypt(ddd!)
                print(ddd)
        }
    
[/code]

> \-----サーバから返ってくる文字列-----  
>
> Z1h/9XCDaMZQ+JIwQLWkfqfNbHmcRs3dK3ITMCewCr8f15witQB7bX/fnhMFBBOmalQkbioX40Io8GzzL8meo5kkeD9TMePEG6ugvZ7fJ6TMXZ2FVcCXMerlOPbYnpGjHWSL4ayM0cAAYhWlNRooACXfUjkmLoTeeUefVIdZ1P4=
[code]

    public func decrypt(encryptData: NSData) -> NSString? {
    
        let privKey = findKey("com.sample.Test.private")
    
        let cipherBuffer = UnsafePointer<UInt8>(encryptData.bytes)
    
        var plaintextBufferSize = SecKeyGetBlockSize(privKey!)
        var plaintextBuffer = [UInt8](count:Int(plaintextBufferSize), repeatedValue:0)
    
        let status = SecKeyDecrypt(privKey!,
                                   SecPadding.PKCS1,
                                   cipherBuffer,
                                   encryptData.length,
                                   &plaintextBuffer,
                                   &plaintextBufferSize)
        if (status != errSecSuccess) {
            return nil
        }
        return NSString(bytes: UnsafePointer<Void>(plaintextBuffer), length:Int(plaintextBufferSize), encoding: NSUTF8StringEncoding)
    }
    
[/code]

サーバ側APIから受け取った暗号化文字列を復号化しようとすると、  
nilが返ってきてしまいます。  
正常に復号化した文字列を表示したいのですが何がいけないのでしょうか。  
ご教授願います。

bbb, ccc, ddd の処理で64文字ごとで改行する処理を行っているつもりです。

> OSStatusの値は「-9809」


CC BY-SA 3.0
2016-06-29T08:47:05.220
27182
2016-06-29T22:29:49.820
2016-06-29T08:55:53.350
16765
16765
question
swift swift2 api
文字列の復号化で「nil」が返ってきて正常に復号化出来ない


コメントの方が文字数制限いっぱいになって「何もかもおかしいとしか言えない」で終わってしまいましたが、続きとして(「回答」になるかどうかはわかりませんが)明らかに修正が必要な点をこちらに書かせていただきます。

(1) JSONの戻り値`aaa`から`decrypt`メソッドに渡すバイナリーデータ`ddd`を求める部分

`aaa`の内容が「サーバから返ってくる文字列」に示された`Z1h/...1P4=`になっているものとします。(改行は含んでいても構いませんが、前後にそれ以外の文字があるなら取り除く必要があります。)  
`ddd`を得るためにはこの1行だけで構いません。

[code]

    let ddd = NSData(base64EncodedString: aaa, options: [.IgnoreUnknownCharacters])
    
[/code]

サーバからの出力はbase64形式になっているので、それを単にデコードしてバイナリーデータにしたものが、`decrypt`に渡すべきデータになります。(「普通なら」の注釈がいるかもしれませんが。)

* * *

なぜ「この1行だけ」で良いのか分かりにくいかもしれませんので、少々長くなりますが、補足しておきます。

一般的な暗号化の流れは次のようになります。

[code]

     +-------------------+
     |  平文テキストデータ  |(1)
     +-------------------+
               ↓(A)UTF-8エンコード
     +-------------------+
     |  平文バイナリデータ  |(2)
     |      (UTF-8)      |
     +-------------------+
               ↓(B)パディング付加
     +-------------------+
     |  平文バイナリデータ  |(3)
     | (UTF-8、パディング) |
     +-------------------+
               ↓(C)暗号化
     +-------------------+
     | 暗号化バイナリデータ |(4)
     +-------------------+
               ↓(D)base64エンコード
     +-------------------+
     | 暗号化テキストデータ |(5)
     |     (base64)      |
     +-------------------+
               ↓(E)64桁区切り
     +-------------------+
     | 暗号化テキストデータ |(6)
     | (base64、64桁区切り)|
     +-------------------+
    
[/code]

(バイナリデータのやり取りが簡単なら(5)(6)は要らないのですが、そうはいかないことが多いので大抵はテキストに変換します。base64でなければいけない、と言うことはないのですが、サーバから返されたデータの形式に合わせておきます。)

サーバから受信したデータは明らかに(6)の形式ですから、元の平文テキスト(1)を得るためには、(A)〜(E)の逆変換を逆順に行ってやる必要があります。

[code]

     +-------------------+
     | 暗号化テキストデータ |(6)
     | (base64、64桁区切り)|
     +-------------------+
               ↓(-E)区切り除去
     +-------------------+
     | 暗号化テキストデータ |(5)
     |     (base64)      |
     +-------------------+
               ↓(-D)base64デコード
     +-------------------+
     | 暗号化バイナリデータ |(4)
     +-------------------+
               ↓(-C)復号化
     +-------------------+
     |  平文バイナリデータ  |(3)
     | (UTF-8、パディング) |
     +-------------------+
               ↓(-B)パディング除去
     +-------------------+
     |  平文バイナリデータ  |(2)
     |      (UTF-8)      |
     +-------------------+
               ↓(-A)UTF-8デコード
     +-------------------+
     |  平文テキストデータ  |(1)
     +-------------------+
    
[/code]

あなたのご質問に書かれている`decrypt`は、(-C)(-B)(-A)の変換を行うという作り(一部間違ってはいますが)になっているので、その関数を呼ぶために必要なのは、(-E)(-D)ということになります。これを一度でやってくれるのが上に紹介した「この1行」です。(ちなみに(-C)(-B)は、`decrypt`内の`SecKeyDecrypt`が一度に処理してくれます。)

暗号化アルゴリズムの詳細を知らなければ暗号を取り扱うプログラムが書けない、と言うものではありませんが(実際私も詳細は分かりません)、暗号化・復号化の流れの中でどの部分がどの処理をしているのかは意識できるようにならないと、意味のある情報交換ができるコードは書けません。しっかり頭に入れておいてください。

* * *

(2) 出力バッファーサイズ`plaintextBufferSize`を計算する部分

※この部分、自分で書くのも面倒なので、参考になるサイトはないかと探していたら、Google検索の上位で見つけたサイト2つはどちらも間違っていました。Google検索の順位は内容が正しいかどうかには関係ない、という好例かもしれません。ちなみに暗号化前のデータ長がブロック長より短い場合には動いているように見えてしまう、という困った誤りです。あなたもどちらかのサイトを参考にされたのでしょう。

前振りが長くなってしまいましたが、あなたの`decrypt`メソッドの中で出力バッファーに必要なバイト数を計算する部分は以下のように書き換える必要があります。

[code]

        var plaintextBufferSize: Int = encryptData.length
    
[/code]

簡単に言うと、現代の暗号化アルゴリズムでは暗号化されたデータと復号化されたデータとは同じデータサイズ(どちらもブロックサイズの整数倍)になりますので、出力バッファーにもそのサイズを確保する必要があるということです。

以上2点を解消してもまだ問題が残る可能性がありますが、その場合にはもう少し情報をいただかないといけないでしょう。(`findKey`の処理内容や、private
keyとpublic keyを公開してもらう必要が出るかもしれません。できれば公開可能なテストデータを作成しておいてください。)


CC BY-SA 3.0
2016-06-29T11:56:47.693
27193
2016-06-29T22:29:49.820
2016-06-29T22:29:49.820
13972
13972
27182
answer