0

これはヘッドスクラッチャーです。そしてそれは暗号化を含み、それを特に厄介にします!

CCCryptを使用してAES128に暗号化するObjective-Cコードがあり、プロトコルバッファとAsyncSocketsを使用して送信するiPhone上のメッセージを暗号化します。iOSコードは次のとおりです。

- (NSData *)AES128EncryptWithKey:(const char *)keyPtr {

    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, kCCKeySizeAES128, // oorspronkelijk 256
                                          keyPtr /* 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];
    } else {
        free(buffer); //free the buffer;
        return nil;
    }
}

AES管理対象オブジェクトを次のように定義します。

    AesManaged AES = new AesManaged();
    AES.Padding = PaddingMode.PKCS7;
    var shared = /* a shared key */
    var salt = shared + DH.P;
    Rfc2898DeriveBytes deriveBytes = /* derived bytes from shared */
    byte[] ekey = deriveBytes.GetBytes(16);
    byte[] eiv = ekey;
    AES.Key = ekey;
    AES.IV = eiv;

次に、次のC#.Netコードを使用して、サーバー上でこのデータを復号化します。

public byte[] Decrypt(byte[] encryptedData)
{
    byte[] dec = null;
    MemoryStream ms = new MemoryStream(encryptedData);
    using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Read))
    {
         BinaryReader reader = new BinaryReader(cs);
         dec = reader.ReadBytes(encryptedData.Length);
         reader.Close();
    }
    return dec;
}

これは、iOSシミュレーターで実行しているとき、およびXcodeからデバイス自体にデバッグするときに完全に機能します。ただし、アプリケーションの配布パッケージ(IPAファイル)を作成してデバイスに展開すると、サーバーで次の例外が発生します。

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.

これを引き起こす原因となる私が送信しているデータの暗号化されていないデータの長さは4であり、暗号化されたサイズは16になります。これはAESブロックサイズであると私は信じているので、これは正しいようです。デバッグログは、これがデプロイされたアプリケーションとシミュレーターの両方でのメッセージのサイズであることを示しています。だからサイズは間違っていないようです。

この例外について読むと、パディングの作成方法に問題があることがわかります。しかし、デバイスがデプロイされている場合と、デバッガーまたはシミュレーターを介して実行されている場合で、これが異なるのはなぜですか?

前もって感謝します。私はこれを何日も理解しようとしてきましたが、それが原因で私のアプリをAppleでテストすることができません。

4

1 に答える 1

0

いくつかのメモ:

a) iOS で共有キーから暗号化キーを導出するコードを示してください。

このコードは .NET 用に表示されましたが、iOS 用には表示されませんでした。

b) iOS の keyPtr に実際に 128 ビット (16 バイト) が含まれていることを確認します。何らかの理由で含まれているものが少ない場合、これに問題がある可能性があります

c) keyPtr を IV として渡すことはお勧めしません。一般的に言えば、それは悪い習慣です。暗号化されたファイルごとに新しい一意の IV を作成する必要があります。

テスト目的で、これを NULL に設定できます (心配する変数を 1 つ少なくするため)。

d) 暗号化キーを導出する .NET コード全体を表示できますか。明確でないことがいくつかあります。

  • D.Pとは?

  • Rfc2898DeriveBytes serveBytes = /* 共有から派生したバイト */ 私が理解しているように、新しい Rfc2898DeriveBytes(pwd, salt); のようなものが来るはずです。pwdとsaltとして何を使用しているのかは明らかではありません。

于 2012-09-26T21:27:00.060 に答える