您的位置:首页 > 理论基础 > 计算机网络

java和.net相互http请求并且经过des的cbc模式加密解密

2014-04-25 17:54 387 查看
前端时间接了个需求,要求是和.net的一下停做对接,说到底就是,互相http发送get'或者post请求,之间遇到了一些问题,记录下来

手下发下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);

}

}

这里有个问题必须要说明

因为我用的是struts2,这个地方我遇到一个问题,就是如果conn.setRequestProperty("content-type", "text/html");这个地方只能是text/html,如果改成application/x-www-form-urlencoded这样一直无法获取,这个原因不清楚,网上说struts2中必须是text/html,其他的无法获取。

然后就是加密和解密了 ,用的是des的cbs模式,代码如下

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();

}

}

}

这里需要说明的是,如果是post请求,一般加过密后就不需要做.URLEncoder.encode的操作了,获取进行解密就行,但是如果是url的方式,

那么加密后必须要做URLEncoder.encode转换的,然后获取在直接进行解密,不然会出现问题的,

下面发下
.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")这样就可以了,

最后说下,对接真是麻烦,遇到好说话的人还好,如果遇到一些不好搞的人,那真是头疼的........
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: