java和.net相互http請求而且通過des的cbc模式加密解密

前端時間接了個需求,要求是和.net的一下停作對接,說到底就是,互相http發送get'或者post請求,之間遇到了一些問題,記錄下來html

手下發下java發送http的post請求的代碼前端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;




public class HttpTest2 {

/**
     * 向指定 URL 發送POST方法的請求
     * 
     * @param url
     *            發送請求的 URL
     * @param param
     *            請求參數,請求參數應該是 name1=value1&name2=value2 的形式。
     * @return 所表明遠程資源的響應結果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打開和URL之間的鏈接
            URLConnection conn = realUrl.openConnection();
            // 設置通用的請求屬性
            conn.setRequestProperty("content-type", "text/html");
            // 發送POST請求必須設置以下兩行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 獲取URLConnection對象對應的輸出流
            out = new PrintWriter(conn.getOutputStream());
            // 發送請求參數
            out.print(param);
            // flush輸出流的緩衝
            out.flush();
            // 定義BufferedReader輸入流來讀取URL的響應
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("發送 POST 請求出現異常!"+e);
            e.printStackTrace();
        }
        //使用finally塊來關閉輸出流、輸入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    } 
    
    
    public static void main(String[] args) {
   
        String sr=HttpTest2.sendPost("路徑", 「參數」);

        System.out.println(sr);
  
    }
}
java

這裏有個問題必需要說明算法

由於我用的是struts2,這個地方我遇到一個問題,就是若是conn.setRequestProperty("content-type", "text/html");這個地方只能是text/html,若是改爲application/x-www-form-urlencoded這樣一直沒法獲取,這個緣由不清楚,網上說struts2中必須是text/html,其餘的沒法獲取。app


而後就是加密和解密了 ,用的是des的cbs模式,代碼以下dom

package com.besttone.commons;


import java.net.URLDecoder;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class DESUtil2 {

/**
  *
  * @return DES算法密鑰
  */
  public static byte[] generateKey() {
       try {


           // DES算法要求有一個可信任的隨機數源
           SecureRandom sr = new SecureRandom();


           // 生成一個DES算法的KeyGenerator對象
           KeyGenerator kg = KeyGenerator.getInstance("DES");
           kg.init(sr);


           // 生成密鑰
           SecretKey secretKey = kg.generateKey();


           // 獲取密鑰數據
           byte[] key = secretKey.getEncoded();


           return key;
       } catch (NoSuchAlgorithmException e) {
           System.err.println("DES算法,生成密鑰出錯!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 加密函數
  *
  * @param data
  *            加密數據
  * @param key
  *            密鑰
  * @return 返回加密後的數據
  */
  public static byte[] encrypt(byte[] data, byte[] key) {


       try {


           // DES算法要求有一個可信任的隨機數源
           SecureRandom sr = new SecureRandom();


           // 從原始密鑰數據建立DESKeySpec對象
           DESKeySpec dks = new DESKeySpec(key);


           // 建立一個密匙工廠,而後用它把DESKeySpec轉換成
           // 一個SecretKey對象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in ECB mode
           Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");


           // 用密匙初始化Cipher對象
           cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);


           // 執行加密操做
           byte encryptedData[] = cipher.doFinal(data);


           return encryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,加密數據出錯!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 解密函數
  *
  * @param data
  *            解密數據
  * @param key
  *            密鑰
  * @return 返回解密後的數據
  */
  public static byte[] decrypt(byte[] data, byte[] key) {
       try {
           // DES算法要求有一個可信任的隨機數源
           SecureRandom sr = new SecureRandom();


           // byte rawKeyData[] = /* 用某種方法獲取原始密匙數據 */;


           // 從原始密匙數據建立一個DESKeySpec對象
           DESKeySpec dks = new DESKeySpec(key);


           // 建立一個密匙工廠,而後用它把DESKeySpec對象轉換成
           // 一個SecretKey對象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in ECB mode
           Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");


           // 用密匙初始化Cipher對象
           cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);


           // 正式執行解密操做
           byte decryptedData[] = cipher.doFinal(data);


           return decryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,解密出錯。");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 加密函數
  *
  * @param data
  *            加密數據
  * @param key
  *            密鑰
  * @return 返回加密後的數據
  */
  public static byte[] CBCEncrypt(byte[] data, byte[] key, byte[] iv) {


       try {
           // 從原始密鑰數據建立DESKeySpec對象
           DESKeySpec dks = new DESKeySpec(key);


           // 建立一個密匙工廠,而後用它把DESKeySpec轉換成
           // 一個SecretKey對象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // Cipher對象實際完成加密操做
           Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
           // 若採用NoPadding模式,data長度必須是8的倍數
           // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");


           // 用密匙初始化Cipher對象
           IvParameterSpec param = new IvParameterSpec(iv);
           cipher.init(Cipher.ENCRYPT_MODE, secretKey, param);


           // 執行加密操做
           byte encryptedData[] = cipher.doFinal(data);


           return encryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,加密數據出錯!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 解密函數
  *
  * @param data
  *            解密數據
  * @param key
  *            密鑰
  * @return 返回解密後的數據
  */
  public static byte[] CBCDecrypt(byte[] data, byte[] key, byte[] iv) {
       try {
           // 從原始密匙數據建立一個DESKeySpec對象
           DESKeySpec dks = new DESKeySpec(key);


           // 建立一個密匙工廠,而後用它把DESKeySpec對象轉換成
           // 一個SecretKey對象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in CBC mode
           Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
           // 若採用NoPadding模式,data長度必須是8的倍數
           // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");


           // 用密匙初始化Cipher對象
           IvParameterSpec param = new IvParameterSpec(iv);
           cipher.init(Cipher.DECRYPT_MODE, secretKey, param);


           // 正式執行解密操做
           byte decryptedData[] = cipher.doFinal(data);


           return decryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,解密出錯。");
           e.printStackTrace();
       }


       return null;
  }


  public static void main(String[] args) {
  try {
           byte[] key = "NEMOBIlE".getBytes("utf-8");
           byte[] iv = "NEMOBIlE".getBytes("utf-8");
           byte[] data = DESUtil2.CBCEncrypt("XXXXX".getBytes("utf-8"), key, iv);
           //加密轉換  
           BASE64Encoder enc = new BASE64Encoder(); 
           
           BASE64Decoder dec = new BASE64Decoder(); 
           String encryptedtext = enc.encode(data); 
           System.out.println("加密後:" + encryptedtext);
           System.out.println("加密後:" + java.net.URLEncoder.encode(encryptedtext,"utf-8"));
           String aaa= java.net.URLDecoder.decode(java.net.URLEncoder.encode(encryptedtext,"utf-8"),"utf-8");
           byte[] resultArr = dec.decodeBuffer(aaa);
           System.out.println("解密後:" + new String(DESUtil2.CBCDecrypt(resultArr, key, iv)));
           
       } catch (Exception e) {
           e.printStackTrace();
       }
  } 
}
ide

這裏須要說明的是,若是是post請求,通常加過密後就不須要作.URLEncoder.encode的操做了,獲取進行解密就行,可是若是是url的方式,函數

那麼加密後必需要作URLEncoder.encode轉換的,而後獲取在直接進行解密,否則會出現問題的,post

下面發下  .net的des加密代碼編碼

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
 
using System.Security.Cryptography;
using System.IO;
using System.Text;


namespace MobileCommonPay.Tool
{
    public class DES2
    {


        // CBC模式


        string iv = "NEMOBIlE";
        string key = "NEMOBIlE";


        /// <summary>
        /// DES加密偏移量,必須是>=8位長的字符串
        /// </summary>
        public string IV
        {
            get { return iv; }
            set { iv = value; }
        }


        /// <summary>
        /// DES加密的私鑰,必須是8位長的字符串
        /// </summary>
        public string Key
        {
            get { return key; }
            set { key = value; }
        }


        /// <summary>
        /// 對字符串進行DES加密
        /// </summary>
        /// <param name="sourceString">待加密的字符串</param>
        /// <returns>加密後的BASE64編碼的字符串</returns>
        public string Encrypt(string sourceString)
        {
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream())
            {
                byte[] inData = Encoding.Default.GetBytes(sourceString);
                try
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }
                    return Convert.ToBase64String(ms.ToArray());
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
        }


        /// <summary>
        /// 對DES加密後的字符串進行解密
        /// </summary>
        /// <param name="encryptedString">待解密的字符串</param>
        /// <returns>解密後的字符串</returns>
        public string Decrypt(string encryptedString)
        {
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();


            using (MemoryStream ms = new MemoryStream())
            {
                byte[] inData = Convert.FromBase64String(encryptedString);
                try
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }
                    return Encoding.Default.GetString(ms.ToArray());
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
        }


        /// <summary>
        /// 對文件內容進行DES加密
        /// </summary>
        /// <param name="sourceFile">待加密的文件絕對路徑</param>
        /// <param name="destFile">加密後的文件保存的絕對路徑</param>
        public void EncryptFile(string sourceFile, string destFile)
        {
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路徑不存在!", sourceFile);


            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);


            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            {
                try
                {
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 對文件內容進行DES加密,加密後覆蓋掉原來的文件
        /// </summary>
        /// <param name="sourceFile">待加密的文件的絕對路徑</param>
        public void EncryptFile(string sourceFile)
        {
            EncryptFile(sourceFile, sourceFile);
        }


        /// <summary>
        /// 對文件內容進行DES解密
        /// </summary>
        /// <param name="sourceFile">待解密的文件絕對路徑</param>
        /// <param name="destFile">解密後的文件保存的絕對路徑</param>
        public void DecryptFile(string sourceFile, string destFile)
        {
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路徑不存在!", sourceFile);


            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);


            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            {
                try
                {
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 對文件內容進行DES解密,加密後覆蓋掉原來的文件
        /// </summary>
        /// <param name="sourceFile">待解密的文件的絕對路徑</param>
        public void DecryptFile(string sourceFile)
        {
            DecryptFile(sourceFile, sourceFile);
        }
    }
}


.net中加密解密的問題,主要就是編碼Encoding.Default這樣默認的就不是utf-8了,這樣加密出問題,這個時候要換成Encoding.GetEncoding("UTF-8")這樣就能夠了,

最後說下,對接真是麻煩,遇到好說話的人還好,若是遇到一些很差搞的人,那真是頭疼的........

相關文章
相關標籤/搜索