`
zhcheng
  • 浏览: 163252 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中3DES加密与C#兼容

    博客分类:
  • java
阅读更多

附 :近日的项目是与其他公司进行合作开发的,在传输密码时对方提出用3DES加密方式进行加密。对方提供了BASE64编码的key和向量IV,其使用的是C#语言,在进行3DES加密时使用的是CBC模式,Zeros填充方式。而我方使用的是java语言。


在Google一番后发现,两种语言之间有两种兼容方式:
1.C#采用CBC Mode,PKCS7 Padding,Java采用CBC Mode,PKCS5Padding Padding
2.C#采用ECB Mode,PKCS7 Padding,Java采用ECB Mode,PKCS5Padding Padding
但是在此次合作中,C#的填充方式为Zeros、CBC模式,使我很苦恼。在大量的Google之后,找到了解决方案,因此进行记录。

在java中用CBC模式,NoPadding填充方式。在进行加密时自己完成对密码的填充(用字节零填充)可以保证与C#中CBC模式Zeros填充方式加密结果相同。

 

 

代码:

 

import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.apache.commons.codec.binary.Base64;

/**
 * 加密方法DESede表示是3des加密方式<p>
 * 运算模式CBC,ECB。在CBC模式下使用key,向量iv;在ECB模式下仅使用key。<p>
 * 填充模式NoPadding、PKCS5Padding、SSL3Padding。<p>
 * 语言之间的兼容:<br>
 * 一个是C#采用CBC Mode,PKCS7 Padding,Java采用CBC Mode,PKCS5Padding Padding,<br>
 * 另一个是C#采用ECB Mode,PKCS7 Padding,Java采用ECB Mode,PKCS5Padding Padding,
 * <p>
 * 此段代码使用的CBC模式NoPadding填充方式、用字节零填充,目的是匹配C#语言中CBC模式,zeros填充方式。
 */
public class ThreeDES {

	/**
	 * 加密BASE64编码的KEY
	 */
	private static final String BASE64_key = "12345678901234567890123456789012";
	/**
	 * 向量IV
	 */
	private static final String _IV = "12345678";
	private final static String Algorithm = "DESede/CBC/NoPadding";//加密方法/运算模式/填充模式
	/* 加密方法DESede表示是3des加密方式
	 * 运算模式CBC,ECB。在CBC模式下使用key,向量iv;在ECB模式下仅使用key。
	 * 填充模式NoPadding、PKCS5Padding、SSL3Padding。
	 * 语言之间的兼容:
	 * 一个是C#采用CBC Mode,PKCS7 Padding,Java采用CBC Mode,PKCS5Padding Padding,
	 * 另一个是C#采用ECB Mode,PKCS7 Padding,Java采用ECB Mode,PKCS5Padding Padding,
	 */
	private static SecureRandom sr = new SecureRandom();
	private static SecretKeyFactory keyFactory;
	private static DESedeKeySpec dks;
	private static SecretKey securekey;
	private static IvParameterSpec ips;

	static {
		
		//添加jce支持(sun有其默认实现)
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		try {
			dks = new DESedeKeySpec(Base64.decodeBase64(BASE64_key.getBytes("UTF-8")));
			keyFactory = SecretKeyFactory.getInstance("DESede");
			securekey = keyFactory.generateSecret(dks);
			ips = new IvParameterSpec(_IV.getBytes("UTF-8"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 3des加密
	 * @param password 密码
	 * @return 加密后密文
	 */
	public static String encrypt(String password){
		
		Cipher cipher;
		String result = null;
		try {
			cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, securekey, ips, sr);
			byte [] arry = cipher.doFinal(FormateData(password));
			result = new String(Base64.encodeBase64(arry),"UTF-8");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 3des解密
	 *  @param password 密文
	 *  @return 解密后密码
	 */
	public static String decrypt(String password){
		
		Cipher cipher;
		String result = null;
		try {

			cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.DECRYPT_MODE, securekey, ips, sr);
			byte [] arry = cipher.doFinal(Base64.decodeBase64(password.getBytes("UTF-8")));
			result = new String(FormateByte(arry));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return result;
	}
	
	/**
	 * 密码加密时,填充字符串为8的倍数。<p>
	 * (此方法在模式是CBC模式,填充方式为NoPadding方式的情况下,用字节零填充.)
	 *	
	 * @param str
	 * 			密码
	 * @return 加密后的密文
	 */
	public static byte [] FormateData(String str) throws UnsupportedEncodingException{
		
		int yu = str.length() % 8;
		if(yu != 0){
			int size = 8 - yu;
			byte [] arr = new byte [str.length() + size];
			byte [] data = str.getBytes("UTF-8");
			int i = 0;
			for (; i < data.length; i++) {
				arr[i] = data[i];
			}
			for (int j = 0; j < size; j++,i++) {
				arr[i] = new byte [] {0}[0];
			}
			return arr;
		}
		return str.getBytes("UTF-8");
	}
	
	/**
	 * 密码解密时,将填充的字节零去掉!<p>
	 * (此方法只在模式是CBC模式,填充方式为NoPadding方式,用字节零填充 的情况下使用。)
	 * @param arr
	 * 			密文字节组
	 * 
	 * @return 密码字节组
	 */
	public static byte [] FormateByte(byte [] arr){
		
		int i = 0;
		for (; i < arr.length; i++) {
			if(arr[i] == new Byte("0")){
				break;
			}
		}
		byte [] result = new byte [i];
		for (int j = 0; j < i; j++) {
			result[j] = arr[j];
		}
		return result;
	}
	
	public static void main(String[] args) {
		String a = encrypt("12345612345612345");
		System.out.println(a);
		System.out.println(decrypt(a));
	}
}
分享到:
评论
2 楼 jurnzhou 2012-06-09  
大哥有没有ECB模式的?
1 楼 jurnzhou 2012-06-09  
是吖,他奶奶的。做.net的就是傻帽,不考虑兼容性的,用md5不是很好吗?非要乱搞,做webservice搞到这样,真恶心。感谢老大的好文,下了再试一下。

相关推荐

    PHP 3des 对称加密解密,与 java c#兼容

    PHP 3des 对称加密解密,与 java c#兼容

    C# RSA加密、支持JAVA格式公钥私钥

    C# RSA加密、支持JAVA格式公钥私钥

    3des加密解密base64编码解码完全与ASP.NET,JAVA,兼容的js

    3des加密解密 base64编码解码的源代码 完全与标准算法一致,与C# java 结果一致

    delphi与java 加密解密 DES/CBC/PKCS5Padding

    最近做一个接口,与JAVA的关于DES/CBC/PKCS5Padding 互相解密。在网上找了很多资料,摸索了3天才摸索出来。同样的明文,用JAVA加密的密文死活都跟用DELPHI加密的不相等,有时候少于8个字符的就正常,多了8个字符的就...

    Delphi与Java互通3Des加解密类(XE2)

    加密后生成一个文件,需要文件的也可以对代码进行修改。加密后的文件可以用c#、java解密,加密模式为ECB。代码已经在项目中使用。

    php DES加密算法实例分析

    主要介绍了php DES加密算法,结合实例形式分析了yii框架的DES加密算法类定义,以及兼容C#和java的3DES加密算法实现技巧,需要的朋友可以参考下

    基于openssl的DES+base64+MD5的加解密C++Demo

    基于openssl静态库的DES+base64+MD5的加解密C++Demo,其中DES采用ECB模式,pkcs5padding的填充方法;兼容JAVA,C#的DES,可应用于与网络服务器通信过程中的加解密,并且已经验证OK。...与C#/java互通的DES加密解密代码。

    Ourmsg2016

    Ourmsg的数据传输采用了GZIP流压缩和AES 256/192、3DES 192/128位加密算法,使数据传输安全可靠。因此,Ourmsg也适合安全性要求较高的私有网络内安装部署使用。同时,Ourmsg也可部署在互联网上,提供给互联网公众...

    asp.net知识库

    C#中结构与类的区别 C#中 const 和 readonly 的区别 利用自定义属性,定义枚举值的详细文本 Web标准和ASP.NET - 第一部分 XHTML介绍 在ASP.NET页面中推荐使用覆写(Override)而不是事件处理(Event Handler) 常用...

Global site tag (gtag.js) - Google Analytics