2012-03-20 14 views
0

次のスニペットを使用して、32バイトのキーで暗号化されたファイルを解読しようとしています。だから、私がファイルデータを暗号化しようとしているとき、すべてがうまくいっています。しかし、私が解読しようとしているときに、プログラムはCryptoExtensions.mにif (cryptStatus == kCCSuccess)の条件を渡すことさえありません。私は本当に問題を理解するのに疲れています。私は、Base64デコードを使用しようとしていたが、私のファイルはUTF8エンコーディングで保存されているので、私はちょうどそれがNSDataのからログの内容です入れたとき、私は何の問題もありません:Objective-cのAES256解読問題

NSData *fileData = [[[NSData alloc] initWithContentsOfFile:destPath] autorelease]; 

NSLog(@"File data:%@",[[NSString alloc] initWithData:fileData encoding:NSUTF8StringEncoding]); 

しかし、私はそれを解読しようとしているとき、I nilからCryptoExtensions方法を取得しています:

NSData *aesResponse = [fileData AES256DecryptWithKey:@"4QXcCZlgRAIchiaqkMVpF3nkpARmdL3z"]; 
NSLog(@"AES:%@",[[NSString alloc] initWithData:aesResponse encoding:NSUTF8StringEncoding]); 

これは暗号スニペットの内容です:

CryptoExtensions.h

#import <Foundation/Foundation.h> 
@interface NSData (CryptoExtensions) 
- (NSData*)AES256EncryptWithKey:(NSString*)key; 
- (NSData*)AES256DecryptWithKey:(NSString*)key; 
@end 

CryptoExtensions.m

#import "CryptoExtensions.h" 
#import <CommonCrypto/CommonCryptor.h> 
@implementation NSData (CryptoExtensions) 
- (NSData*)AES256EncryptWithKey:(NSString*)key { 
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise 
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [self length]; 

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block. 
    //That's why we need to add the size of one block here 
    size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
    void* buffer    = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES256, 
              NULL /* initialization vector (optional) */, 
              [self bytes], dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesEncrypted); 

    if (cryptStatus == kCCSuccess) 
    { 
     //the returned NSData takes ownership of the buffer and will free it on deallocation 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    free(buffer); //free the buffer; 
    return nil; 
} 

- (NSData*)AES256DecryptWithKey:(NSString*)key { 
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise 
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [self length]; 

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block. 
    //That's why we need to add the size of one block here 
    size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
    void* buffer    = malloc(bufferSize); 

    size_t numBytesDecrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES256, 
              NULL /* initialization vector (optional) */, 
              [self bytes], dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesDecrypted); 

    if (cryptStatus == kCCSuccess) 
    { 
     //the returned NSData takes ownership of the buffer and will free it on deallocation 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; 
    } 

    free(buffer); //free the buffer; 
    return nil; 
} 
@end 
+1

あなたはどこでもAES256とAES128を混合しています。すべて同じアルゴリズム、ブロックサイズなどを使用すべきではありませんか? – MByD

+0

私は[この記事](http://stackoverflow.com/questions/1400246/aes-encryption-for-an-nsstring-on-the-iphone)の主なものを理解しているので、どのAESアルゴリズム使用されている。何でもキーサイズに関するものです。 btw:256鍵用に実装されたメソッドはありません。128だけです.kCCKeySize256だけが利用可能です。 – kokoko

+1

*アルゴリズム*はAES128です。つまり、ブロックサイズは128バイトです。これは、AESで唯一サポートされているブロックサイズです。 * keysize *は256ビットです。定数の混合は正常です。 –

答えて

5

このコードでは、重大なセキュリティ上の問題があります。誤ってAESキーが構築され、キースペースが大幅に縮小され、IVがなくなり、最初のブロックに問題が発生します。このコードに対しては強くお勧めします。

私は、このよく使われるスニペットの代替品を開発することで、ほとんどの方法を行っています。 https://github.com/rnapier/RNCryptorを参照してください。それが箱の外であなたのために働かないなら、私に知らせてください。私は人々がAES256EncryptWithKeyを使用して停止する一般的なすべてのケースで使用するのに十分に簡単にしようとしています。

このコードの問題については、もう少し詳しくは、Properly encrypting with AES with CommonCryptoを参照してください。誰かがAES暗号化を使いやすいカテゴリにまとめたことが大好きです。私はそれがあまりにも多くのセキュリティ問題を抱えていなかったことを望むだけです。


EDIT:あなたの実際の質問に戻って来て、あなたがこのデータを暗号化するためにAES256EncryptWithKeyを使用しましたか?そうでない場合、特定の形式は根本的に異なる可能性があります。ほぼすべてのAES暗号化の実装では、入力パラメータを生成してから出力を生成する際に、別のアプローチを使用します(ほとんどの場合、これも文書化されません)。パラメータとフォーマットを一致させる必要があります。たとえば、AES256EncryptWithKeyを使用して、openssl encで生成されたものを復号化することはできません。

+0

私はこのスニペットを使用しようとしましたが、結果NSStringをどのようにNSStringにキャストできますか?私はbase64encodeとNSUTF8encodingを使用しようとしていましたが、NSLog(@ "%@"、[[NSString alloc] initWithData ... usingEncoding:NSUTF8Encoding ...])のnull結果を取得できません。しかし、私は実際に暗号化されたデータがそのサイズからNSDataに送信されることを知っています。 – kokoko

+1

暗号化されたデータが読み取り可能なUTF8Stringをエンコードしていると(何度も* legal * UTF8Stringをエンコードしないので、 'nil'を得ていることになります)、驚くべきことです。暗号化されたデータはランダムなバイトと区別できません(ランダムであると区別できれば、定義上は安全な暗号ではありません)。ランダムなデータを7ビットのASCII文字列に変換する必要がある場合、これがBase64エンコーディング用のものです。それを16進バイトに変換することもできます。 http://stackoverflow.com/questions/1305225/best-way-to-serialize-a-nsdata-into-an-hexadeximal-string –