こんにちは、VOYAGE GROUPのしんばし(@shinbashi)です。

昨今何につけてもスマートフォンですよね。
かくいう僕もPDAからのW-ZERO3という王道を通って来ました。

さて、最近は特にスマートフォン対応とか、アプリ化する機会が増えてきたと思います。
android版を作ればiOS版も出すよ!みたいな話になりますよね。
「android版だけでいい」
なんて言葉を信じて設計すると、後で痛い目を見るのは火を見るより明らかです。

前フリが長くなりました。
android版だけだと信じて僕が痛い目を見たのは暗号化・復号処理の部分です。
Javaはともかく、Objective-Cをよく知らなかったのでライブラリに頼るわけですが、
Objective-Cの暗号化・復号処理をしてくれるライブラリでは扱えないアルゴリズムとかあるんですね。

ざっくり調べた感じだと以下な感じです

表1 アルゴリズム比較表
AES ARCFOUR Blowfish DES DESede ECIES RC2 RC4 RC5 RSA CAST
javax.crypt(android)
CCCrypt(iOS)

表2 パディング比較表
no padding PKCS7 PKCS5 PKCS1 PAEP
javax.crypt(android)
CCCrypt(iOS) ※1

※1 PKCS7 ≒ PKCS5 (ブロック長の違いなのでPKCS7でPKCS5形式のものをunpad出来る)

実際、パディング処理は暗号化前、復号後に自前でやってしまえばいいのでなんとでもなりますね。
こうしてみると、暗号化アルゴリズムはAESで実装するのが妥当そうです。
Objective-Cで自前でPKCS5でunpadする場合は以下な感じになると思います。
+ (NSData *) pkcs5_unpad:(NSData *)data
{
    int pad = [[[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(data.length - 1, 1)] encoding:NSASCIIStringEncoding] characterAtIndex:0];
    if (pad > data.length) return nil;
    return [data subdataWithRange:NSMakeRange(0, data.length - pad)];
}
ざっくりまとめると
  • アルゴリズム:AES(鍵長は128でも256でもいいと思います)
  •  ブロック形式:CBC(EBCも使えます)
  • パディング:PKCS5(独自で実装できるのでお好きにどうぞ)
な感じで暗号化しておけば、android(java)でもiOS(Objective-C)でも取り扱いできます。
javax.cryptやCCCryptの使い方は色々な方が解説していらっしゃるのでそちらを参考にしていただければと思います。決してJavaのコード長すぎて写すのを面倒臭がっているわけではありません。

また、僕の場合だけかもしれませんが、CCCryptを使った時に、末尾に改行コードが含まれていて、NSDataからNSStringに変換しようとした時にエラーが発生したので、トリムする必要があるかもしれません。
また、WindowsPhoneに関してですが
「C#だし」
ってことで割愛させて頂きました。


おまけ

mixi Engineers' Blog » OpenSSLの暗号文をJava/Perl/Rubyで開く
http://alpha.mixi.co.jp/blog/?p=91

こちらでJavaでOpenSSLのパスフレーズから鍵を導出する処理が書かれていたので、せっかくなのでObjective-Cで実装するとどうなるのか書いてみました。

+(NSDictionary*) pass2keyInfo:(NSData *)pass salt:(NSData *)salt
{
    int keySize = 256;
    int ivSize  = 128;
    int keyAndIvSize = (keySize/8) + (ivSize/8);
    NSMutableData* result = [[NSMutableData alloc] init];
    NSMutableData* keyAndIv = [[NSMutableData alloc] init];
    while (keyAndIv.length < keyAndIvSize) {
        [result appendData:pass];
        [result appendData:salt];
        [result setData:[result MD5Digest]];
        [keyAndIv appendData: result];
    }
    NSData* key = [keyAndIv subdataWithRange:NSMakeRange(0, keySize/8)];
    NSData* iv  = [keyAndIv subdataWithRange:NSMakeRange(keySize/8, ivSize/8)];
    return [NSDictionary dictionaryWithObjectsAndKeys:key, @"key", iv, @"iv", nil];
}
参考
Java ™ 暗号化アーキテクチャー標準アルゴリズム名のドキュメント
http://java.sun.com/javase/ja/6/docs/ja/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator

CommonCryptor.c
http://opensource.apple.com/source/CommonCrypto/CommonCrypto-36064/Source/CommonCryptor.c