背景:在和外部系統經過HTTP方式跳轉時, 爲保障傳輸參數安全性, 採用AES 加密參數. 關於對稱加密中 AES, DES, CBC, ECB, PKCS5Padding 概念可參考https://blog.csdn.net/qq_35698774/article/details/78964249 php
問題: 我方技術java, 對方使用PHP. 使用一樣加密算法DES, 加密模式ECB, 填充方式PKCS5Padding, 編碼處理BASE64, 解密仍失敗. 最終發現緣由: JAVA 端加密時使用了SHA1PRNG, 經過google最終解決 , 拿來分享.html
加密代碼中黃色部分是解決linux下隨機生成key添加的. 正是這個代碼 ,致使php解密異常.java
1 private static SecretKeySpec getSecretKey(final String key) { 2 //返回生成指定算法密鑰生成器的 KeyGenerator 對象 3 KeyGenerator kg = null; 4 5 try { 6 kg = KeyGenerator.getInstance(KEY_ALGORITHM); 7 //防止linux下 隨機生成key 8 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); 9 secureRandom.setSeed(key.getBytes()); 10 //DES 要求密鑰長度爲 56 11 kg.init(56, secureRandom); 12 13 //生成一個密鑰 14 SecretKey secretKey = kg.generateKey(); 15 16 return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 轉換爲DES專用密鑰 17 } catch (NoSuchAlgorithmException ex) { 18 Logger.getLogger(DESUtils.class.getName()).log(Level.SEVERE, null, ex); 19 } 20 21 return null; 22 }
php 代碼:linux
/** * 解密 * * @param $encrypted * @return string */ public function decrypt($encrypted) { if ($this->output == self::OUTPUT_BASE64) { $encrypted = base64_decode($encrypted); } else if ($this->output == self::OUTPUT_HEX) { $encrypted = hex2bin($encrypted); } $key2 = substr(openssl_digest(openssl_digest($this->key, 'sha1', true), 'sha1', true), 0, 16); $sign = @openssl_decrypt($encrypted, $this->method, $key2, $this->options, $this->iv); $sign = $this->unPkcsPadding($sign); $sign = rtrim($sign); return $sign; }
代碼中, 綠色部分是解決此問題關鍵.算法
$key2 = substr(openssl_digest(openssl_digest($this->key, 'sha1', true), 'sha1', true), 0, 16);安全
因爲以前未接觸php, 本地搭建php環境代價較多, 直接找在線的php環境 , 如https://www.dooccn.com/php/, 可直接運行, 並有錯誤調試信息, 很是方便.dom
技術問題google 真的是靠譜, 找準搜索關鍵詞相當重要.this
參考:google
https://www.jianshu.com/p/9591a3f59b19編碼
https://www.cnblogs.com/dragon16/p/7238858.html