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

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 原文地址:http://www.cnblogs.com/AloneSword/p/3479376.html在 JAVA 中,从 J2EE1.4 开始,SUN 提供了 JCE( JAVA CRYPTO ENGINE ),其中包含有 DES 算法,在 JAVA 中使用 DES 算法的代码示例如下:import java.

原文地址:http://www.cnblogs.com/AloneSword/p/3479376.html

在 JAVA 中,从 J2EE1.4 开始,SUN 提供了 JCE( JAVA CRYPTO ENGINE ),其中包含有 DES 算法,在 JAVA 中使用 DES 算法的代码示例如下:

复制代码
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;
 }
 
}
复制代码

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

复制代码
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


目录
相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
92 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
15天前
|
Java Android开发 C++
Java和C++
Java和C++
34 15
WK
|
1月前
|
安全 Java 编译器
C++和Java哪个更好用
C++和Java各具优势,选择取决于项目需求、开发者偏好及目标平台特性。C++性能出色,适合游戏、实时系统等;Java平台独立性强,适合跨平台、安全敏感应用。C++提供硬件访问和灵活编程范式,Java有自动内存管理和丰富库支持。两者各有千秋,需根据具体需求选择。
WK
30 1
|
2月前
|
IDE Java 程序员
C++ 程序员的 Java 指南
一个 C++ 程序员自己总结的 Java 学习中应该注意的点。
25 5
|
2月前
|
存储 算法 C++
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
656 0
高精度算法(加、减、乘、除,使用c++实现)
|
2月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
92 2
WK
|
1月前
|
开发框架 移动开发 Java
C++和Java哪个更适合开发移动应用
本文对比了C++和Java在移动应用开发中的优劣,从市场需求、学习难度、开发效率、跨平台性和应用领域等方面进行了详细分析。Java在Android开发中占据优势,而C++则适合对性能要求较高的场景。选择应根据具体需求和个人偏好综合考虑。
WK
55 0
WK
|
1月前
|
安全 Java 编译器
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
84 0
|
2月前
|
缓存 并行计算 Java
C++矢量运算与java矢量运算
本文探讨了C++和Java中的矢量运算与标量运算的性能比较,解释了矢量运算的原理和为什么它比标量运算快,包括并行性、数据局部性、指令优化和数据重用等优势。文章还提供了C++和Java的矢量运算示例代码,并展示了运行结果,以证明矢量运算在处理大量数据时的性能优势。
25 0
C++矢量运算与java矢量运算
|
2月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
43 0
下一篇
DataWorks