2014-07-19 43 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; 
}