简体   繁体   English

Java中的C#加密实现

[英]C# encryption realization in java

I am developing an android application in which i need to implement some encryption. 我正在开发一个Android应用程序,在其中我需要实现一些加密。 At the same time i have to keep compatibility with other versions of application (eg for the WP platform), which are already in production. 同时,我必须保持与其他已在生产中的应用程序版本(例如WP平台)的兼容性。

This is C# code: 这是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");
        }
      .......
     }

I have tried to implement it in Java. 我试图用Java实现它。 AFAIK, there is no default RC2 crypto provider in android, so i used Spongy Castle library (bouncycastle fork for android). AFAIK,android中没有默认的RC2加密提供程序,因此我使用了Spongy Castle库(适用于android的Bouncycastle fork)。

This is my Java code: 这是我的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;
             }

And the results of these functions are different. 这些功能的结果是不同的。 What i am doing wrong? 我做错了什么?

How do i do it right? 我该怎么办? Any examples and suggestions are welcome. 欢迎任何示例和建议。

With best regards. 最诚挚的问候。

UPD The main goal is to get identical byte arrays from both functions. UPD的主要目标是从两个函数中获取相同的字节数组。 I can't modify c# code. 我无法修改C#代码。 First, i want to clarify am i right with c#-code: 首先,我想用C#代码澄清我的意思:

  • it creates MD5 hash from the passphrase 's bytes array 它从passphrase的字节数组创建MD5哈希
  • it generates crypto key using proprietary WinApi.CryptDeriveKey function 它使用专有的WinApi.CryptDeriveKey函数生成加密密钥
  • this key is used to encrypt data using RC2 algorithm 该密钥用于使用RC2算法加密数据

Second, i want to know whether there is an analogue of WinApi.CryptDeriveKey function - as i see this is the main problem. 其次,我想知道是否存在WinApi.CryptDeriveKey函数的类似物-如我所见,这是主要问题。

Sorry, my question is too general, because i am not sure that the problem above ( CryptDeriveKey ) is the only. 抱歉,我的问题太笼统了,因为我不确定上面的问题( CryptDeriveKey )是唯一的。

Unfortunately I don't have access to a Windows machine to test this on right now but here is what I think should be interoperable. 不幸的是,我现在没有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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM