DES 算法的 C++ 与 JAVA 互相加解密


======================================================
注:本文源代码点此下载
======================================================

在 java 中,从 j2ee1.4 开始,sun 提供了 jce( java crypto engine ),其中包含有 des 算法,在 java 中使用 des 算法的代码示例如下:

java crypto example

import java.security.key;

import java.security.security;

import javax.crypto.cipher;

public class desplus

{

static string strdefaultkey = "initkey";

static cipher encryptcipher = null;

static cipher decryptcipher = null;

static {

security.addprovider(new com.sun.crypto.provider.sunjce());

key key = null;

try {

key = getkey(strdefaultkey.getbytes());

encryptcipher = cipher.getinstance("des");

encryptcipher.init(cipher.encrypt_mode, key);

decryptcipher = cipher.getinstance("des");

decryptcipher.init(cipher.decrypt_mode, key);

}catch(exception e){

e.printstacktrace();

}

}

public desplus(){

}

public static byte[] encrypt(byte[] arrb) throws exception {

return encryptcipher.dofinal(arrb);

}

public static byte[] decrypt(byte[] arrb) throws exception {

return decryptcipher.dofinal(arrb);

}

private statickey getkey(byte[] arrbtmp) throws exception {

byte[] arrb = new byte[8];

for (int i = 0; iarrbtmp.length && iarrb.length; i++) {

arrb[i] = arrbtmp[i];

}

key key = new javax.crypto.spec.secretkeyspec(arrb, "des");

return key;

}

}

需要注意的是,加密后的结果是字节数组,一般情况下可以使用 base64 进行编码,以方便存储在字符串形的数据库字段中,当然亦可以采用原始的字节流或者是十六进制编码字符串;同样需要注意的是,在上面的代码示例中,java 的 des 算法可以指定加密的模式和填充方式,如果不指定,则默认的就是 ecb 加密模式和 pkcs#5 填充方式,关于加密模式和填充方式之后将进行介绍,现在我们来看 opensll 的 des 算法,还是先给一段代码示例:

c++ crypto example

int encrypt( unsigned char * inbuf , unsigned char * * outbuf , int inlen , unsigned char * key, unsigned char * iv )

{

bio *bio, *mbio, *cbio;

unsigned char *dst;

int outlen;

mbio = bio_new( bio_s_mem( ) );

cbio = bio_new( bio_f_cipher( ) );

bio_set_cipher( cbio , evp_des_ecb( ) , key , iv , 1 );

bio = bio_push( cbio , mbio );

bio_write( bio , inbuf , inlen );

bio_flush( bio );

outlen = bio_get_mem_data( mbio , (unsigned char **) & dst );

* outbuf = ( unsigned char * ) malloc( outlen );

memcpy( * outbuf , dst , outlen );

bio_free_all( bio );

return outlen;

}

该段代码使用了 openssl 库,该函数返回加密结果的长度,同时将加密的结果放置在 outbuf 中,需要注意的是,bio_set_chiper 这一行,最后两个参数:iv 参数在 ecb 加密模式下是不起作用的,仅 cbc 模式才会使用该变量,该变量要求必须是一个八字节的数组,enc 参数,如果是 1 则表明是进行加密,如果是 0 则表明是解密,-1 则表明使用最后一次操作的方式,只需要修改最后一个参数为0,就是解密了,所以解密的代码就不再重复了;

另外补充一点,这个加密方式是最古老的 des ,不是 3des ,输入参数 key 的长度要求至少是 8 个字节,如果不够,补 '\0',例如:unsigned char key[ ] = { "key\0\0\0\0\0" },如果超过八个字节,那么后面的不使用;如果你不愿意补零,那么需要保证和 java 的对应,否则不能互相加解密;

哦,还有一点,请注意在使用完后释放 outbuf 内存块,保证没有内存泄露;

下面来说一下加密模式,常见的加密模式有 ecb / cbc / cfb / ofb 四种,这也是 openssl 提供的四种,加密模式的主要意义就是,加密算法是按块进行加密的,例如 des ,是 64bit 一个块的进行加密,就是每次加密 8 个字节,因此每次输入八个字节的明文输出八个字节密文,如果是 16 个字节,那么分成两个块依次进行加密,问题就出现在这里,如果明文是 1234567812345678,分块分别进行加密,那么加密的结果类似“c4132737962c519c c4132737962c519c”,可以看出明文的规律,这就是 ecb 加密模式,密文可以看出明文的规律;为了解决这个问题,有了其他的加密模式:cbc 加密模式(密码分组连接),cfb加密模式(密码反馈模式),ofb加密模式(输出反馈模式)cbc 是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,cfb 和 ofb 则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果网络传输时发生了一部分错误,则后面的解密结果就可能是错误的;(ecb模式仅影响传输错误的那个块);

密码算法基本上都是分组(按快)进行加密的,如果密文长度不是刚刚好可以进行分组,怎么办?只能进行填充,填充的方法有很多中,常用的是 pkcs#7,该填充方法是将每一个补充的字节内容填充为填充的字节个数;例如明文长度是 100 , 分组的大小是32个字节,那么需要分为四组,补充28个字节,那么补充的字节全部补充为'\0x28',如果分组的大小是 8 个字节,那么 pkcs#7 的填充方式和 pkcs#5 是完全一致的;另外还有一个规定,就是如果明文刚刚好进行分组,那么需要补充一个独立的分组出来,例如 des ,如果明文为 8 个字节,那么需要补充为 16 个字节进行运算,这样的好处是进行解密后,将解密出来的最后一个字节取出来,并将解密结果的长度减去该值,就是原来明文的长度;

更多的信息可以参考:http://en.wikipedia.org/wiki/block_cipher_modes_of_operation


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值