iOSセキュリティ対策:データ暗号化の実践手法

プライバシーデータの送信方法

ユーザーのプライバシー情報を送信する際は、必ずPOSTメソッドを使用してください。GETリクエストではすべてのパラメータがURLに直接表示され、リクエストURLはサーバーのアクセスログに記録されることが多いため、攻撃者の標的となりやすいのです。

プライバシー情報には以下のようなものがあります:

  • ログインパスワード
  • 銀行口座情報
  • その他個人情報

データセキュリティの重要性

単にPOSTリクエストを使用するだけでは、セキュリティ問題は完全には解決しません。ソフトウェア(例:Charles)を使用してプロキシサーバーを設定し、スマートフォンの通信データを傍受・確認することが可能です。そのため、プライバシー情報を送信する際は、必ず暗号化処理を施してから送信する必要があります。

一般的な暗号化アルゴリズム

以下に代表的な暗号化アルゴリズムを挙げます:

MD5 \ SHA \ DES \ 3DES \ RC2とRC4 \ RSA \ IDEA \ DSA \ AES

暗号化アルゴリズムの選択:

一般的に、各企業には独自の暗号化規格があり、そのインターフェース仕様書に従って暗号化処理を実装する必要があります。

MD5暗号化の詳細

MD5とは

正式名称は「Message Digest Algorithm 5」で、「メッセージダイジェストアルゴリズム第5版」と訳されます。入力情報に対して128ビットのハッシュ値(32文字)を生成する効果があります。

MD5の特徴

  • 異なる2つの入力から同じ出力が得られることはありません
  • 出力値から元の平文を復元することは不可能(不可逆性)

MD5の応用例

MD5は比較的高い安全性を持ち、無料で利用可能なため、広く使用されています。主にデジタル署名、ファイル完全性検証、パスワード暗号化などに活用されます。

MD5復元サイト:http://www.cmd5.com

MD5の改良方法

現在のMD5は絶対安全とは言えません。そのため、以下のような改良を加えることで、復元の難易度を高めることができます:

  • ソルト(Salt)追加:平文の特定位置にランダムな文字列を挿入してからMD5化
  • 暗号化後の文字列並び替え:まず平文をMD5で暗号化し、その結果の文字列を並び替える

基本的な方針は、データベースが侵害されても、正しい平文を復元できないようにすることです。

ネットワークデータ暗号化戦略

  1. 暗号化対象:プライバシー情報(パスワード、銀行情報など)
  2. 暗号化方案
    • プライバシー情報は必ずPOSTリクエストで送信
    • MD5などの暗号化アルゴリズムを使用してデータを暗号化
  3. 暗号化強化:復元の難易度を高めるため
    • 平文に対する2重MD5:MD5(MD5(pass))
    • まず平文にソルトを追加し、MD5化:MD5(pass.$salt)

ローカルストレージの暗号化

  1. 暗号化対象:重要なデータ(例:ゲームデータ)

コードセキュリティの問題

  1. リバースエンジニアリング
    • 現在、ツールや技術を用いてソースコードを逆コンパイル可能
    • 逆コンパイルすると純粋なC言語のコードになり、可読性は低い
    • 少なくとも使用されているフレームワークの特定は可能
  2. 参考書籍:『iOSリバースエンジニアリング』
  3. 解決策:リリース前にコードを難読化
    • 難読化前:
      @interface HMPerson :NSObject
      - (void)run;
      - (void)eat;
      @end
    • 難読化後:
      @interface A :NSObject
      - (void)a;
      - (void)b;
      @end

MD5暗号化の実装例

暗号化ファイルのインポート

#import "ViewController.h"
#import "MBProgressHUD.h"
#import "NSString+Hash.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *userIDField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
- (IBAction)performLogin;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

- (IBAction)performLogin {
    // 1.ユーザー名の確認
    NSString *userIDText = self.userIDField.text;
    if (userIDText.length == 0) {
        [MBProgressHUD showError:@"ユーザー名を入力してください"];
        return;
    }

    // 2.パスワードの確認
    NSString *passwordText = self.passwordField.text;
    if (passwordText.length == 0) {
        [MBProgressHUD showError:@"パスワードを入力してください"];
        return;
    }

    // ローディング表示
    [MBProgressHUD showMessage:@"ログイン中...."];

    // 3.サーバーにユーザー名とパスワードを送信
    NSURL *url = [NSURL URLWithString:@"http://218.83.161.124:8080/job/login"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.timeoutInterval = 15;
    request.HTTPMethod = @"POST";

    // パスワードの暗号化
    passwordText = [self obfuscatedMD5:passwordText];

    // リクエストボディの設定
    NSString *param = [NSString stringWithFormat:@"username=%@&pwd=%@", userIDText, passwordText];
    request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];

    // ヘッダー情報の設定
    [request setValue:@"iPhone 6" forHTTPHeaderField:@"User-Agent"];

    // 非同期リクエストの送信
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
     ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
         // ローディング非表示
         [MBProgressHUD hideHUD];

         if (connectionError || data == nil) {
             [MBProgressHUD showError:@"リクエスト失敗"];
             return;
         }

         // サーバーからのJSONレスポンスの解析
         NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
         NSString *errorMessage = responseDict[@"error"];
         if (errorMessage) {
             [MBProgressHUD showError:errorMessage];
         } else {
             NSString *successMessage = responseDict[@"success"];
             [MBProgressHUD showSuccess:successMessage];
         }
     }];
}

/**
 * MD5($pass.$salt) の実装
 *
 * @param input 平文
 * @return 暗号化された文字列
 */
- (NSString *)saltedMD5:(NSString *)input
{
    // ソルト追加:平文にランダムな文字列を連結
    NSString *saltedInput = [input stringByAppendingString:@"aaa"];
    return [saltedInput md5String];
}

/**
 * MD5(MD5($pass)) の実装
 *
 * @param input 平文
 * @return 二重に暗号化された文字列
 */
- (NSString *)doubleMD5:(NSString *)input
{
    return [[input md5String] md5String];
}

/**
 * まず暗号化してから文字列を並び替える
 *
 * @param input 平文
 * @return 暗号化・並び替え済みの文字列
 */
- (NSString *)obfuscatedMD5:(NSString *)input
{
    NSString *hashedPassword = [input md5String];
    
    // ハッシュ値の分割
    NSString *prefix = [hashedPassword substringFromIndex:2];
    NSString *suffix = [hashedPassword substringToIndex:2];
    
    // 並び替え
    NSString *result = [prefix stringByAppendingString:suffix];
    
    NSLog(@"\ninput=%@\nhashed=%@\nresult=%@", input, hashedPassword, result);
    
    return result;
}
@end

タグ: iOS セキュリティ 暗号化 Objective-C MD5

8月26日 03:38 投稿