JAVA 3DES 加密解密(二)

关于3DES算法C版本与JAVA版本的兼容问题

今天在一个项目中遇到报文中密码字段3DES加密的情况,对方提供了JAVA版的例子,我这里下载了一个C版本的3DES实现源码包,尝试后发现加密后结果不同。

在网上查了下,发现有很多和这个情况一样,在《用java实现3des加密》一文中提到:

对于其他语言开发的3des,一定要采用相同的mode和padding才能保证通信。

重点就在这里,这里说的mode和padding是什么意思呢?(注:以下内容大段抄袭《DES 算法的 C++ 与 JAVA 互相加解密》-。-)

首先说mode。mode在这里指加密模式。常见的加密模式有ECB/CBC/CFB/OFB四种。加密算法是按块进行加密的,例如DES是64bit(8 bytes)一个块进行加密,每次输入8个字节的明文进行加密,输出8个字节密文,如果是明文一共16个字节长,则分成两组加密。例如明文是12345678 12345678(空格为了查看方便,实际不包含,下同),那么加密的结果类似C4132737962C519C  C4132737962C519C,如果是你,看到密文什么感想?没错,这个应该是一组数据重复两遍吧?这中加密模式就是ECB,分组之间没有联系,只要组和组明文相同,那么他们的密文也是相同的。为了解决这个问题,出现了其他的加密模式,分别为CBC 加密模式(密码分组连接),CFB加密模式(密码反馈模式),OFB加密模式(输出反馈模式)。CBC 是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,CFB 和 OFB 则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果网络传输时发生了一部分错误,则后面的解密结果就可能是错误的(ECB模式仅影响传输错误的那个块)。

接下来是padding。padding在这里指填充方式,假如明文是10位,按照8bytes分组,正好1组多2个byte,这2个byte怎么加密?这时候必须对明文进行填充。填充方式很多,具体可以参考《Using Padding in Encryption》一文。常用的PKCS#7,该填充方法是将每一个补充的字节内容填充为填充的字节个数;例如明文长度是 100 , 分组的大小是32个字节,那么需要分为四组,补充28个字节,那么补充的字节全部补充为’\0×28′。还有一种PKCS#5,和PKCS#7的区别就是,分组的大小为8个字节。另外还有一个规定,就是如果明文刚刚好进行分组,那么需要补充一个独立的分组出来。例如 DES明文:12345678,为 8 个字节,则必须补充8个0×08至16个字节,然后进行加密;解密后的字符串为12345678\x08\x08\x08\x08\x08\x08\x08\x08,需要将后面的0×08去掉,就能得到原始明文。

知道了这些,再去看下JAVA版本的3DES加解密。
private static final String Algorithm = "DESede"; //定义加密算法,可用DES,DESede,Blowfish
在这里,DESede算法即为传说中的3DES加密,其mode为ECB,padding为PKCS#5。按照上面所描述的,我封装了两个函数。

首先是包含的头文件,以及预定义内容:

1
2
3
4
#include "d3des.h"
#define BLOCK_BYTES 8
#define SetKey(a,b) des3key((a),(b))
#define DoCrypt(a,b) Ddes((a),(b))

其中d3des.h为网上下载的3des的C版本实现。网上很好找。

然后是加密函数:将from中长度为len个字节的明文,经过密钥key的DESede加密,获得密文存放在to中,函数返回值为密文长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
unsigned  int
DESede_Encrypt ( char  *to,  char  *from,  unsigned  int len,  char  *key )
{
     int  i ;
     unsigned  int padding_bytes ;
     char  *data ;
     unsigned  char  *p,  *q ;

    data  =  ( char  * ) malloc ( sizeof ( char ) *len +BLOCK_BYTES ) ;
     memcpy (data, from, len ) ;

     /* PKCS5 padding */
    padding_bytes  = BLOCK_BYTES  - len  % BLOCK_BYTES ;
     for  ( i = 0 ; i <padding_bytes ;  ++)  {
        data [len +i ]  =  ( unsigned  char )padding_bytes ;
     }
    len  + = padding_bytes ;

     /* encrypt */
    SetKey (key, EN0 ) ;
     for  ( p =data, q =to ; p < ( unsigned  char  * )data +len ; p + =BLOCK_BYTES, q + =BLOCK_BYTES  )  {
        DoCrypt (p, q ) ;
     }

     free (data ) ;
     return len ;
}

解密函数:将from中长度为len个字节的密文,经过密钥key的DESede解密,获得明文存放在to中,函数返回值为明文长度。

1
2
3
4
5
6
7
8
9
10
unsigned  int
DESede_Decrypt ( char  *to,  char  *from,  unsigned  int len,  char  *key )
{
     unsigned  char  *p,  *q ;
    SetKey (key, DE1 ) ;
     for  ( p =from, q =to ; p < ( unsigned  char  * )from +len ; p + =BLOCK_BYTES, q + =BLOCK_BYTES  )  {
        DoCrypt (p, q ) ;
     }
     return len - ( unsigned  int )to [len - 1 ] ;
}

以上两个函数中的key(24位)以及其他输入参数都需要函数调用者负责校验。

参考资料:
[1] 用java实现3des加密
[2] DES 算法的 C++ 与 JAVA 互相加解密
[3] Using Padding in Encryption
[4] Block cipher modes of operation

分类: AlgorithmC/CPP 标签: 3DESAlgorithmCJAVApadding 1个评论  Permalink
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值