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

3DES加密算法(ECB模式与PKCS7填充方式)

阅读更多

参考

http://baike.baidu.com/view/350958.htm

http://blog.163.com/zhqh43@126/blog/static/4043302720093276344788/

 

背景

最近由于公司项目的需要,最近研究了3DES算法运用,我的公司有一个合作的公司,提供webservice接口,是C#写的,用到3DES加密算法,C#代码以下:

public static string Encrypt3DES(string a_strString, string a_strKey)
{
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
            DES.Key = ASCIIEncoding.ASCII.GetBytes(a_strKey);
            DES.Mode = CipherMode.ECB;
            ICryptoTransform DESEncrypt = DES.CreateEncryptor();
            byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(a_strString);
            return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
}

 

 public static string Decrypt3DES(string a_strString, string a_strKey)
 {
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
            DES.Key = ASCIIEncoding.ASCII.GetBytes(a_strKey);
            DES.Mode = CipherMode.ECB;
            DES.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
            ICryptoTransform DESDecrypt = DES.CreateDecryptor();
            string result = "";
            try
            {
                byte[] Buffer = Convert.FromBase64String(a_strString);
                result = ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
            }
            catch (Exception e)
            {

            }
            return result;
}

 

解法

直接使用公司框架中的3DES算法类,代码如下:

package com.cn.crypt.implement;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.log4j.Logger;


/**
 * <p>
 * Title: 3DES加密算法实现
 * </p>
 * 
 * <p>
 * Description: 3DES加密算法实现
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * 
 * <p>
 * Company: com.cn
 * </p>
 * 
 * @author LinPeng
 * @version 1.0
 */
public class Crypto3DESImpl implements Crypto3DSModule {
	/**
	 * logger 日志
	 */
	public static Logger logger = Logger.getLogger(Crypto3DESImpl.class);

	/**
	 * 将byte数组转换为表示16进制值的字符串, 如:byte[]{8,18}转换为:0813, 和public static byte[]
	 * hexStr2ByteArr(String strIn) 互为可逆的转换过程
	 * 
	 * @param arrB
	 *            需要转换的byte数组
	 * @return 转换后的字符串
	 * @throws Exception
	 *             本方法不处理任何异常,所有异常全部抛出
	 */
	private static String byteArr2HexStr(byte[] arrB) throws Exception {
		int iLen = arrB.length;
		// 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
		StringBuffer sb = new StringBuffer(iLen * 2);
		for (int i = 0; i < iLen; i++) {
			int intTmp = arrB[i];
			// 把负数转换为正数
			while (intTmp < 0) {
				intTmp = intTmp + 256;
			}
			// 小于0F的数需要在前面补0
			if (intTmp < 16) {
				sb.append("0");
			}
			sb.append(Integer.toString(intTmp, 16));
		}
		return sb.toString();
	}

	/**
	 * 将表示16进制值的字符串转换为byte数组, 和public static String byteArr2HexStr(byte[] arrB)
	 * 互为可逆的转换过程
	 * 
	 * @param strIn
	 *            需要转换的字符串
	 * @return 转换后的byte数组
	 * @throws Exception
	 *             本方法不处理任何异常,所有异常全部抛出
	 * @author <a href="mailto:zhangji@aspire-tech.com">ZhangJi</a>
	 */
	private static byte[] hexStr2ByteArr(String strIn) throws Exception {
		byte[] arrB = strIn.getBytes();
		int iLen = arrB.length;

		// 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
		byte[] arrOut = new byte[iLen / 2];
		for (int i = 0; i < iLen; i = i + 2) {
			String strTmp = new String(arrB, i, 2);
			arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
		}
		return arrOut;
	}

	// 加密和解密函数的使用用法实例
	public static void main(String[] args) throws Exception {
		Crypto3DESImpl des = new Crypto3DESImpl();
		// 设置算法
		des.setDesAlgorithm("DES");
		// 设置密钥
		des.setKeyString("18947f2c467c4763fd2492cf");
		String str = des.decrypt("8394bef13776eae45547cb484e075963f9a7e9542301f87a82ef9a4dcaf4b0c5e1bcc66c34ecabf1b8d8012a7357c85271ae3ca2a19887cb6228677a84acd22ae3aa4a230a30f91557fa8677fe6c8edb81cf8e93f3128cb841a3b863f0a790bfc9bbc8c6c5979df32ca3f7fb1ffff1ad0e30bf8bf14c1a778808d82064de6b85d46eb3c1c0b8465e124eb113e5d56e519aa7e92819993ac9");
		
		logger.debug(str);
 
	}

	/**
	 * 3desAlgorithm 3des加密算法,可用 DES,DESede,Blowfish
	 */
	public String desAlgorithm;

	/**
	 * keyString 加密密钥
	 */
	String keyString;

	public Crypto3DESImpl() {
		Security.addProvider(new com.sun.crypto.provider.SunJCE());
	}

	/**
	 * decrypt 3DES单参数解密函数
	 * 
	 * @param src
	 *            byte[]
	 * @return byte[]
	 * @throws Exception
	 */
	private byte[] decrypt(byte[] src) throws Exception {
		byte[] keybyte = keyString.getBytes();
		// 生成密钥
		Key deskey = getKey(keybyte);
		Cipher decryptCipher = Cipher.getInstance(desAlgorithm);
		decryptCipher.init(Cipher.DECRYPT_MODE, deskey);
		return decryptCipher.doFinal(src);
	}

	/**
	 * decrypt 3DES单参数解密函数
	 * 
	 * @param src
	 *            String
	 * @return String
	 * @throws Exception
	 */
	public String decrypt(String src) throws Exception {
		byte[] srcBytes = Crypto3DESImpl.hexStr2ByteArr(src);
		return new String(this.decrypt(srcBytes));
	}

	/**
	 * encrypt 3DES单参数加密函数
	 * 
	 * @param src
	 *            byte[] 输入字符数组
	 * @return byte[] 返回字符数组
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws BadPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws Exception
	 */
	public byte[] encrypt(byte[] src) throws NoSuchPaddingException,
			NoSuchAlgorithmException, InvalidKeyException, BadPaddingException,
			IllegalBlockSizeException, Exception {
		byte[] keybyte = keyString.getBytes();
		// 生成密钥
		Key deskey = getKey(keybyte);
		// 加密
		Cipher c1 = Cipher.getInstance(desAlgorithm);
		c1.init(Cipher.ENCRYPT_MODE, deskey);
		return c1.doFinal(src);
	}

	/**
	 * encrypt 3DES单参数加密函数
	 * 
	 * @param src
	 *            String
	 * @return String
	 * @throws Exception
	 */
	public String encrypt(String src) throws Exception {
		byte[] srcBytes = src.getBytes();
		return Crypto3DESImpl.byteArr2HexStr(this.encrypt(srcBytes));
	}

	public String getDesAlgorithm() {
		return desAlgorithm;
	}

	/**
	 * 从指定字符串生成密钥,密钥所需的字节数组长度为8位 不足8位时后面补0,超出8位只取前8位
	 * 
	 * @param arrBTmp
	 *            构成该字符串的字节数组
	 * @return 生成的密钥
	 * @throws Exception
	 */
	private Key getKey(byte[] arrBTmp) throws Exception {
		// 创建一个空的8位字节数组(默认值为0)
		byte[] arrB = new byte[8];
		// 将原始字节数组转换为8位
		for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
			arrB[i] = arrBTmp[i];
		}
		// 生成密钥
		Key key = new SecretKeySpec(arrB, desAlgorithm);
		return key;
	}

	public String getKeyString() {
		return keyString;
	}

	public void setDesAlgorithm(String desAlgorithm) {
		this.desAlgorithm = desAlgorithm;
	}

	public void setKeyString(String keyString) {
		this.keyString = keyString;
	}

}

   测试之后发现,C#加密与解密完全与上面的java代码3DES结果不一样,不知道怎么回事,难道是我们框架代码有问题,那我就开始在网上搜索3DES相关例子,发现3DES还有两个重要参数:模式与填充方式,又仔细看了看C#代码中提到了ECB与PKCS7,正是3DES重要参数,但我还是不会写,又在网上找,代码如下:

package com.cn.crypt.implement;

import java.net.URLEncoder;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.cn.crypt.IDESecbpkcs7;

/**
 * @author 刘宗安
 * @version 1.0 功能 :釆用3DES标准以模式为ECB、填充方式为PKCS7加密数据
 */
public class DESecbpkcs7Impl implements IDESecbpkcs7
{
	private Cipher cipher = null;
	// base64编码
	private BASE64Encoder base64Encode = new BASE64Encoder();
	private BASE64Decoder base64Decode = new BASE64Decoder();
	// 密钥
	private String key = "";
	// 过滤换行
	private boolean filter = true;

	public String getKey()
	{
		return key;
	}

	public boolean getFilter()
	{
		return filter;
	}
	
	/**
	 * 设置密钥
	 * @param key
	 */
	public void setKey(String key)
	{
		this.key = key;
	}

	public void setFilter(boolean filter)
	{
		this.filter = filter;
	}

	private final Cipher initCipher(int mode)
	{
		try
		{
			// 添加新安全算法:PKCS7
			Security.addProvider(new BouncyCastleProvider());
			String algorithm = "DESede/ECB/PKCS7Padding";
                         		SecretKey desKey = new SecretKeySpec((new BASE64Decoder()).decodeBuffer(key), algorithm);
			//SecretKey desKey = new SecretKeySpec(key.getBytes("ASCII"), algorithm);
			Cipher tcipher = Cipher.getInstance(algorithm);
			tcipher.init(mode, desKey);
			return tcipher;
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加密以charset编码做为密文
	 * 
	 * @param src
	 *            明文
	 * @param charset
	 *            编码,例:UTF8、BASE64
	 * @return
	 */
	public String encrypt(String src, String charset)
	{
		try
		{
			return URLEncoder.encode(encrypt(src), charset);
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * @param src 二进制数组
	 * @return
	 * @throws Exception
	 */
	private byte[] decrypt(byte[] src) throws Exception
	{
		cipher = initCipher(Cipher.DECRYPT_MODE);
		return cipher.doFinal(src);
	}
	/**
	 * 解密
	 * @param src 密文
	 * @return
	 * @throws Exception
	 */
	public  String decrypt(String src) throws Exception
	{
		byte[] bt=base64Decode.decodeBuffer(src);
		byte[] sbt=decrypt(bt);
		return new String(sbt,"ASCII");
	}
	/**
	 * 加密以base64做为密文
	 * 
	 * @param src
	 *            明文
	 * @return 密文
	 */
	public String encrypt(String src)
	{
		cipher = initCipher(Cipher.ENCRYPT_MODE);
		byte[] dd = encrypt(src.getBytes());
		String str = base64Encode.encode(dd);
		str = str.replaceAll("\r", "");
		str = str.replaceAll("\n", "");
		return str;
	}

	/**
	 * 
	 * @param src
	 * @return
	 */
	public byte[] encrypt(byte[] src)
	{
		try
		{
			return cipher.doFinal(src);
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws Exception
	{
		DESecbpkcs7Impl cWebService3DES = new DESecbpkcs7Impl();
		Security.addProvider(new com.sun.crypto.provider.SunJCE());
		cWebService3DES.key = "18947f2c467c4763fd2492cf".toUpperCase();
		System.out.println("18947f2c467c4763fd2492cf".toUpperCase());
		String s = cWebService3DES
				.encrypt("<?xml version=\"1.0\" encoding=\"utf-8\" ?><SXData><UserID>bjtele-union</UserID><EnCode>9289a37b0f5cb18abb5aa4d33e85afe9</EnCode></SXData>");
		s = s.replaceAll("\r", "");
		s = s.replaceAll("\n", "");
		System.out.println(s);
		System.out.println(cWebService3DES.decrypt(s));
	}

}

 

测试之后,发现与C#还是不一样,这下我可晕,不知道从哪里修改好?哎,真不知道从何下手了,又继续找原因,后来发现上面C#代码中存在这一段代码:

 

 DES.Key = ASCIIEncoding.ASCII.GetBytes(a_strKey);

 

呵呵,将以前的BASE64编码代码

SecretKey desKey = new SecretKeySpec((new BASE64Decoder()).decodeBuffer(key), algorithm);

 

 

修改java代码KEY为ASCII:

	SecretKey desKey = new SecretKeySpec(key.getBytes("ASCII"), algorithm);

 

 这一下终于调试成功了,最后还要提醒一下将加密后的二进制数组以base64编码进行显示,代码如下:

String str = base64Encode.encode(dd);

 

OK 

 

 

 

1
0
分享到:
评论
4 楼 飞飞965 2014-06-22  
在没有用base64加解密的情况下,我用你的方法解密是中文出现了乱码,而英文和数字没事,而且解密出来的明文前面多了一个问号,这是什么情况?
3 楼 lydawen 2012-08-03  
冰封--world 写道
楼主是否可以给我发个你的列子 1793815563@qq.com
多谢

http://www.iteye.com/topic/540708
2 楼 冰封--world 2012-08-02  
楼主是否可以给我发个你的列子 1793815563@qq.com
多谢
1 楼 lydawen 2010-02-08  
楼主有没有测一下呀,这样的工具类在高并发情况下会有异常出现。如1000个线程

相关推荐

    北京联通全网有关网上订购和点播接口URL加密算法 * *采用3DES加密, ECB模式/使用PKCS7方式填充不足位, *目前给的密钥是192位(24个字节)经过BASE64编码后的可见字符串

    北京联通全网有关网上订购和点播接口URL加密算法 * *采用3DES加密, ECB模式/使用PKCS7方式填充不足位, *目前给的密钥是192位(24个字节)经过BASE64编码后的可见字符串

    des 及3des ecb pkcs5padding 加密 c++

    总的来说,理解和实现DES及3DES的ECB模式加密,以及PKCS5Padding在C++中的应用,需要对加密算法原理、C++编程以及OpenSSL库有一定的掌握。这样的技能在信息安全、网络通信和数据保护等领域都有广泛的应用。通过实际...

    delphi版的3DES加密 pkcs5padding填充

    总结起来,Delphi中的3DES加密结合了ECB模式和PKCS5Padding填充,提供了一种可靠的数据加密方案。通过源代码文件`DesCipher.pas`,我们可以深入了解这种加密方法的具体实现,这对于理解和使用3DES加密在Delphi环境中...

    对接java AES/ECB/PKCS7Padding加密

    在IT行业中,尤其是在...总之,PHP与Java之间的AES/ECB/PKCS7Padding加密对接是一个需要细心处理的过程,涉及到加密算法、填充方式以及编码转换等多个环节。通过合理的代码实现,可以确保数据在两个平台间的安全传输。

    DES加密算法C++实现

    常见的填充方式有PKCS#7,它保证了填充后的数据长度是64位的整数倍。在C++中,需要编写填充和解填充的函数。 7. **编码和解码**:在C++中,原始的二进制数据通常需要转换为字符字符串进行存储和传输,如使用hex编码...

    基于openssl的3DES加密算法

    3DES加密算法,使用openssl库,ECB算法,pkcs7padding填充模式(借鉴网上的算法,并经过自己的改良,可以实现加密与解密)

    AES 示例(CBC算法模式 PKCS5填充模式)

    CBC(Cipher Block Chaining)是AES的一种工作模式,而PKCS5(Public Key Cryptography Standards #5)则是一种常用的填充方式,用于确保输入数据长度能够完美适应块密码处理。在本示例中,我们将深入理解AES-CBC-...

    Delphi10.2 DES/CBC/PKCS5Padding/UTF-8

    总之,"Delphi10.2 DES/CBC/PKCS5Padding/UTF-8" 是一个针对Delphi环境的加密库,它实现了DES加密算法的CBC模式,遵循PKCS5填充规则,同时处理了中文字符的UTF-8编码,确保了与其他语言环境的互操作性。

    JAVA实现des加密算法 实例

    DES(Data Encryption Standard)是一种对称加密算法,广泛应用于数据的加密保护。在Java中,我们可以使用`javax.crypto`包中的类来实现DES加密。以下将详细介绍如何在Java中实现DES加密,并提供一个实例。 首先,...

    des加密算法实现任意文件加解密

    2. **初始化 Cipher 对象**:使用`Cipher`类的`getInstance()`方法获取一个DES加密/解密对象,并设置其工作模式(如ECB、CBC等)和填充模式(如NoPadding、PKCS5Padding等)。 3. **加密操作**:调用`Cipher`对象的`...

    3DES-ECB模式加密,可以与C#和Java互通

    标签中的“3des c/c++”表明本主题关注的是使用C或C++语言实现3DES加密算法。 在提供的压缩包文件中,有两个文件:`des.cpp`和`des.h`。`des.cpp`通常包含实际的3DES-ECB加密算法的实现代码,而`des.h`可能包含了...

    DES加密算法JAVA代码

    ### DES加密算法JAVA代码知识点详解 #### 一、概述 数据加密标准(Data Encryption Standard,简称DES)是一种广泛使用的对称密钥加密技术。在Java中实现DES加密解密功能通常涉及以下几个关键类:`javax.crypto....

    DES加密_delphi_加解密_des_

    DES(Data Encryption Standard)是一种经典的对称加密算法,由IBM在1970年代初开发,后被美国国家标准局(NIST)采纳为标准。它主要用于保护数据的安全,通过一个密钥将明文数据转化为密文,然后可以使用相同的密钥...

    java AES,DES,3DES,RAS,DSA 加密算法实现

    在Java中,可以使用`Cipher.getInstance("DESede/CBC/PKCS5Padding")`进行3DES加密。 4. **RSA( Rivest-Shamir-Adleman)** RSA是一种非对称加密算法,基于大整数因子分解的困难性。它有两个密钥:公钥用于加密,...

    DES加密算法(JAVA和C语言描述)结果一致

    为了确保Java和C语言的加密结果一致,关键在于确保两者的密钥设置、模式(这里是ECB)和填充方式(PKCS5Padding在Java中,相当于PKCS7填充在C语言的OpenSSL中)相同。在上述例子中,我们使用了相同的密钥、模式和...

    'DES加密算法在VB中的实现

    3. **选择模式和填充方式**:DES支持多种操作模式(如ECB、CBC等)和填充方式(如PKCS7、ZeroPadding等)。在VB中,可以使用Mode和Padding属性设置。 ```vb des.Mode = CipherMode.ECB '默认模式 des.Padding = ...

    c++,c#互通DES加密算法(支持中文)

    填充方式有多种,最常见的是PKCS7填充,确保数据长度为8的倍数。 3. **编码转换**:在处理中文字符时,需要考虑到字符编码。C++和C#默认使用不同的编码,C++通常是ASCII或宽字符集,C#则常用Unicode(UTF-16)。在...

    C++和JAVA,AES/ECB/PKCS5Padding 互通

    AES是一种广泛使用的对称加密算法,而ECB是其一种加密模式,PKCS5则是一种填充方式,确保数据长度符合AES的块大小要求。 首先,让我们详细了解这三个概念: 1. **AES(Advanced Encryption Standard)**:是一种...

    AES_CBC_PKCS5加解密 MD5加密

    是一种广泛应用的块密码算法,而CBC(Cipher Block Chaining)模式和PKCS5(Public Key Cryptography Standards #5)填充模式是AES加密中常用的模式和填充方式。下面将详细解释这些概念以及如何在QT环境中实现它们。...

    des加密算法的JAVA 实现

    // 使用DES,不使用密钥分组,填充方式为PKCS5 cipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom()); ``` 4. 加密和解密操作: 对于加密,调用`cipher.doFinal()`方法。 ```java byte[] ...

Global site tag (gtag.js) - Google Analytics