0

我正在开发一个 android 应用程序,我需要在其中实现一些加密。同时,我必须保持与其他版本的应用程序(例如 WP 平台)的兼容性,这些版本已经在生产中。

这是 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库(用于 android 的 bouncycastle fork)。

这是我的 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) 是唯一的。

4

1 回答 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;
}
于 2014-07-19T15:12:20.147 回答