2012-08-14 17 views
13

最初にまず以前は、パスワードを暗号化してパスワードを解読した.netウェブサービスのパラメータとして送るために、Androidで簡単なAES暗号化が必要でした。iOSとAndroidでのAES暗号化、C#.NETでの復号化

次は私のAndroidの暗号化です:

private static String Encrypt(String text, String key) 
     throws Exception { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     byte[] keyBytes= new byte[16]; 
     byte[] b= key.getBytes("UTF-8"); 
     int len= b.length; 
     if (len > keyBytes.length) len = keyBytes.length; 
     System.arraycopy(b, 0, keyBytes, 0, len); 
     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec); 

     byte[] results = cipher.doFinal(text.getBytes("UTF-8")); 
     String result = Base64.encodeBytes(results); 
     return result; 
     } 

そして私はC#で、それを復号化し:これは魅力のように働いたが、私が何をしようとしたときに問題が来

 public static string Decrypt(string textToDecrypt, string key) 
    { 
     System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); 

     RijndaelManaged rijndaelCipher = new RijndaelManaged(); 
     rijndaelCipher.Mode = CipherMode.CBC; 
     rijndaelCipher.Padding = PaddingMode.PKCS7; 

     rijndaelCipher.KeySize = 0x80; 
     rijndaelCipher.BlockSize = 0x80; 

     string decodedUrl = HttpUtility.UrlDecode(textToDecrypt); 
     byte[] encryptedData = Convert.FromBase64String(decodedUrl); 
     byte[] pwdBytes = Encoding.UTF8.GetBytes(key); 
     byte[] keyBytes = new byte[0x10]; 
     int len = pwdBytes.Length; 
     if (len > keyBytes.Length) 
     { 
      len = keyBytes.Length; 
     } 
     Array.Copy(pwdBytes, keyBytes, len); 
     rijndaelCipher.Key = keyBytes; 
     rijndaelCipher.IV = keyBytes; 
     byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length); 
     return encoding.GetString(plainText); 
    } 

iOSでも同じです私はそれをGoogleで検索ofcauseので、私は、iphone/ipadのためにかなりの新しいアプリケーション開発をしていますし、提供ほぼすべてのコードサンプルは以下の通りであった:

- (NSData *)AESEncryptionWithKey:(NSString *)key { 
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused) 
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

NSUInteger dataLength = [self length]; 

size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void *buffer = malloc(bufferSize); 

size_t numBytesEncrypted = 0; 

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES128, 
             NULL /* initialization vector (optional) */, 
             [self bytes], [self 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; 

}

たぶん私は、少しあまりにも楽観的でした

"EgQVKvCLS4VKLoR0xEGexA=="

、その後のiOSは私を与える:Androidのは私のようなものを投げているときので、私は、ここでのスムーズな移行を期待していました

"yP42c9gajUra7n0zSEuVJQ==" 

うまくいけば、忘れてしまった設定ですか、設定の一部が間違っていますか?

[UPDATE]結果は、base64エンコーディング後に表示されます。

+1

アンドロイド版は、 "YHH + gTxyIxvAx1cPFLcP0IEW2HcVHQVi9X11656CFsk =" ''(60 71 fe 81 3c 72 23 1b c0 c7 57 0f ​​14 b7 0f ​​d0 81 16 d8 77 15 1d 05 62に等しいURLでエンコードされたbase64文字列です。 f5 7d 75 eb 9e 82 16 c9) '。 – Joe

+0

Woops、申し訳ありませんが、私はそれを言い忘れました。私はiOS版の結果を別の方法でエンコードしていますが、結果はエンコード前とは異なります。 – Morten

+0

base64エンコーディングの後に結果を表示する質問が更新されました。同じパスワードと同じキーが使用されます。 – Morten

答えて

5

最初の注意点は、このコードで重大なセキュリティ上の問題があることです。文字列のパスワードを取得し、それをキーにドロップするだけです。その文字列を人間が入力可能なものにすると、キースペースを大幅に狭めてしまいます(AES-128をAES-40やAES-50のように変えてしまうかもしれません)。あなたはPBKDF2を使って鍵を塩と伸ばしする必要があります。完全な説明はProperly encrypting with AES with CommonCryptoを参照してください。

キーをIVとして使用しているため、重大なセキュリティ上の問題もあります(詳細は下記を参照してください。これが実際に症状の原因です)。これはIVを選択する正しい方法ではなく、暗号文を予測可能にします。同じキーで暗号化された同一の平文は、同じ結果を与えます。これはIVを全く持たないことに似ています。 IVはランダムである必要があります。詳細については上記のリンクを参照してください。

実際の症状になりました。問題はあなたがJavaとC#のIVとしてキーを使用しているが、iOSのIVとして0(NULL)を使用していることです(IVはオプションではなく、ただ0を渡すだけです)。すべての場合に同じIVを使用する必要があります。

+0

セキュリティ上の問題があることは知っていますが、それは一時的な解決策に過ぎません。これは簡単な修正であるため、最終的な解決策が完了するまで、わかりやすいテキストを渡すことはありません。私は今実際に何かをテストすることはできません。なぜなら、それは仕事上の問題だからです。正しく理解すれば、以下を変更すれば修正されるはずです:C#-decryption:rijndaelCipher.IV = X; Java暗号化の場合:IvParameterSpec ivSpec =新しいIvParameterSpec(X)。 ... NULLパラメータをXに変更しました。ここで、X ofcauseは同じ値ですか? ところで、お返事ありがとうございます... – Morten

+0

上記のコードでは、現在「X」はiOS以外の場所のキーのコピーです。 iOS上でキーにするか、C#とJavaで0にすることができます。私はいくつかの静的な値(0以外)にしません。 –

+0

さて、どうもありがとうございました。私は明日にそれを試して、あなたの答えを "受け入れられた"とマークします... – Morten

関連する問題