Posts Tagged ‘iPhone’

{ 2010.12.5 }

iPhone で暗号化

    はてなブックマーク - iPhone で暗号化
    このエントリーをはてなブックマークに追加

    初めまして、Fusic 河野です。
    わたくし、IT 系のバスケの社会人チームiPhone アプリ系のコミュニティとかを
    やってたりするので、ご興味のある方はぜひご参加ください。

    弊社にはもう一人河野というものがおり、そっちとは違う方と
    覚えて頂けると溜飲が下がります。。。

    最近、プライベートではこんなことやってたりして遊んでます。
    Fusic では、主に ruby on rails をやっており、ZENPREiPhone アプリ
    担当させていただいてたりします。

    さて、昨日行われました安元の結婚式も無事に終わり、本日はとっても天気の良い日曜日です。
    それにしても、とても良い結婚式でした。

    「おめでとうございます。お二人とも末永くお幸せに!」

    で、そんな幸せに包まれつつな日曜日も Advent Calendar です。
    こんな日にバトンがまわってくるとは、、な気分ではございますがさっそく。

    ご結婚されたばかりのお二人には、なんとも、、な話かもしれませんが、
    いくら仲睦まじい関係だとしても、時には隠蔽する必要が出てくる事が
    あるやも知れません。
    そんな時に必要になってくること。

    “暗号化”についてです。

    前に山本が「as3cryptoで暗号化」 という記事を書いてますが、
    その記事の iPhone 版だと思っていただければ幸いです。

    暗号化

     objective-c で暗号化をする場合、CCCrypt() という関数を使います。

     [CCCrypt(3cc) Mac OS X Manual Page]
     developer.apple.com/library/mac/#DOCUMENTATION/Darwin/Reference/ManPages/man3/CCCrypt.3cc.html
     
     iPhone 用のサンプルコードはこちらになるのですが、見ていただくと分かるのですが、
     まー、as のように楽じゃないなというのが分かって頂けるかなと。

     CCCrypt() を使用して、NSData クラスに AES256EncryptWithKey, AES256DecryptWithKey のメソッドを追加します。
     (※ こちらを参考にしました)

     NSDataAdditions.m というファイルを作成し、以下を追加します。

    #import <CommonCrypto/CommonCryptor.h>
     
    @implementation NSData (Additions)
     
    @class NSString; 
     
    - (NSData *)AES256EncryptWithKey:(NSString *)key {
            char keyPtr[kCCKeySizeAES256+1];
            bzero(keyPtr, sizeof(keyPtr));
     
            [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     
            NSUInteger dataLength = [self length];
     
            size_t bufferSize = dataLength + kCCBlockSizeAES128;
            void *buffer = malloc(bufferSize);
     
            size_t numBytesEncrypted = 0;
            CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,       
                                                                             kCCOptionPKCS7Padding | kCCOptionECBMode,
                                                                             keyPtr, kCCKeySizeAES256,
                                                                             NULL,
                                                                             [self bytes], dataLength,
                                                                             buffer, bufferSize,
                                                                             &numBytesEncrypted);
            if (cryptStatus == kCCSuccess) {
                    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
            }
            free(buffer);
            return nil;
    }
     
    - (NSData *)AES256DecryptWithKey:(NSString *)key {
            char keyPtr[kCCKeySizeAES256+1];
            bzero(keyPtr, sizeof(keyPtr));
     
            [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     
            NSUInteger dataLength = [self length];
     
            size_t bufferSize = dataLength + kCCBlockSizeAES128;
            void *buffer = malloc(bufferSize);
     
            size_t numBytesDecrypted = 0;
            CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 
                                                                             kCCOptionPKCS7Padding | kCCOptionECBMode,
                                                                             keyPtr, kCCKeySizeAES256,
                                                                             NULL,
                                                                             [self bytes], dataLength,
                                                                             buffer, bufferSize,
                                                                             &numBytesDecrypted);
     
            if (cryptStatus == kCCSuccess) {
                    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
            }
            free(buffer);
            return nil;
    }
    @end

     使う側でファイルをインポートすれば、NSData クラスのメソッドとして使えます。

    base64encoding

     暗号化したデータを ZENPRE とかのように、サーバにデータを送る必要があるなら、
     base64 エンコードも実装する必要があります。
     同じく NSData クラスに newStringInBase64FromData というメソッドを追加します。
     (※ こちらを参考にしました)

     先程のファイルに下記を追加します。

    - (NSString *)newStringInBase64FromData {
            NSMutableString *dest = [[NSMutableString alloc] initWithString:@""];
            unsigned char * working = (unsigned char *)[self bytes];
            int srcLen = [self length];
     
            for (int i=0; i<srcLen; i += 3) {
                    for (int nib=0; nib<4; nib++) {
                        int byt = (nib == 0)?0:nib-1;
                            int ix = (nib+1)*2;
     
                            if (i+byt >= srcLen) break;
     
                            unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);
     
                            if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);
     
                            [dest appendFormat:@"%c", base64[curr]];
                    }
            }
            return dest;
    }

     同じく使う側でファイルをインポートすれば、NSData クラスのメソッドとして使えます。

    実行

     上記の追加したコードを含めたサンプルコードを実行します。

     

     入力した値が、base64 に変換されている事(真ん中のグレー領域)と
     暗号化されたものが復元されている事(下の白領域)を確認します。

    おわりに

     やはり、どうしても as と比べるとなんだかメンドクサイですね。
     暗号化の話は、コードも含め長文にどうしてもなってしまうので
     駆け足で進めていってしまいました。
     今回、objective-c の醍醐味の一つでもあるかなと個人的に思ってる、
     既存クラスへのメソッドの追加ができるってだけでも実感頂ければと思います。

     今回使用したサンプルのソースコードはココにあげております。
     お役に立てれば幸いです。

     それと、近々 ZENPREiPhone アプリの新版がリリースされる予定です。
     ご期待下さい。

      はてなブックマーク - プレゼンテーション配信ツール「ZENPRE」のご紹介
      このエントリーをはてなブックマークに追加

      こんにちは。
      最近、これから紹介するサービスの対応に追われ続けている山本です。

      8/3(火)に、Fusicの新サービス「ZENPRE」をOPENしました。
      今回は、そのZENPREのご紹介や特徴について書かせていただきます。

      ZENPREは、スライド資料と動画が同時に配信できるプレゼンテーションツールです。
      Ustreamが身近に使われるようになった昨今、全国で行われるイベントの模様がお気軽に配信・閲覧できるようになりました。
      勉強会やセミナーの様子も配信される機会も増え、主に都心部でしか行われない貴重な勉強会でも遠方にいながらにして擬似的に参加できるようになりました。
      しかし、専用のカメラ機材を使って中継される稀なケースを除き、配信される映像の解像度は低く、スクリーンに映し出された資料の解読が困難なことがなかったでしょうか。

      当サービス「ZENPRE」では、資料と動画を別画面に分けて表示します。そのため資料部分の可読性は一気に向上します。
      また、配信する方のページ操作がそのまま受信する方のページに反映されるため、リアルタイム性が保持されます。
      さらにチャット機能も搭載しておりますので、発表の際の気になった発言もすぐ質問ができ発表者や自分以外の参加者とのコニュニケーションが可能です。

      発表の際に、受信する方が見る画面サンプルを掲載いたします。

      画面は3つの領域に分かれます。
      左側が資料を表示する領域です。この部分が、発表者のページ操作に同期し自動でページが切り替わります。自分で操作することはできません。
      右側上部が動画再生領域です。Ustreamを通した現地の様子が閲覧できます。
      右側下部がチャット領域です。

      これらサービスの利用には、発表者に資料の登録をしてもらう必要があります。
      セミナー等で発表することが決まり、資料の作成も完了したらZENPREに資料を登録してください。
      また、動画を配信するために、UstreamのチャンネルIDも同時に登録しておきます。

      実際に発表の日時になり、自分の番になったらZENPREの配信用画面を会場のスクリーンに映し出します。
      配信用の画面サンプルは以下になります。

      ほぼ受信用の画面と同じですね。
      唯一違うのは、赤色で強調した部分のページ送りボタンが付いていることです。
      「次ページ」ボタンを押すことで、自身の画面のスライドが次ページへ移動するとともに、受信者の画面にも伝わり、次ページが表示されます。
      もちろん「前ページ」ボタンで前ページへ移動し、ページ数の指定もすることができます。
      また、配信用画面には動画は不要というケースもあるため、資料部分のみフルスクリーンで表示することも可能です。

      公開が終了した後は、受信者画面でもページの操作ができるようになり、後々の資料として活用することもできます。

      ページ操作に関しては、この配信用画面から操作する以外にもスマートフォンアプリを利用して行うことができます。
      OPENに合わせて、iPhone用アプリとAndroid用アプリを用意しました。
      どちらのアプリも全く同じ機能を持っているのですが、iPhoneアプリの画面を以下に掲載いたします。

      ページの操作はフリック(画面を指でスライドさせる動作)で行います。
      直感的に、かつ、リモコン感覚でページの操作が可能になります。

      他にも、
      ・新着ニュースの閲覧
      ・過去に配信した資料の閲覧
      がアプリで可能です。

      AppStore、もしくは、AndroidMarketで「ZENPRE」と検索してください。
      無料でダウンロード可能です。

      以上の機能が、すべて無料で利用できます。
      今後、より多くの人に参加してほしい勉強会やセミナーがございましたら、ぜひともZENPREをご活用ください。

      次回は、ZENPREを支えている技術についてご紹介したいと思います。

      ZENPRE
      zenpre.net

      Fusic によるZENPRE紹介
      fusic.co.jp/product/zenpre.html

      ZENPRE on twitter
      twitter.com/ZENPRE