Padding无效,无法移除 – 在C#中进行解密(加密在Java中完成)

huangapple go评论160阅读模式
英文:

Padding is invalid and cannot be removed - decryption in c# (encryption done in java)

问题

public static string Decrypt_License(string encryptedText, byte[] key)
{
    string initVector = "RgUkXp2s5v8y/B?E";
    var ivBytes = Encoding.UTF8.GetBytes(initVector);
    var keyBytes = new byte[16];
    Array.Copy(key, keyBytes, Math.Min(keyBytes.Length, key.Length));
    string plaintext = null;
    
    using (AesManaged aes = new AesManaged())
    {
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = keyBytes;
        aes.IV = ivBytes;
        aes.BlockSize = 128;
        aes.KeySize = 128;
        aes.Mode = CipherMode.CBC;
        
        ICryptoTransform decryptor = aes.CreateDecryptor(keyBytes, ivBytes);
        
        using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(encryptedText)))
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader reader = new StreamReader(cs))
                {
                    plaintext = reader.ReadToEnd();
                }
            }
        }
    }
    return plaintext;
}

// Usage
string decryptedString = Decrypt_License(getDefaultKey(), encryptedLicense);

In your code, you are using PKCS7 padding, which is correct. The equivalent to Java's getBytes() method in C# is Encoding.UTF8.GetBytes(). However, Convert.FromBase64String() is not equivalent to getBytes(). It's used to decode a Base64 encoded string back to its byte representation. If you use Encoding.UTF8.GetBytes() on the encrypted text, you won't get the correct result, as you observed.

To compare the results of the hashKey() method between Java and C#, you need to ensure that the input and the logic are the same. Both methods seem to use SHA-1 hashing. You should compare the actual byte arrays generated by both methods, not their string representations.

If you're still encountering issues, ensure that the key, initialization vector, and padding settings are consistent between Java and C#. Double-check that the inputs and implementations match exactly on both sides.

英文:
Java code

public String encrypt(String key, String value) {
    try {
      String initVector = "RgUkXp2s5v8y/B?E";
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
      SecretKeySpec skeySpec = new SecretKeySpec(hashKey(key), "AES");
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      cipher.init(1, skeySpec, iv);
      byte[] encrypted = cipher.doFinal(value.getBytes());
      return Base64.getEncoder().encodeToString(encrypted);
    } catch (Exception ex) {
      ex.printStackTrace();
      return null;
    } 
  }
  
  private byte[] hashKey(String keyValue) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    byte[] key = keyValue.getBytes("UTF-8");
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
    key = messageDigest.digest(key);
    return Arrays.copyOf(key, 16);
  }



public static String decrypt(byte[] key, String encrypted)
{
    try
    {
        String initVector = "RgUkXp2s5v8y/B?E";
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(2, skeySpec, iv);
        byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));
        return new String(original);
    }
    catch (Exception ex)
    {
        Logger.getLogger("Decryption ").log(Level.SEVERE, "Exception processing decryption " + ex.getMessage());
        return null;
    }
}

String encryptedLicense = ENCRYPT.encrypt(string_key, stringToEncrypt);




converted c# code

   public static byte[] getDefaultKey()
{
    return DecryptUtil.hashKey(DecryptUtil.getUniqueIdentifier());
}


private static byte[] hashKey(string keyValue)
{
    try
    {
        var sha1 = SHA1Managed.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(keyValue);
        byte[] outputBytes = sha1.ComputeHash(inputBytes);
        return outputBytes;
       
    }
    catch (Exception ex)
    {
        ErrorLogger.WriteToFile("hashKey " + ex.Message.ToString());
    }
    return null;
}

public static string Decrypt_License(string encryptedText, byte[] key)
{
    string initVector = "RgUkXp2s5v8y/B?E";
                var ivBytes = Encoding.UTF8.GetBytes(initVector);
                var keyBytes = new byte[16];
                Array.Copy(key, keyBytes, Math.Min(keyBytes.Length, key.Length));
                string plaintext = null;
                // Create AesManaged    
                using (AesManaged aes = new AesManaged())
                {
                    aes.Padding = PaddingMode.PKCS7;
                    aes.Key = keyBytes;
                    aes.IV = ivBytes;
                    aes.BlockSize = 128;
                    aes.KeySize = 128;
                    aes.Mode = CipherMode.CBC;
                     
                    ICryptoTransform decryptor = aes.CreateDecryptor(keyBytes, ivBytes);
                   
                    
                    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(encryptedText)))
                    {
                       
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                        {
                               
                            using (StreamReader reader = new StreamReader(cs))
                                plaintext = reader.ReadToEnd();
                        }
                    }
                }
                return plaintext;
}

String decryptedString = DecryptUtil.Decrypt_License(hashkey(string_key), stringToDecrypt);

I am converting java code to c#, encryption done in java now I am trying to decrypt the data in c# . I read PaddingMode.PKCS7 and PKCS5 both are same. Is it true? or should I change padding type?

I have used all the concepts which is used in java. but it is not working. Am I missing something?

I have doubt in Convert.FromBase64String(encryptedText), because this is the place they(java) have used value.getBytes(). getBytes() equivalent in c# is Convert.FromBase64String()? will they produce same result?

Java hashkey() method and C# hashkey method giving different results. How to compare them as byte[]?

If I change Convert.FromBase64String() to Encoding.UTF8.GetBytes() then it is throwing 'Length of the data to decrypt is invalid AES C#' error.

This is my encrypted text
wJZESOEPNb66FbnpB8DqmwLcyosxGOjzgPKa9+7/VUatEFxSs1YqS28HHU26EmCcZDo7otE5PvX/qIpgQgTrhlCHgUJBb0+qd522/1egYoisE48ZL8X3cwCNx1AOVYJ0T2VOLB+J3HDWK4HOJfgm2CqbQpep0ioOTgNKQA0SF3SRmF92MGbf7wjUBA8WGdeUiIKRX9Lm/x6mUUuXHEIrCHbZOqDZvo2xR9zndIzwT/FfgLsQbJQjRjZPg7urfWLpUt6drbYcPFm3KgTmSrsRhzk15P6mw3GNO+3BmqBIndKmzi8blQqG8YFXVW8wiaurCm0jVcX5kwdU1PO1ktHSXQ==

secret key used for encryption
BFEBFBFF000306D4

答案1

得分: 1

我使用了自己的解密方法来进行C# AES和散列密钥的处理,我知道它们是有效的 :-).

将以下数据作为Java加密的输入:

String string_key = "mySecretKey";
String stringToEncrypt = "The quick brown fox jumps over the lazy dog";

我得到了加密后的许可证:

encryptedLicense: lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK

使用这个字符串和给定的 string_key 在C#中进行处理得到:

plaintext expect : The quick brown fox jumps over the lazy dog
plaintext from C#: The quick brown fox jumps over the lazy dog

安全警告:此代码使用固定的加密密钥和固定的初始化向量,使得整个加密过程不安全。该代码没有适当的异常处理,仅用于教育目的。

C# 代码:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program {
    public static void Main() {
        Console.WriteLine("Padding is invalid and cannot be removed - decryption in c# (encryption done in java)");

        string plaintextExpected = "The quick brown fox jumps over the lazy dog";
        string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
        string string_key = "mySecretKey";
        string plaintext = "";

        // 解密
        plaintext = decryptFromBase64(hashKey(string_key), encryptedLicense);
        Console.WriteLine("plaintext expect : " + plaintextExpected);
        Console.WriteLine("plaintext from C#: " + plaintext);
    }

    public static byte[] hashKey(string value)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
        SHA1 sha = new SHA1CryptoServiceProvider();
        byte[] sha1Hash = sha.ComputeHash(bytes);
        byte[] sha1HashLength = new byte[16];
        Array.Copy(sha1Hash, 0, sha1HashLength, 0, 16);
        return sha1HashLength;
    }

    static string decryptFromBase64(byte[] key, string data) {
        string decryptedtext;
        using(Aes aesAlg = Aes.Create()) {
            aesAlg.Key = key;
            string initVector = "RgUkXp2s5v8y/B?E";
            byte[] IV = Encoding.UTF8.GetBytes(initVector);
            byte[] cipherText = Convert.FromBase64String(data);
            aesAlg.IV = IV;
            aesAlg.Mode = CipherMode.CBC;
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            using(var msDecrypt = new MemoryStream(cipherText)) {
                using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
                    using(var srDecrypt = new StreamReader(csDecrypt)) {
                        decryptedtext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }
        return decryptedtext;
    }
}

编辑 1:
在我的Java代码中,我更改了以下行:

//String string_key = "mySecretKey";
String string_key = "BFEBFBFF000306D4";

并得到如下结果:

encryptedLicense: 7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA

将我的C#代码修改如下:

//string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
string encryptedLicense = "7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA";
//string string_key = "mySecretKey";
string string_key = "BFEBFBFF000306D4";

得到结果:

plaintext expect : The quick brown fox jumps over the lazy dog
plaintext from C#: The quick brown fox jumps over the lazy dog

所以一切都正常工作。

英文:

I used my own decryption method for c# aes and hashKey as well as I know they are working :-).

Giving these data as input for the Java encryption:

String string_key = "mySecretKey";
String stringToEncrypt = "The quick brown fox jumps over the lazy dog";

I'm getting the

encryptedLicense: lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK

Using this string and the given string_key to C# is puts out:

plaintext expect : The quick brown fox jumps over the lazy dog
plaintext from C#: The quick brown fox jumps over the lazy dog

Security warning: this code uses a fixed encryption key and a fixed initialization vector that makes the
complete encryption UNSECURE. The code has not proper exception handling and is for educational purpose only.

C#-code:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class Program {
public static void Main() {
Console.WriteLine("Padding is invalid and cannot be removed - decryption in c# (encryption done in java)");
string plaintextExpected = "The quick brown fox jumps over the lazy dog";
string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
string string_key = "mySecretKey";
string plaintext = "";
// decryption
plaintext = decryptFromBase64(hashKey(string_key), encryptedLicense);
Console.WriteLine("plaintext expect : " + plaintextExpected);
Console.WriteLine("plaintext from C#: " + plaintext);
}
public static byte[] hashKey(string value)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] sha1Hash = sha.ComputeHash(bytes);
byte[] sha1HashLength = new byte[16];
Array.Copy(sha1Hash, 0, sha1HashLength, 0, 16);
return sha1HashLength;
}
static string decryptFromBase64(byte[] key, string data) {
string decryptedtext;
using(Aes aesAlg = Aes.Create()) {
aesAlg.Key = key;
string initVector = "RgUkXp2s5v8y/B?E";
byte[] IV = Encoding.UTF8.GetBytes(initVector);
byte[] cipherText = Convert.FromBase64String(data);
aesAlg.IV = IV;
aesAlg.Mode = CipherMode.CBC;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using(var msDecrypt = new MemoryStream(cipherText)) {
using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using(var srDecrypt = new StreamReader(csDecrypt)) {
decryptedtext = srDecrypt.ReadToEnd();
}
}
}
}
return decryptedtext;
}
}

Edit 1:
In my Java code I changed the following line:

//String string_key = "mySecretKey";
String string_key = "BFEBFBFF000306D4";

and got as result:

encryptedLicense: 7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA

Changing my C#-code as follow:

//string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
string encryptedLicense = "7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA";
//string string_key = "mySecretKey";
string string_key = "BFEBFBFF000306D4";

gets the result:

plaintext expect : The quick brown fox jumps over the lazy dog
plaintext from C#: The quick brown fox jumps over the lazy dog

So everything is working.

huangapple
  • 本文由 发表于 2020年8月27日 13:15:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63609617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定