使用相同的密钥在 C# 中加密并在 Java 中解密

问题描述 投票:0回答:2

我正准备在服务器端(C#)进行加密,并在 Android 端(Java)对我的 api 密钥进行解密。 C# 中的加密/解密都可以。而且,在java中,加密/解密也可以。主要问题是用 C# 生成的 ciphertext 与 java 不同,尽管我使用了相同的密钥。 C# 生成的密文无法在 Java 中解密。我尝试如下。

Java

 public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb";
    private static byte[] key_Array = Base64.decode(key,Base64.DEFAULT);

    public static String encrypt(String plainText)
    {
        try
        {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

            // Initialization vector.
            // It could be any value or generated using a random number generator.
            byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Key secretKey = new SecretKeySpec(key_Array, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);

            return Base64.encodeToString(cipher.doFinal(plainText.getBytes()),Base64.DEFAULT);
        }
        catch (Exception e)
        {
            System.out.println("[Exception]:"+e.getMessage());
        }
        return null;
    }

    public static String decrypt(String encryptedMessage)
    {
        try
        {
            //Cipher _Cipher = Cipher.getInstance("AES");
            //Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

            // Initialization vector.
            // It could be any value or generated using a random number generator.
            byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Key SecretKey = new SecretKeySpec(key_Array, "AES");
            _Cipher.init(Cipher.DECRYPT_MODE, SecretKey, ivspec);

            byte decodedMessage[] = Base64.decode(encryptedMessage,Base64.DEFAULT);
            return new String(_Cipher.doFinal(decodedMessage));

        }
        catch (Exception e)
        {
            System.out.println("[Exception]:"+e.getMessage());

        }
        return null;
    }

在 C# 中

public class Crypt
    {
        // C# Code, CipherMode.CBC
        // CBC version need Initialization vector IV.

        public static string keyStr = "aaaaaaaabbccccbbaaaaaaaabbccccbb";
                                      // FFClY170hLrhsDnKUEhJ4FhVOnrpNNFFClY170hLrhsDnKUE
        public static string Encrypt(string PlainText)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.BlockSize = 128;
            aes.KeySize = 256;

            // It is equal in java 
            /// Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");    
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            byte[] keyArr = Convert.FromBase64String(keyStr);
            byte[] KeyArrBytes32Value = new byte[32];
            Array.Copy(keyArr, KeyArrBytes32Value, 24);

            // Initialization vector.   
            // It could be any value or generated using a random number generator.
            byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
            byte[] IVBytes16Value = new byte[16];
            Array.Copy(ivArr, IVBytes16Value, 16);

            aes.Key = KeyArrBytes32Value;
            aes.IV = IVBytes16Value;

            ICryptoTransform encrypto = aes.CreateEncryptor();

            byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
            byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
            return Convert.ToBase64String(CipherText);

        }

        public static string Decrypt(string CipherText)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.BlockSize = 128;
            aes.KeySize = 256;

            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            byte[] keyArr = Convert.FromBase64String(keyStr);
            byte[] KeyArrBytes32Value = new byte[32];
            Array.Copy(keyArr, KeyArrBytes32Value, 24);

            // Initialization vector.   
            // It could be any value or generated using a random number generator.
            byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
            byte[] IVBytes16Value = new byte[16];
            Array.Copy(ivArr, IVBytes16Value, 16);

            aes.Key = KeyArrBytes32Value;
            aes.IV = IVBytes16Value;

            ICryptoTransform decrypto = aes.CreateDecryptor();

            byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
            byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return ASCIIEncoding.UTF8.GetString(decryptedData);
        }
    }

Java 输出

纯文本:hla hla

密文:MW6b3AIpNw5RLmhvAro1Yg==

C# 输出

纯文本:hla hla

密文:qsHRHy05GbRv5Q1QNOUlZQ==

任何想法或替代方法将不胜感激。谢谢。

java c# encryption cryptography
2个回答
4
投票

问题是,在 Java 代码中,您仅使用 192 位密钥,而在 C# 版本中,您使用 256 位密钥。

您的 Base64 编码密钥为 32 个字符,转换为 24 个字节,即 192 位。

这些是 Java 中的违规行:

public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb"; // 32 characters
private static byte[] key_Array = Base64.decode(key, Base64.DEFAULT); // 24 bytes

只需更改 Java 键数组的创建即可解决问题。比如:

public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb"; // 32 characters
private static byte[] key_Array = new byte[32]; // 32 bytes

static {
    // copy the 24 base64-decoded bytes to the key array
    System.arraycopy(Base64.decode(key, Base64.DEFAULT), 0, key_Array, 0, 24);
}

0
投票

对我来说这非常有效。

JAVA

   import javax.crypto.Cipher;
   import javax.crypto.spec.IvParameterSpec;
   import javax.crypto.spec.SecretKeySpec;
   import java.security.Key;
   import java.util.Base64;

   public class Main {

       private static String key = "000102030405060708090a0b0c0d0e0f";
       private static byte[] key_Array = new byte[32];

       public static void main(String[] args) throws Exception {
           
             System.out.print("\nEncrypt2:"+ encrypt("Hello World",key.getBytes(),new byte[16]));
             String encry= encrypt("Hello World",key.getBytes(),new 
                         byte[16]);
             System.out.print("\nDecrypt2:"+decrypt(encry,key.getBytes(),new byte[16]));
       }

       public static String encrypt(String plainText, byte[] key, byte[] iv) throws Exception {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
            byte[] encryptedData = cipher.doFinal(plainText.getBytes());
            return Base64.getEncoder().encodeToString(encryptedData);
        }

        public static String decrypt(String encryptedText, byte[] key, byte[] iv) throws Exception {
             SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
             cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
             byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
             return new String(decryptedData);
         }

     }

其输出将是:b5cCsUojhg71otTVZNxxyA==

在 C# 中

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;

    namespace EncryptandDecrypt
    {
    public class Encrypt
    {
       public static string keyStr = "000102030405060708090a0b0c0d0e0f";
               
       public static string Encrypt(string plainText, byte[] key, byte[] iv)
       {
          using (Aes aes = Aes.Create())
              {
                  aes.Key = key;
                  aes.IV = iv;
                  aes.Mode = CipherMode.CBC;
                  aes.Padding = PaddingMode.PKCS7;

                  ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
                  byte[] encryptedData = encryptor.TransformFinalBlock(Encoding.UTF8.GetBytes(plainText), 0, plainText.Length);
                  return Convert.ToBase64String(encryptedData);
          }
       }

     public static string Decrypt(string encryptedText, byte[] key, byte[] iv)
     {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            byte[] d1 = Convert.FromBase64String(encryptedText);
            int l1 = d1.Length;
            int l2 = encryptedText.Length;
            byte[] decryptedData = decryptor.TransformFinalBlock(Convert.FromBase64String(encryptedText), 0, Convert.FromBase64String(encryptedText).Length);
            return Encoding.UTF8.GetString(decryptedData);
          }
       }
   }
}



  Program.cs file
  {
      Console.WriteLine("Encrynew :" +Encrypt.Encrypt("{\"phoneNumber\":\"9989186732\"}", Encoding.UTF8.GetBytes(secretKey),new byte[16]));
      string dec = Encrypt.Encrypt("{\"phoneNumber\":\"9989186732\"}", Encoding.UTF8.GetBytes(secretKey), new byte[16]);
       Console.WriteLine("Decrynew :" + Encrypt.Decrypt(dec, Encoding.UTF8.GetBytes(secretKey), new byte[16]));

   }
© www.soinside.com 2019 - 2024. All rights reserved.