4

私はこれを何時間も見たり見たりしてきました。AES-256暗号化を使用してiOSに短いテキストを暗号化させ、opensslで復号化できるように必死に試みています。

まっすぐ?いいえ。

私が見つけた iOS 用のコードは、openssl 用のキーおよび IV と互換性がないため、適応させる必要がありましたが、明らかに機能していません。

だからここに私が使用している暗号化するコードがあります...暗号化する文字列(dataString)を文字列キー(キー)と文字列初期化ベクトル(iv)に渡します...

- (NSData *)AES256Encrypt:(NSString *)dataString WithKey:(NSString *)key iv:(NSString *)iv {

    // '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];

    //NSLog(@"keyPtr: '%s'", keyPtr);

    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"keyPtr: '%s'", keyData.bytes);
    NSData *dataToEncrypt = [dataString dataUsingEncoding:NSUTF8StringEncoding];
    NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [dataToEncrypt 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,
                                          keyData.bytes, kCCKeySizeAES256,
                                          ivData.bytes, // initialisation vector
                                          dataToEncrypt.bytes, 
                                          dataToEncrypt.length, /* 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;
}

同じ文字列をエンコードする場合、openssl を同じキーと iv で使用した場合と同じ値は生成されません。たとえば、次のコマンド ライン:

openssl enc -aes-256-cbc -e -in secrets.txt -a -iv 0000 -K 0000 -p

secrets.txt は、暗号化する文字列を含む単なるテキスト ファイルです。

これは次のようなものを出力します:

salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
qTMfgtAxbF8Yyh27ZDrcIQ==

復号化するには、逆の操作を行います (上記の暗号化されたデータの最後の行が test.secrets.out にあると仮定します)。

openssl enc -aes-256-cbc -d -in test.secrets.out -a -iv 0000 -K 0000 -p 
salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
< text of the secrets.txt file >

ここで、4 文字のキーと iv を使用すると、iOS で正しくエンコードされません。完全な長さのキーと iv を使用すると、これも正しくエンコードされません。

基本的に、これは暗号化されたデータを送信した場合に、それが正しいデータであることを確認するためのチェックです。

私は何が欠けていますか?

答えを見つけるために調べたコード...

http://robnapier.net/blog/aes-commoncrypto-564

https://github.com/rnapier/RNCryptor

http://pastie.org/426530

ここでも広範囲に検索しましたが、答えが見つかりません。

どんな助けでも感謝します。

4

1 に答える 1

2

OpenSSL には、パスワードを IV とキーに変換するための独自の (「標準に近くなく、特に安全ではない」と読む) 方法があります。RNOpenSSLCryptorを見ると、使用されているアルゴリズムがわかります。

// For aes-128:
//
// key = MD5(password + salt)
// IV = MD5(Key + password + salt)

//
// For aes-256:
//
// Hash0 = ''
// Hash1 = MD5(Hash0 + Password + Salt)
// Hash2 = MD5(Hash1 + Password + Salt)
// Hash3 = MD5(Hash2 + Password + Salt)
// Hash4 = MD5(Hash3 + Password + Salt)
//
// Key = Hash1 + Hash2
// IV = Hash3 + Hash4
//

// File Format:
//
// |Salted___|<salt>|<ciphertext>|
//

を使用すると、OpenSSL 形式のサポートがRNOpenSSLCryptor可能になります。RNCryptor私は現在、async非同期操作をサポートするためにブランチでこのコードを修正している最中であり、そのブランチはまだ OpenSSL をサポートしていませんが、間もなく (2012 年 7 月中旬までに) 修正する予定です。

自分用にこれを実装するコードが必要な場合は、 および を参照してkeyForPassword:salt:くださいIVForKey:password:salt:

OpenSSL ファイル形式にはいくつかのセキュリティ上の問題があるため、回避できる場合はお勧めしません。鍵を生成するために非常に優れた KDF を使用せず、必要なほどランダムな IV を持たず、認証用の HMAC を提供しません。これらのセキュリティ上の問題が、私が別のファイル形式を設計した理由であり、「さらに別の互換性のないコンテナー」を作成するのが嫌いだったのと同じです。

于 2012-06-22T15:17:49.883 に答える