簡體   English   中英

使用NSInputStream進行NSMutableData加密

[英]NSMutableData encryption in place using NSInputStream

我正在嘗試使用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 );
}

我肯定在這里缺少明顯的東西,加密,甚至使用輸入流對我來說都是新的。

只要只調用CCUpdate()一次,就可以加密到讀取的相同緩沖區中,而無需使用流。 有關示例 ,請參見RNCryptManager.m 研究applyOperation:fromStream:toStream:password:error: 我在這里確實使用過流,但是如果您已經有NSData ,則無需這樣做。

但是,必須確保CCUpdate()僅被調用一次。 如果您多次調用它,它將破壞它自己的緩沖區。 這是CommonCryptor( Radar:// 9930555 )中的一個打開的錯誤。

附帶說明:您的密鑰生成非常不安全,並且對此類數據使用ECB模式幾乎不能視為加密。 它將模式留在密文中,可用於解密數據, 在某些情況下,只需查看即可 如果您確實打算保護此數據,則我不建議您使用此方法。 如果您想學習如何很好地使用這些工具,請參閱《 使用CommonCrypto使用AES正確加密》 如果需要預包裝的解決方案,請參見RNCryptor (但是,RNCryptor當前沒有方便的就地加密方法。)

在該行中:

result = [inStream read:buffer maxLength:BUFFER_LEN];

數據被讀入bufferresult設置為執行結果。 排成一行:

status = CCCryptorUpdate(cryptor, &result, ...

您應該將buffer用於輸入數據,而不是狀態

status = CCCryptorUpdate(cryptor, buffer, ...

使用更好的名稱將有助於消除簡單的錯誤。 如果將變量而不是result命名為readStatus則很可能不會發生該錯誤。 同樣,與其命名數據變量buffer而不是命名它為streamData ,也應該更加清楚。 命名不正確確實會導致錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM