欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DES加密

程序员文章站 2022-05-28 14:15:04
...

DES 对称加密方式,在通信过程中经常用到。DES有四种加密模式:

 

1. ECB

Electronic Codebook

最古老简单的模式,加密数据长度必须为8的倍数(不足8位添加padding),密钥必须为8位。不依赖向量,易受到字典攻击。不推荐。

2. CBC

Cipher Block Chaining

引入初始化vector,可以使用不同的Vector产生不同的密文。缺点一个错误发生后,当前和以后的数据都会被影响。

3. CFB

Cipher Feedback 

加密反馈模式克服了需要等待8个字节才能加密的缺点,它采用了分组密码作为流密码的密钥流生成器。缺点一旦某位数据出错,会影响目前和其后8个块的数据;

4. OFB

Output Feedback 

 

其中以ECB模式最简单,不依赖向量,缺点也比较明显,易受到字典攻击。推荐使用CFB方式加密。

下面探讨一下ECB各语言下的实现。

 

一. C实现

C语言下可调用第三方库openssl实现DES加密。

#include <openssl/des.h>

/**
 * @brief DES ECB加解密,暂时不选用CBC
 * @param pSrc [in] 源字符串
 * @param pLen 源字符串长度
 * @param key  [in] 密钥
 * @param kLen 密钥长度
 * @param enc 操作类型,DES_ENCRYPT加密,DES_DECRYPT解密
 * @param cipher [out] 加密后的字符串
 * @param oLen [out] 加密后的字符串长度
 *
 * @return 加密后的字符串
 */
std::string _DESCode( const char *pSrc,
							int pLen,
							char *key,
							int kLen,
							int *oLen,
							int enc )
{
	std::string strCipher;
	std::vector<unsigned char> ciphers;
	
	DES_cblock keyEncrypt;
	memset( (void*)keyEncrypt,0,8 );
	
	// 只取key的8位
	memcpy( (void*)keyEncrypt,
			(void*)key,
			kLen >=8?8:kLen );
	
	// 设置key
	DES_key_schedule keySchedule;
	DES_set_key_unchecked(&keyEncrypt, &keySchedule);
	
	const_DES_cblock inputText;		// 每次输入8位
	DES_cblock outputText;			// 每次输出8位
	unsigned char tmp[8];			// 中间结果
	
	// 每次加密8字节
	for( int i = 0; i < pLen/8; i++ ) 
	{
		memcpy( inputText, pSrc + i*8,8 );
		DES_ecb_encrypt( &inputText,&outputText,&keySchedule,enc );
		memcpy( tmp,outputText,8 );

		// 汇总
		for( int j=0; j<8; j++ )
		{
			ciphers.push_back( tmp[j] );
		}
	}
	
	// 不足8倍数补齐
	if( pLen%8 ) 
	{
		int tmp1 = pLen/8*8;
		int tmp2 = pLen - tmp1;
		memset( (void*)inputText,0,8 );							// 填充0
		memcpy( (void*)inputText,(void*)(pSrc + tmp1), tmp2 );	// 剩余部分

		DES_ecb_encrypt( &inputText,&outputText,&keySchedule,enc );
		memcpy( tmp,outputText,8 );

		// 汇总
		for( int j=0; j<8; j++ )
		{
			ciphers.push_back( tmp[j] );
		}
	}
	
	// 复制结果
	strCipher.clear();
	strCipher.assign( ciphers.begin(),ciphers.end() );
	
	// 密文长度
	*oLen = ciphers.size();
	if( enc == DES_DECRYPT )
	{
		*oLen = strCipher.size();
	}
	
	return strCipher;
}

 

2. java实现

public static final String ALGORITHM_DES = "DES/ECB/NoPadding";	// ECB

/**
 * DES算法,加密
 *
 * @param data 待加密字符串,数据不足8位倍数会自动补全
 * @param key  加密私钥,长度不能够小于8位
 * @return 加密后的字节数组,一般结合Base64编码使用
 * @throws InvalidAlgorithmParameterException 
 * @throws Exception 
 */
public static byte[] encode(String key,String data) {
	if(data == null)
		return null;
	
	// ECB模式下,待加密字符串长度必须为8的倍数
	data = fillZero(data);
	
	try{
		DESKeySpec dks = new DESKeySpec(key.getBytes());	    	
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		
		// key的长度不能够小于8位字节
		Key secretKey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
		
		// 加密
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);           
		byte[] bytes = cipher.doFinal(data.getBytes());            
		return bytes;
	}catch(Exception e){
		System.out.println(e.getMessage());
	}
	
	return null;
}
	
/**
 * DES算法,解密
 *
 * @param data 待解密字符串
 * @param key  解密私钥,长度不能够小于8位
 * @return 解密后的字节数组,数据不足8位倍数会自动补全,需去除\0
 * @throws Exception 异常
 */
public static String decode(String key,byte[] data) {
	if(data == null)
		return null;
	
	try {
		DESKeySpec dks = new DESKeySpec(key.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		
		// key的长度不能够小于8位字节
		Key secretKey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
	   
		// 解密
		cipher.init(Cipher.DECRYPT_MODE, secretKey);
		
		// 去除空格
		byte[] output = cipher.doFinal(data);
		int i = 0;
		for( i=output.length-1; i>=0; i-- ){
			if( output[i] != '\0' )
				break;
		}
		
		return new String(output,0,i+1);
	} catch (Exception e){
		System.out.println(e.getMessage());
	}
	
	return null;
}

 

参考资料:

https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

 

 

 

 

相关标签: java c DES ECB