2014-07-19 47 views
0

我正在開發一個android應用程序,我需要實現一些加密。 同時,我必須保持與其他版本的應用程序(例如WP平臺)的兼容性,這些版本已經在生產。java中的C#加密實現

這是C#代碼:

static public byte[] Encrypt(String passphrase, byte[] data) 
    { 
     //encrypted data 
     byte[] buffer = null; 

     //crypto handles 
     IntPtr hProvider = IntPtr.Zero; 
     IntPtr hKey = IntPtr.Zero; 

     try 
     { 

      if (!WinApi.CryptAcquireContext(ref hProv, null, WinApi.MS_DEF_PROV, 
       WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT)) 
       Failed("CryptAcquireContext"); 

      //128 bit hash object 
      if (!WinApi.CryptCreateHash(hProv, 
       WinApi.CALG_MD5, IntPtr.Zero, 0, ref hHash)) 
       Failed("CryptCreateHash"); 

    // add passphrase to hash 
      byte[] keyData = ASCIIEncoding.ASCII.GetBytes(passphrase); 
      if (!WinApi.CryptHashData(hHash, keyData, (uint)keyData.Length, 0)) 
       Failed("CryptHashData"); 

      // create 40 bit crypto key from passphrase hash 
      if (!WinApi.CryptDeriveKey(hProv, WinApi.CALG_RC2, 
       hHash, WinApi.CRYPT_EXPORTABLE, ref hKey)) 
       Failed("CryptDeriveKey"); 

      // determine how large of a buffer is required 
      // to hold the encrypted data 
      uint dataLength = (uint)data.Length; 
      uint bufLength = (uint)data.Length; 
      if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true, 
       0, null, ref dataLength, bufLength)) 
       Failed("CryptEncrypt"); 

      // allocate and fill buffer with encrypted data 
      buffer = new byte[dataLength]; 
      Buffer.BlockCopy(data, 0, buffer, 0, data.Length); 

      dataLength = (uint)data.Length; 
      bufLength = (uint)buffer.Length; 
      if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true, 
       0, buffer, ref dataLength, bufLength)) 
       Failed("CryptEncrypt"); 
     } 
     ....... 
    } 

我試圖實現它在Java中。 AFAIK,Android中沒有默認的RC2加密提供程序,所以我使用了Spongy Castle庫(bouncycastle fork for android)。

這是我的Java代碼:

public static byte[] encryptLB(byte[] key, byte[] iv, byte[] unencrypted) 
       throws NoSuchAlgorithmException, ... { 
      MessageDigest digest = MessageDigest.getInstance("MD5"); 
      digest.update(key); 
      byte[] hash = digest.digest(); //build the hash (128 bit) 

       Cipher cipher = Cipher.getInstance("RC2/CBC/PKCS5Padding"); 
       cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(hash, "RC2")); 
       byte[] unByte = unencrypted; 
       byte[] encrypted = cipher.doFinal(unencrypted); 
       return encrypted; 
      } 

而這些功能的結果是不同的。 我做錯了什麼?

我該怎麼做對不對? 歡迎任何示例和建議。

祝好。

UPD主要目標是從兩個函數中獲取相同的字節數組。我無法修改C#代碼。首先,要說明的是嗎用c#-code:

  • 它從passphrase的字節陣列創建MD5哈希
  • 它生成使用專有WinApi.CryptDeriveKey功能
  • 此密鑰用於加密密鑰的使用RC2算法

二加密數據,我想知道是否有WinApi.CryptDeriveKey功能的類似物 - 依我之見,這是主要的問題。

對不起,我的問題太籠統了,因爲我不確定上面的問題(CryptDeriveKey)是否唯一。

+0

您是否正在執行* encryption *或* hashing *?它們非常不同 - 你似乎在Java代碼中進行哈希處理。 C#代碼並不十分清晰,因爲您使用Windows API的原因不明顯 - 在.NET中有很多加密API。 –

+0

我只是試圖用java編寫的用C#編寫的算法。不幸的是,我不熟悉WinApi和C#中的最佳實踐,這個代碼也不是我的。據我所知,這種方法(c#)從'passphrase'創建MD5哈希,然後將其用作密鑰。並且這一步'if(!WinApi.CryptDeriveKey(hProv,WinApi.CALG_RC2,hHash,WinApi.CRYPT_EXPORTABLE,ref hKey))'對我來說仍然不清楚。 MSDN說,它以某種方式從哈希數據生成密鑰。此功能是否存在任何Java或開源模擬? –

+1

那你究竟在努力實現什麼?在任何其他事情之前,你需要清楚這一點。 –

回答

0

不幸的是,我現在沒有權限訪問Windows機器來測試它,但我認爲這應該是可以互操作的。

public static byte[] encrypt(String passphrase, byte[] data) throws Exception { 

    // Hash the ASCII-encoded passphrase with md5 

    byte[] keyData = passphrase.getBytes(Charset.forName("US-ASCII")); 
    MessageDigest md = MessageDigest.getInstance("MD5"); 
    byte [] md5HashOfKey = md.digest(keyData); 

    // Need to use bouncycastle (spongycastle on Android) to get RC2 

    Security.addProvider(new BouncyCastleProvider()); 

    Cipher rc2 = Cipher.getInstance("RC2/CBC/PKCS5PADDING"); 

    // Create an RC2 40-bit key from the 1st 5 bytes of the hash. 

    SecretKeySpec rc2KeySpec = new SecretKeySpec(md5HashOfKey, 0, 5, "RC2"); 
    rc2.init(Cipher.ENCRYPT_MODE, rc2KeySpec); 

    byte [] cipher = rc2.doFinal(data); 

    return cipher; 
}