1. 程式人生 > >如何一步步實現JAVA與C# AES加密結果相同

如何一步步實現JAVA與C# AES加密結果相同

實現JAVA與C# AES加密結果相同

最近公司開發一個電池溯源的介面,對方給的是一個java的demo,使用的是AES加密,但是我們的整合平臺是使用C#開發的,所有必須把java中的AES加密方法改成C#實現。對方給的demo如下
        /**
         * AES加密演算法
         * 
         * @param content
         *            加密內容
         * @param password
         *            密匙
         * @return
         */
        public
static String encryptAES(String content, String password) { try { if (content == null || content.equalsIgnoreCase("")) { return ""; } KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"
); secureRandom.setSeed(password.getBytes()); kgen.init(128, secureRandom); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"
); Cipher cipher = Cipher.getInstance("AES"); byte[] byteContent = content.getBytes("utf-8"); cipher.init(1, key); byte[] result = cipher.doFinal(byteContent); String str = Base64.encode(result); return str; } catch (NoSuchAlgorithmException var13) { var13.printStackTrace(); } catch (NoSuchPaddingException var14) { var14.printStackTrace(); } catch (InvalidKeyException var15) { var15.printStackTrace(); } catch (UnsupportedEncodingException var16) { var16.printStackTrace(); } catch (IllegalBlockSizeException var17) { var17.printStackTrace(); } catch (BadPaddingException var18) { var18.printStackTrace(); } return null; }

改成c# 實現

//AES加密
        public static string AesEncrypt(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
            RijndaelManaged rm = new RijndaelManaged
            {
                Key = Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

結果發現,JAVA和C#加密的結果不一樣,然後上網查資料,說是需要輸出SHA1後的真正金鑰,然後C#再利用這個祕密進行加密,,我把初始金鑰設定成123456,然後輸出C#真正的金鑰,程式碼如下:

try {
            String password = "123456";//AES的金鑰
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            kgen.init(128, secureRandom);

            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();//AES加密實際的Key值
            System.out.println(new String(java.util.Base64.getEncoder().encodeToString(enCodeFormat)));
            }
            catch (NoSuchAlgorithmException var13) {
                var13.printStackTrace();
            }

輸出後的金鑰放在C#裡面,加密的結果仍然不一樣。最後只能利用byte[]直接加密,

public static String encryptAES(String content, String password) {
            try {
                if (content == null || content.equalsIgnoreCase("")) {
                    return "";
                }

                KeyGenerator kgen = KeyGenerator.getInstance("AES");
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(password.getBytes());
                kgen.init(128, secureRandom);
                SecretKey secretKey = kgen.generateKey();
                byte[] enCodeFormat = secretKey.getEncoded();

                //輸出byte
                for(int i=0;i<enCodeFormat.length;i++)
                {
                    int b=(int)enCodeFormat[i];
                    //java轉c#
                    b= b >= 0 ? (int)b : (int)(b + 256);  
                    System.out.println(b);
                }

                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); 
                Cipher cipher = Cipher.getInstance("AES");
                byte[] byteContent = content.getBytes("utf-8");
                cipher.init(1, key);
                byte[] result = cipher.doFinal(byteContent);
                String str = Base64.encode(result);

                return str;
            } catch (NoSuchAlgorithmException var13) {
                var13.printStackTrace();
            } catch (NoSuchPaddingException var14) {
                var14.printStackTrace();
            } catch (InvalidKeyException var15) {
                var15.printStackTrace();
            } catch (UnsupportedEncodingException var16) {
                var16.printStackTrace();
            } catch (IllegalBlockSizeException var17) {
                var17.printStackTrace();
            } catch (BadPaddingException var18) {
                var18.printStackTrace();
            }

            return null;
        }

byte輸出結果 107 180 131 126 183 67 41 16 94 228 86 141 218 125 198 126

c#利用byte進行加密

//AES加密
        public static string AesEncrypt(string str, string key)
        {
            byte[] b = new byte[] { 107, 180, 131, 126, 183, 67, 41, 16, 94, 228, 86, 141, 218, 125, 198, 126 };
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

            RijndaelManaged rm = new RijndaelManaged
            {
                Key = b,//Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7

            };

            ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

此時,兩邊的加密結果終於一致了。