0

CommonCrypto を使用して NSMutableData オブジェクトを暗号化しようとしています (結果のバイトを複製せずにそれ自体にコピーします)。以前は CCCrypt() の「ワンショット」方式を使用していましたが、これは主に単純に思えたからです。データ オブジェクトがメモリ内で複製されていることに気付きました。これを回避するために、バッファ サイズが 2048 バイトの NSInputStream オブジェクトを使用してみました。NSMutableData オブジェクトを読み込んでおり、継続的に CCCryptorUpdate() を呼び出して暗号化を処理しています。問題は、まだ重複しているように見えることです。これが私の現在のコードです(これはNSMutableDataのカテゴリであることに注意してください-主に歴史的な理由のため-したがって、「自己」参照):

- (BOOL)encryptWithKey:(NSString *)key
{
    // Key creation - not relevant to the dercribed problem
    char * keyPtr = calloc(1, kCCKeySizeAES256+1); 
    [key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];

    // Create cryptographic context for encryption
    CCCryptorRef cryptor;
    CCCryptorStatus status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode, keyPtr, kCCKeySizeAES256, NULL, &cryptor);
    if (status != kCCSuccess)
    {
        MCLog(@"Failed to create a cryptographic context (%d CCCryptorStatus status).", status);
    }

    // Initialize the input stream
    NSInputStream *inStream = [[NSInputStream alloc] initWithData:self];
    [inStream open];
    NSInteger result;
    // BUFFER_LEN is a define 2048
    uint8_t buffer[BUFFER_LEN];
    size_t bytesWritten;

    while ([inStream hasBytesAvailable])
    {
        result = [inStream read:buffer maxLength:BUFFER_LEN];
        if (result > 0)
        {
            // Encryption goes here
            status = CCCryptorUpdate(
                                     cryptor,               // Previously created cryptographic context
                                     &result,               // Input data
                                     BUFFER_LEN,            // Length of the input data
                                     [self mutableBytes],   // Result is written here
                                     [self length],         // Size of result
                                     &bytesWritten          // Number of bytes written
                                     );

            if (status != kCCSuccess)
            {
                MCLog(@"Error during data encryption (%d CCCryptorStatus status)", status);
            }
        }
        else
        {
            // Error
        }
    }

    // Cleanup
    [inStream close];
    CCCryptorRelease(cryptor);
    free(keyPtr);
    return ( status == kCCSuccess );
}

ここで明らかな暗号化が間違いなく欠けており、入力ストリームを使用することさえ私には少し新しい..

4

2 に答える 2

2

一度だけ呼び出す限りCCUpdate()、ストリームを使用せずに、読み取り元と同じバッファーに暗号化できます。例については、 RNCryptManager.mを参照してください。勉強しapplyOperation:fromStream:toStream:password:error:ます。ここではストリームを使用しましたが、既にNSData.

CCUpdate()ただし、 が 1 回だけ呼び出されるようにする必要があります。複数回呼び出すと、それ自体のバッファーが破損します。これは、CommonCryptor の未解決のバグです (rad ://9930555 )。

補足として、キーの生成は非常に安全ではなく、この種のデータに ECB モードを使用することは、ほとんど暗号化として認められません。場合によっては、データを見るだけで、データの復号化に使用できる暗号文にパターンが残ります。実際にこのデータを保護するつもりなら、このアプローチはお勧めしません。これらのツールをうまく使用する方法を学習したい場合は、CommonCrypto を使用して AES で適切に暗号化する を参照してください。パッケージ化されたソリューションが必要な場合は、RNCryptorを参照してください。(ただし、RNCryptor には現在、インプレースで暗号化するための便利な方法がありません。)

于 2014-05-14T16:38:40.723 に答える