3

このエラーについてグーグルで調べすぎましたが、何も役に立ちませんでした。次のコードを使用して、php で暗号化されたファイルを取得しています。

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateencryptkey, base64_encode(file), MCRYPT_MODE_CBC, $hardvector);

IOS で復号化できません。NSDATA+CommonCrypto、NSFileManager-AES、NSDATA-aes などの多くのライブラリを試しましたが、ファイルの復号化に成功していません。

以下は、使用される目的の C コードです。

- (NSData *)AESDecryptWithPassphrase:(NSString *)pass
{
    NSMutableData *ret = [NSMutableData dataWithCapacity:[self length]];
    unsigned long rk[RKLENGTH(KEYBITS)];
    unsigned char key[KEYLENGTH(KEYBITS)];
    const char *password = [pass UTF8String];
    for (int i = 0; i < sizeof(key); i++)
        key[i] = password != 0 ? *password++ : 0;

    int nrounds = rijndaelSetupDecrypt(rk, key, KEYBITS);
    unsigned char *srcBytes = (unsigned char *)[self bytes];
    int index = 0;
    while (index < [self length])
    {
        unsigned char plaintext[16];
        unsigned char ciphertext[16];
        int j;
        for (j = 0; j < sizeof(ciphertext); j++)
        {
            if (index >= [self length])
                break;

            ciphertext[j] = srcBytes[index++];
        }
        rijndaelDecrypt(rk, nrounds, ciphertext, plaintext);
        [ret appendBytes:plaintext length:sizeof(plaintext)];

    }
    return ret;
}

このコードはテキストに対しては適切に機能しますが、ファイルを復号化することはできません。復号化されたファイルを保存すると、ファイル システム エラーが表示されます。これらの復号化されたファイルは、どのシステムでも開くことができません。その過程でファイル形式が乱れていると思います。

次のコードも試しましたが、成功しませんでした:

- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm
                                     key: (id) key      // data or string
                    initializationVector: (id) iv       // data or string
                                 options: (CCOptions) options
                                   error: (CCCryptorStatus *) error
{
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = kCCSuccess;

    NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
    NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]);

    NSMutableData * keyData, * ivData;
    if ( [key isKindOfClass: [NSData class]] )
        keyData = (NSMutableData *) [key mutableCopy];
    else
        keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];

    if ( [iv isKindOfClass: [NSString class]] )
        ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
    else
        ivData = (NSMutableData *) [iv mutableCopy];    // data or nil

    [keyData autorelease];
    [ivData autorelease];

    // ensure correct lengths for key and iv data, based on algorithms
    FixKeyLengths( algorithm, keyData, ivData );

    status = CCCryptorCreate( kCCDecrypt, algorithm, options,
                              [keyData bytes], [keyData length], [ivData bytes],
                              &cryptor );

    if ( status != kCCSuccess )
    {
        if ( error != NULL )
            *error = status;
        return ( nil );
    }

    NSData * result = [self _runCryptor: cryptor result: &status];
    if ( (result == nil) && (error != NULL) )
        *error = status;

    CCCryptorRelease( cryptor );

    return ( result );
}

上記のコードの 2 番目の関数:

- (NSData *) _runCryptor: (CCCryptorRef) cryptor result: (CCCryptorStatus *) status
{
    size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[self length], true );
    void * buf = malloc( bufsize );
    size_t bufused = 0;
    size_t bytesTotal = 0;
    *status = CCCryptorUpdate( cryptor, [self bytes], (size_t)[self length], 
                              buf, bufsize, &bufused );
    if ( *status != kCCSuccess )
    {
        free( buf );
        return ( nil );
    }

    bytesTotal += bufused;

    // From Brent Royal-Gordon (Twitter: architechies):
    //  Need to update buf ptr past used bytes when calling CCCryptorFinal()
    *status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused );
    if ( *status != kCCSuccess )
    {
        free( buf );
        return ( nil );
    }

    bytesTotal += bufused;

    return ( [NSData dataWithBytesNoCopy: buf length: bytesTotal] );
}

1週間解けなかった…

4

1 に答える 1

7

注意すべきことの 1 つは、mcrypt_encrypt のファイル パラメータです。暗号化の前にファイルが base64 でエンコードされているように見えます (意味がないというわけではありません)。これは、復号化後に base64 でデコードする必要があることを意味します。

他のパラメーターは簡単です:
MCRYPT_RIJNDAEL_128 は AES、128 は 128 ビット キー
MCRYPT_MODE_CBC は cbc モード、CommonCrypto のデフォルトです。
ブロックサイズへのパディングはnull文字であり、標準的ではないため、パディングされていない長さが問題になる可能性があります。

さらに別の AES メソッドが必要というわけではありません。これは私が使用するものです。

#import <CommonCrypto/CommonCryptor.h>

+ (NSData *)doCipher:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES128,
                       kCCOptionPKCS7Padding,
                       symmetricKey.bytes, 
                       kCCKeySizeAES128,
                       iv.bytes,
                       dataIn.bytes,
                       dataIn.length,
                       dataOut.mutableBytes,
                       dataOut.length,
                       &cryptBytes);

    if (ccStatus != kCCSuccess) {
        NSLog(@"CCCrypt status: %d", ccStatus);
    }

    dataOut.length = cryptBytes;

    return dataOut;
}
// Also add Security.framework to your project.

NSData 入力が想定されており、パディングは標準の PKCS として指定されていることに注意してください。

CommonCryptor.hを参照してください

于 2012-04-09T19:28:36.247 に答える