java与C++ DES 算法

转:http://www.open-open.com/bbs/view/1320502797546

java与C++通过des、blowfish互相加解密

在简单的服务器端与客户端通信的应用中,这种做法比较常见

DES、blowfish扫盲:

1.des的常见模式分为四种 ECB / CBC / CFB / OFB     这里使用默认的ECB

ECB的缺陷:能从密文看出明文的规律

加密算法是按块进行加密的, DES ,是 64Bit 一个块的进行加密,就是每次加密 8 个字节,因此每次输入八个字节的明文输出八个字节密文,如果是 16 个字节,那么分成两个块依次进行加密,问题就出现在这里,如果明文是 1234567812345678,分块分别进行加密,那么加密的结果类似“C4132737962C519C C4132737962C519C”,可以看出明文的规律,这就是 ECB 加密模式,密文可以看出明文的规律

CBC/CFB/OFB:

为了解决这个问题,有了其他的加密模式:CBC 加密模式(密码分组连接),CFB加密模式(密码反馈模式),OFB加密模式(输出反馈模式)CBC 是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,CFB 和 OFB 则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果网络传输时发生了一部分错误,则后面的解密结果就可能是错误的;(ECB模式仅影响传输错误的那个块);

2.上面提到des是以64bit作为单位块单位来进行加密的,如果加密的内容长度刚好不是64bit块的倍数,则需要做填充(padding)

常用的填充算法是 PKCS#7,该填充方法是将每一个补充的字节内容填充为填充的字节个数;例如明文长度是 100 , 分组的大小是32个字节,那么需要分为四组,补充28个字节,那么补充的字节全部补充为'\0x28',如果分组的大小是 8 个字节,那么 PKCS#7 的填充方式和 PKCS#5 是完全一致的;另外还有一个规定,就是如果明文刚刚好进行分组,那么需要补充一个独立的分组出来,例如 DES ,如果明文为 8 个字节,那么需要补充为 16 个字节进行运算,这样的好处是进行解密后,将解密出来的最后一个字节取出来,并将解密结果的长度减去该值,就是原来明文的长度;

当然你也可以选择NoPadding模式,自己对加密内容的字节数做处理,确保它的长度是64bit的倍数

(以上规则blowfish也同样使用)

代码:

java

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 static  Key getKey(byte[] arrBTmp) throws Exception {
  byte[] arrB = new byte[8];
  for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
   arrB[i] = arrBTmp[i];
  }
  Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
  return key;
 }
 
}

 
c++
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;
}

 

转:http://www.blogjava.net/iamhuzl/articles/379494.html

DES(Data Encryption Standard)算法,于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。一般密码长度为8个字节,其中56位加密密钥,每个第8位都用作奇偶校验。

   DES的几种工作方式

第一种电子密本方式(ECB)
   将明文分成n个64比特分组,如果明文长度不是64比特的倍数,则在明文末尾填充适当数目的规定符号。对明文组用给定的密钥分别进行加密,行密文C=(C0,C1,……,Cn-1)其中Ci=DES(K,xi),i=0,1,…..,n-1。

  第二种密文分组链接方式(CBC)
   在CBC方式下,每个明文组xi在加密前与先一组密文按位模二加后,再送到DES加密,CBC方式克服了ECB方式报内组重的缺点,但由于明文组加密前与一组密文有关,因此前一组密文的错误会传播到下一组。

  第三种密文反馈方式(CFB),可用于序列密码
   明文X=(x0,x1,……,xn-1),其中xi由t个比特组成0   第四种输出反馈方式(OFB),可用于序列密码
   与CFB唯一不同的是OFB是直接取DES输出的t个比特,而不是取密文的t个比特,其余都与CFB相同。但它取的是DES的输出,所以它克服了CFB的密文错误传播的缺点

   DES的几种填补方式
   DES是对64位数据的加密算法,如数据位数不足64位的倍数,需要填充,补充到64位的倍数。

   NoPadding
   API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim

   PKCS5Padding
   加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
   解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文

   SSL3Padding
   SSL3.0协议定义的填补算法


   java默认的DES算法实现方式为DES/ECB/PKCS5Padding。若c++或其他语言与java进行加解密互通,若java采用默认实现,另一方工作方式和填补算法必须都是用ECB和PKCS5Padding。

你可能感兴趣的:(java与C++ DES 算法)