简体   繁体   English

C#中的Java加密代码

[英]Java encryption code in c#

I have the following Java code being used on an Android device that encrypts and decrypts strings using the AES encryption algorithm and an SHA1PRNG hash. 我在Android设备上使用以下Java代码,该设备使用AES加密算法和SHA1PRNG哈希对字符串进行加密和解密。 I want the Android device to call a .NET WCF service written in C#. 我希望Android设备调用以C#编写的.NET WCF服务。 I have been searching everywhere trying to find an equivalent in C# that could encrypt and decrypt in a similar way to the Java code, but could not find the exact same way to do it. 我一直在寻找可以找到与C#类似的方式进行加密和解密的C#等效项,但找不到与之完全相同的方法。 Here is the Encrypt() method in both languages: 这是两种语言的Encrypt()方法:

Java: Java:

public static String encrypt(String seed, String cleartext) throws Exception 
{
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();

    byte[] rawKey = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(cleartext.getBytes());
    return toHex(encrypted);
}

I have created something similar to this in C#, which also uses AES and SHA1: 我在C#中创建了与此类似的东西,它也使用AES和SHA1:

C#: C#:

public static string Encrypt(string seed, string cleartext)
{
  var objAesCrypto = new AesManaged();
  var objHashSha1 = new SHA1Managed();

  var byteHash = objHashSha1.ComputeHash(Encoding.ASCII.GetBytes(seed));
  var truncatedHash = new byte[16];
  Array.Copy(byteHash, truncatedHash, truncatedHash.Length);
  objAesCrypto.Key = truncatedHash;
  objAesCrypto.Mode = CipherMode.ECB;

  var byteBuff = Encoding.ASCII.GetBytes(cleartext);
  return Convert.ToBase64String(objAesCrypto.CreateEncryptor().TransformFinalBlock(byteBuff, 0, byteBuff.Length));
}

There are several problems with this, however. 但是,这有几个问题。 As you can see, using C#'s version of SHA1 (SHA1Managed), it returns a hash of 20 bytes, not 16. The only way to get it to pass into the AES algorithm is to truncate the hash to 16 bytes first. 如您所见,使用C#版本的SHA1(SHA1Managed),它将返回20字节的哈希,而不是16。将其传递给AES算法的唯一方法是首先将哈希截断为16个字节。

The second problem is, although both work just fine in their respective environments, when I try to pass an encrypted string from Java, along with the seed, the C# code is never able to decrypt it properly. 第二个问题是,尽管两者在各自的环境中都可以正常工作,但是当我尝试从Java传递加密的字符串以及种子时,C#代码永远无法正确解密它。 The encrypted strings in both cases look nothing alike and are even different lengths. 两种情况下的加密字符串看起来都不相同,甚至长度也不同。 A typical encrypted string from the Java side looks something like this: F7E8758A2E65518FB49C53BC707288FC (32 chars long). 从Java端看,典型的加密字符串看起来像这样: F7E8758A2E65518FB49C53BC707288FC (32个字符长)。 Whereas the same exact encrypted string with the same exact seed from the C# side looks like this: 3VysgnYgNi9OJBxL2FP+rQ== (24 chars long). 而从C#端来看具有相同确切种子的相同确切加密字符串如下所示: 3VysgnYgNi9OJBxL2FP+rQ== (24个字符长)。

I'm sure it has something to do with the fact that I'm truncating the hash in C#, but that doesn't explain why the two encrypted strings look so vastly different. 我确定这与我在C#中将哈希值截断有关,但这并不能解释为什么两个加密字符串看起来如此不同。 (Another intersting thing I noticed is that no matter what string and seed I use on the C# side, it's always 24 chars long and ends with two equal signs - why is that?) (我注意到的另一件有趣的事是,无论我在C#端使用什么字符串和种子,它总是24个字符,并以两个等号结尾-为什么?)

So, my question is, how do I get both environments to be able to decrypt each other's encrypted strings using the same seed values? 因此,我的问题是,如何使两个环境都能够使用相同的种子值解密彼此的加密字符串? I don't care if I even need to use different algorithms on the C# side than the Java side, I just need the C# code to be able to read the Java-encrypted strings. 我不在乎我是否甚至需要在C#端使用与Java端不同的算法,我只需要C#代码就能读取Java加密的字符串。

The second problem is, although both work just fine in their respective environments, when I try to pass an encrypted string from Java, along with the seed, the C# code is never able to decrypt it properly. 第二个问题是,尽管两者在各自的环境中都可以正常工作,但是当我尝试从Java传递加密的字符串以及种子时,C#代码永远无法正确解密它。

You shouldn't be trying to decrypt a hash. 您不应该尝试解密哈希。 Hashes are one-way. 哈希是单向的。

A typical encrypted string from the Java side looks something like this: F7E8758A2E65518FB49C53BC707288FC (32 chars long). 从Java端看,典型的加密字符串看起来像这样:F7E8758A2E65518FB49C53BC707288FC(32个字符长)。 Whereas the same exact encrypted string with the same exact seed from the C# side looks like this: 3VysgnYgNi9OJBxL2FP+rQ== (24 chars long). 而从C#端来看具有相同确切种子的相同确切加密字符串如下所示:3VysgnYgNi9OJBxL2FP + rQ ==(24个字符长)。

That's because you're converting to hex in Java, but to Base64 in C#: 那是因为您要在Java中转换为十六进制,但在C#中转换为Base64:

return toHex(encrypted);

vs

return Convert.ToBase64String(...);

As for the seed length issue - again, you're doing different things in the Java vs the C#. 至于种子长度问题-再次,您在Java和C#中做不同的事情。 It's not at all clear to me that using SecureRandom in that way is meant to generate the same secret key as using a straight hash from SHA1. 对我来说一点也不清楚,以这种方式使用SecureRandom目的是生成与使用SHA1中的直接散列相同的密钥。

Rather than trying to fix this approach though, I'd suggest you should be rethinking it - it doesn't look secure to me at all. 我建议您应该重新考虑它,而不是尝试解决此问题,因为它对我来说似乎并不安全。 What you've called a seed is more than just a seed - it's basically a complete key. 您所称的种子不仅仅是种子,而是一个完整的密钥。 An attacker who knows the seed effectively knows the "password" to your system; 知道种子的攻击者实际上知道您系统的“密码”。 you might as well just use raw bytes. 您最好只使用原始字节。

Your toHex(encrypted); 您的toHex(encrypted); is not the same thing as Convert.ToBase64String() as far as I know. 据我所知,它与Convert.ToBase64String()是不同的。

It appears that Android uses a fixed version of the SHA1PRNG. 看来Android使用的是SHA1PRNG的固定版本。 Also there seem to be many implementations for SHA1PRNG for .NET/Java/Android. 对于.NET / Java / Android,SHA1PRNG似乎也有许多实现。

You may want to take a look at the below link for some similar problem and also a possible port of the SHA1PRNG present in Android to C#. 您可能需要查看以下链接,以解决一些类似的问题,以及可能存在的Android到C#的SHA1PRNG端口。 SHA1PRNG in Android - .NET Android中的SHA1PRNG-.NET

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

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