最近在跟三方對接 對方采用AES加解密 作為一個資深neter Ctrl CV 是我最大的優點 所以我義正言辭的問他們要了demo
java demo代碼:
public class EncryptDecryptTool
{private static final String defaultCharset = "UTF-8";private static final String KEY_AES = "AES";private static final String KEY_MD5 = "MD5";private static MessageDigest md5Digest;static {try {md5Digest = MessageDigest.getInstance(KEY_MD5);} catch (NoSuchAlgorithmException e) {//}}public String encrypt(String message, String key) throws Exception
{return doAES(message, key, Cipher.ENCRYPT_MODE);
}public String decrypt(String message, String key) throws Exception
{return doAES(message, key, Cipher.DECRYPT_MODE);
}/*** 加解密** @param data* @param key* @param mode* @return* @throws NoSuchPaddingException * @throws NoSuchAlgorithmException */
private static String doAES(String data, String key, int mode) throws Exception
{if (StringUtils.isBlank(data) || StringUtils.isBlank(key)) {return null;}boolean encrypt = mode == Cipher.ENCRYPT_MODE;byte[]content;if (encrypt) {content = data.getBytes(defaultCharset);} else {content = Base64.decodeBase64(data.getBytes());}SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset)), KEY_AES);Cipher cipher = Cipher.getInstance(KEY_AES);// 創建密碼器
cipher.init(mode, keySpec);// 初始化byte[] result = cipher.doFinal(content);if (encrypt) {return new String(Base64.encodeBase64(result, false), defaultCharset);} else {return new String(result, defaultCharset);}}
}EncryptDecryptTool tool = new EncryptDecryptTool();try{//這里key的位數是個坑 之前找的一堆資料 java C#通用版啥的 都說key一定要是16位的 結果后來我發現 靠String msg = tool.decrypt("{\"Name\":\"20180122T155221\",\"OrderNo\":\"Test1000012059021180000008153\"}", "64個英文字母");System.out.println(msg);}catch (Exception e){// TODO Auto-generated catch blocke.printStackTrace();}
哇咔咔 這不是大名鼎鼎的java嘛 但這難不倒我 不是還有IKVM 照樣Ctrl CV
新建一個.NET Standard項目NuGet 安裝IKVM
C#主要代碼
public class EncryptDecryptTool{private static readonly string KEY_AES = "AES";private static readonly string KEY_MD5 = "MD5";private static MessageDigest md5Digest;static EncryptDecryptTool(){try{md5Digest = MessageDigest.getInstance(KEY_MD5);}catch (NoSuchAlgorithmException e){//}}public string encrypt(string message, string key){return doAES(message, key, Cipher.ENCRYPT_MODE);}public string decrypt(string message, string key){return doAES(message, key, Cipher.DECRYPT_MODE);}/// <summary>/// /// </summary>/// <param name="data"></param>/// <param name="key"></param>/// <param name="mode"></param>/// <returns></returns>private static string doAES(string data, string key, int mode){bool encrypt = mode == Cipher.ENCRYPT_MODE;byte[] content;if (encrypt){content = Encoding.UTF8.GetBytes(data);}else{content = Convert.FromBase64String(data);}SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(Encoding.UTF8.GetBytes(key)), KEY_AES);Cipher cipher = Cipher.getInstance(KEY_AES);// 創建密碼器cipher.init(mode, keySpec);// 初始化byte[] result = cipher.doFinal(content);if (encrypt){return Convert.ToBase64String(result);}else{return Encoding.UTF8.GetString(result);}}}static void Main(string[] args){var encryptDecryptTool = new EncryptDecryptTool();Console.WriteLine(encryptDecryptTool.encrypt("jack","64位密鑰"));}
運行NetCore控制臺
這是Net Framework Net Core以及IKVM不得不說的故事了 但是下午就要聯調了 總不能給三方講一千零一夜 沒事這難不倒我 新建一個Net Framework控制臺
static void Main(string[] args){try{var argsLength = args.Length;if (argsLength > 1){EncryptDecryptTool tool = new EncryptDecryptTool();string result = string.Empty;if (args[0] == "encrypt"){result = tool.encrypt(args[1]);}else{result = tool.decrypt(args[1]);}Console.WriteLine(result);}}catch (Exception ex){Console.WriteLine(ex.Message);}}
Net Core調用
string path = @"D:\WebSite\AESTool.exe";var method="encrypt";var msg="this is msg";string fileName = path;Process p = new Process();p.StartInfo.UseShellExecute = false;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.FileName = fileName;p.StartInfo.CreateNoWindow = true;p.StartInfo.Arguments = $"{method} {msg}";//參數以空格分隔p.Start();var output = await p.StandardOutput.ReadToEndAsync();
測試ok 沒問題 就是時間有點久 加密解密每次差不多都要一秒
就這樣跑了一段時間 今天閑下來 想起上次的一秒
嗯 寫好辭職申請 備份 好的 我要開始重構了 嗯 知己知彼百戰不殆 那我們先去維密上大概了解一下AES
好吧 我知道你也沒看懂
我們還是看代碼吧 作為一個資深程序員的直覺
之前查了一堆資料 都說java C# AES加解密通用版 key的位都必須是16位 害的笨菜鳥陷入了思維誤區 我們再看上面那段代碼 Debug進去看 發現是用MD5算法根據key生成長度16的byte數據 16啊 多么敏感的數字 就是哈希計算 靠
果斷google,Ctrl CV
public static class EncryptDecryptTool{private const string key = "qCOHfwhXgsZFBFSeZeGOlXtZbKOzApLBuZoWxrQjcmoxYHfrWZzdyFbvGuMcZqmC";/// <summary>/// MD5哈希計算/// </summary>/// <param name="key"></param>/// <returns></returns>public static byte[] ConvertStringToMD5(string key){byte[] ByteData = Encoding.UTF8.GetBytes(key);MD5 oMd5 = MD5.Create(); byte[] HashData = oMd5.ComputeHash(ByteData);return HashData;}/// <summary>/// AES加密 /// </summary>/// <param name="toEncrypt"></param>/// <returns></returns>public static string Encrypt(string toEncrypt){byte[] keyArray = ConvertStringToMD5(key);byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);}/// <summary>/// AES解密/// </summary>/// <param name="toDecrypt"></param>/// <returns></returns>public static string Decrypt(string toDecrypt){byte[] keyArray = ConvertStringToMD5(key);byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateDecryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return Encoding.UTF8.GetString(resultArray);}