本来觉得DES、AES这种流行加密算法,使用起来应该很简单。但研究后发现有两个变数:

1)分块的方式。加密是逐块进行的。分块方法有:CBC、ECB、CFB……

2)padding的方式。当数据的位数不及块的大小时,需要填充。填充方式有:NoPadding、PKCS5Padding……

如果加解密端采用不同的分块方式或padding方式,即使都是采用DES/AES算法,同样无法解密成功。上次需要C端和Java端进行密文传输,就跪在这一点上(那时候没时间研究)。

参考文章:Java AES算法和openssl配对 ,主要通过其了解openssl里比较高级的EVP系列API(其默认padding和java一样都是PKCS5Padding),节约了搜索时间。

贴代码了,以下代码测试通过了。Java和C++均可以正确解密对方的密文。

约定:分块和padding采用Java默认的 ECB + PKCS5Padding。

加密程序,输入是"src.txt"文件(加密无需纯文本,只是为了可读性),输出保存在"enc.bin"文件。

解码程序,输入是"enc.bin"文件,输出保存在"dec.txt"文件。

------------------------------------------

DES:

Java加密代码:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;

import javax.crypto.spec.SecretKeySpec;

public class DesEnc {

public static byte[] desEncrypt(byte[] source, byte rawKeyData[])

throws GeneralSecurityException {

// 处理密钥

SecretKeySpec key = new SecretKeySpec(rawKeyData, "DES");

// 加密

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key);

return cipher.doFinal(source);

}

public static void main(String[] args) throws Exception {

// DES算法要求密鈅64位(8字节)

byte rawKeyData[] = "hellodes".getBytes("UTF-8");

// 读取文件内容(为了简单忽略错误处理)

File file = new File("src.txt");

byte[] source = new byte[(int) file.length()];

FileInputStream is = new FileInputStream(file);

is.read(source, 0, (int) file.length());

is.close();

// 加密

byte[] enc = desEncrypt(source, rawKeyData);

System.out.println("desEncrypt:" + source.length + "->" + enc.length);

// 输出到文件

FileOutputStream os = new FileOutputStream(new File("enc.bin"));

os.write(enc, 0, enc.length);

os.close();

}

}

Java解密代码:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;

import javax.crypto.spec.SecretKeySpec;

public class DesDec {

public static byte[] desDecrypt(byte[] data, byte rawKeyData[])

throws GeneralSecurityException {

// 处理密钥

SecretKeySpec key = new SecretKeySpec(rawKeyData, "DES");

// 解密

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key);

return cipher.doFinal(data);

}

public static void main(String[] args) throws Exception {

// DES算法要求密鈅64位(8字节)

byte rawKeyData[] = "hellodes".getBytes("UTF-8");

// 读取文件内容(为了简单忽略错误处理)

File file = new File("enc.bin");

byte[] data = new byte[(int) file.length()];

FileInputStream is = new FileInputStream(file);

is.read(data, 0, (int) file.length());

is.close();

// 加密

byte[] dec = desDecrypt(data, rawKeyData);

System.out.println("desDecrypt:" + data.length + "->" + dec.length);

// 输出到文件

FileOutputStream os = new FileOutputStream(new File("dec.txt"));

os.write(dec, 0, dec.length);

os.close();

}

}

C++加密代码:

#include 见后文

// 注意:参数和返回值全部是二进制数据

std::string desEncrypt(const std::string& source, const std::string& key)

{

EVP_CIPHER_CTX ctx;

EVP_CIPHER_CTX_init(&ctx);

int ret = EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);

assert(ret == 1);

unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间

int len1 = 0;

ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());

assert(ret == 1);

int len2 = 0;

ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);

assert(ret == 1);

std::cout << len1 << "," << len2 << std::endl;

ret = EVP_CIPHER_CTX_cleanup(&ctx);

assert(ret == 1);

std::string res((char*)result, len1+len2);

delete[] result;

return res;

}

int main()

{

std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串

// 读取文件内容(简单起见认为文件内容<100K)

char buf[1024*100];

FILE* fp = fopen("src.txt", "rb");

int bytes = fread(buf, 1, 1024*100, fp);

fclose(fp);

std::string source(buf, bytes); // 二进制数据

// 加密

std::string enc = desEncrypt(source, key);

std::cout << "desEncrypt:" << source.length() << "->" << enc.length() << std::endl;

// 输出到文件

fp =  fopen("enc.bin", "wb");

fwrite(enc.data(), 1, enc.length(), fp);

fclose(fp);

}

C++解密代码:

#include 见后文

// 注意:参数和返回值全部是二进制数据

std::string desDecrypt(const std::string& ciphertext, const std::string& key)

{

EVP_CIPHER_CTX ctx;

EVP_CIPHER_CTX_init(&ctx);

int ret = EVP_DecryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);

assert(ret == 1);

unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间

int len1 = 0;

ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());

assert(ret == 1);

int len2 = 0;

ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);

assert(ret == 1);

std::cout << len1 << "," << len2 << std::endl;

ret = EVP_CIPHER_CTX_cleanup(&ctx);

assert(ret == 1);

std::string res((char*)result, len1+len2);

delete[] result;

return res;

}

int main()

{

std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串

// 读取文件内容(简单起见认为文件内容<100K)

char buf[1024*100];

FILE* fp = fopen("enc.bin", "rb");

int bytes = fread(buf, 1, 1024*100, fp);

fclose(fp);

std::string data(buf, bytes); // 二进制数据

// 加密

std::string dec = desDecrypt(data, key);

std::cout << "desDecrypt:" << data.length() << "->" << dec.length() << std::endl;

// 输出到文件

fp =  fopen("dec.txt", "wb");

fwrite(dec.data(), 1, dec.length(), fp);

fclose(fp);

}

------------------------------------------

AES:

Java加密代码:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;

import javax.crypto.spec.SecretKeySpec;

public class AesEnc {

public static byte[] aesEncrypt(byte[] source, byte rawKeyData[])

throws GeneralSecurityException {

// 处理密钥

SecretKeySpec key = new SecretKeySpec(rawKeyData, "AES");

// 加密

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key);

return cipher.doFinal(source);

}

public static void main(String[] args) throws Exception {

// AES算法要求密鈅128位(16字节)

byte rawKeyData[] = "helloaeshelloaes".getBytes("UTF-8");

// 读取文件内容(为了简单忽略错误处理)

File file = new File("src.txt");

byte[] source = new byte[(int) file.length()];

FileInputStream is = new FileInputStream(file);

is.read(source, 0, (int) file.length());

is.close();

// 加密

byte[] enc = aesEncrypt(source, rawKeyData);

System.out.println("aesEncrypt:" + source.length + "->" + enc.length);

// 输出到文件

FileOutputStream os = new FileOutputStream(new File("enc.bin"));

os.write(enc, 0, enc.length);

os.close();

}

}

Java解密代码:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;

import javax.crypto.spec.SecretKeySpec;

public class AesDec {

public static byte[] aesDecrypt(byte[] data, byte rawKeyData[])

throws GeneralSecurityException {

// 处理密钥

SecretKeySpec key = new SecretKeySpec(rawKeyData, "AES");

// 解密

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key);

return cipher.doFinal(data);

}

public static void main(String[] args) throws Exception {

// AES算法要求密鈅128位(16字节)

byte rawKeyData[] = "helloaeshelloaes".getBytes("UTF-8");

// 读取文件内容(为了简单忽略错误处理)

File file = new File("enc.bin");

byte[] data = new byte[(int) file.length()];

FileInputStream is = new FileInputStream(file);

is.read(data, 0, (int) file.length());

is.close();

// 加密

byte[] dec = aesDecrypt(data, rawKeyData);

System.out.println("desDecrypt:" + data.length + "->" + dec.length);

// 输出到文件

FileOutputStream os = new FileOutputStream(new File("dec.txt"));

os.write(dec, 0, dec.length);

os.close();

}

}

C++加密代码:

#include 见后文

// 注意:参数和返回值全部是二进制数据

std::string aesEncrypt(const std::string& source, const std::string& key)

{

EVP_CIPHER_CTX ctx;

EVP_CIPHER_CTX_init(&ctx);

int ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);

assert(ret == 1);

unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间

int len1 = 0;

ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());

assert(ret == 1);

int len2 = 0;

ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);

assert(ret == 1);

std::cout << len1 << "," << len2 << std::endl;

ret = EVP_CIPHER_CTX_cleanup(&ctx);

assert(ret == 1);

std::string res((char*)result, len1+len2);

delete[] result;

return res;

}

int main()

{

std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串

// 读取文件内容(简单起见认为文件内容<100K)

char buf[1024*100];

FILE* fp = fopen("src.txt", "rb");

int bytes = fread(buf, 1, 1024*100, fp);

fclose(fp);

std::string source(buf, bytes); // 二进制数据

// 加密

std::string enc = aesEncrypt(source, key);

std::cout << "aesEncrypt:" << source.length() << "->" << enc.length() << std::endl;

// 输出到文件

fp =  fopen("enc.bin", "wb");

fwrite(enc.data(), 1, enc.length(), fp);

fclose(fp);

}

C++解密代码:

#include 见后文

// 注意:参数和返回值全部是二进制数据

std::string aesDecrypt(const std::string& ciphertext, const std::string& key)

{

EVP_CIPHER_CTX ctx;

EVP_CIPHER_CTX_init(&ctx);

int ret = EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);

assert(ret == 1);

unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间

int len1 = 0;

ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());

assert(ret == 1);

int len2 = 0;

ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);

assert(ret == 1);

std::cout << len1 << "," << len2 << std::endl;

ret = EVP_CIPHER_CTX_cleanup(&ctx);

assert(ret == 1);

std::string res((char*)result, len1+len2);

delete[] result;

return res;

}

int main()

{

std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串

// 读取文件内容(简单起见认为文件内容<100K)

char buf[1024*100];

FILE* fp = fopen("enc.bin", "rb");

int bytes = fread(buf, 1, 1024*100, fp);

fclose(fp);

std::string data(buf, bytes); // 二进制数据

// 加密

std::string dec = aesDecrypt(data, key);

std::cout << "aesDecrypt:" << data.length() << "->" << dec.length() << std::endl;

// 输出到文件

fp =  fopen("dec.txt", "wb");

fwrite(dec.data(), 1, dec.length(), fp);

fclose(fp);

}

===============================发表后的分割线===============================

1、发表后发现C++代码中include类库都由于小括号的缘故,被卡擦掉了。这边补充一下,需要包含以下头文件:

[string]

[iostream]

[stdio.h]

[assert.h]

[openssl/objects.h]

[openssl/evp.h]

2、DES、AES加密算法都是针对数据块,Java加解密函数参数使用byte数组。C++用std::string,那是因为这是C++中使用byte数组的最简单方式(std::string可以存储二进制数据,很多人没想到吧),缺点是拷贝内存的次数可能会略多些。如果想要优化拷贝效率,可以使用自己封装的Buffer类来代替std::string

java 与c des_Java和C/C++进行DES/AES密文传输相关推荐

  1. java security / SSL / TLS / md5 / sha / base64 / rsa / des / aes / 3des

    java jdk keytool C:\Program Files\Java\jdk1.7.0_11\bin\keytool.exe [lindows@Loadrunner19 ~]$ ll /opt ...

  2. java中的DES,AES,BASE64,MD5和Cipher类\MessageDigest类

    Cipher类位于javax.crypto包下,声明为 public class Cipher extends Object 此类为加密和解密提供密码功能.它构成了 Java Cryptographi ...

  3. RC4算法原理、Java实现RC4加密算法、DES AES RC4算法比较

    DES AES RC4算法比较 根据密钥类型的不同,加密算法分为对称和非对称两种.对称加密系统是指加密和解密均采用同一把密钥. 对称加密算法是最常用的加密算法,优势在于算法公开,计算量小,加密效率高. ...

  4. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    [最简单的加密] 1.简单的概念 明文:加密前的信息 密文:机密后的信息 算法:加密或解密的算法 密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao) 2.简单的例子 ...

  5. java aes密钥生成_如何在Java(Android)中生成与.Net中相同的AES密钥?

    我需要从.Net WebService提供的salt和密码生成 Java( Android)中的AES密钥.我需要使用与.net生成的密钥相同的密钥和相同的密码和盐(使用Rfc2898DeriveBy ...

  6. JAVA加密解密→术语、密码分类、OSI与TCP/IP安全体系、Base64、消息摘要算法MD/SHA/MAC、对称加密算法DES/AES/PBE、非对称加密算法DH/RSA/EIGamaI

    术语 密码分类 OSI与TCP/IP安全体系 JAVA安全 Base64算法 消息摘要算法MD 消息摘要算法MD图解 消息摘要算法SHA 消息摘要算法SHA图解 消息摘要算法MAC 消息摘要算法MAC ...

  7. Linux下运行java DES AES加解密

    2019独角兽企业重金招聘Python工程师标准>>> DES java源代码如下: import java.security.InvalidKeyException; import ...

  8. Java基础23 网络编程 socket套接字流 TCP传输总结

    一.网络编程的概念 1.计算机网络:将不同地区的计算机,使用网络来进行连接 实现不同地区的数据的交互与共享(互联时代) 2. 网络编程的三要素:IP地址 端口号 协议 3. ip地址:是在网络连接中 ...

  9. aes加密算法python语言实现_C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现[转载]...

    原文:http://outofmemory.cn/code-snippet/35524/AES-with-javascript-java-csharp-python-or-php c#里面的AES加密 ...

最新文章

  1. 蚂蚁金服AAAI论文:基于长短期老师的样本蒸馏方法和自动车险定损系统的最新突破...
  2. 【LeetCode】121.买卖股票的最佳时机
  3. Python执行 shell 命令并实时打印输出
  4. 让你一目了然的ip划分!
  5. Eclipse将引用了第三方jar包的Java项目打包成jar文件
  6. 微博:第二批共处置10106个账号 十万粉丝到一百万粉丝的账号8个
  7. 华为认证考试HCIA H12-811 Datacom数通考试真题题库【带答案刷题必过】【第二部分】
  8. 界面控件DotNetBar for WinForms使用教程:LayoutControl布局与通用代码设置(三)
  9. CVE-2018-18311 阿里云漏洞修复 RHSA-2019:0109-Important: perl secur
  10. 微软背叛wintel联盟,Intel似乎正陷入四面楚歌之中
  11. mysql hugepage_mysql启用hugepage-阿里云开发者社区
  12. 分布式锁的一些细节问题,值得收藏
  13. AD7606数据转换
  14. 数据库复习题选择题+判断题+填空题(考试续命必备
  15. 天文常用网站:数据库软件工具code
  16. 盘点经典免费录屏软件,短视频创作必备
  17. [渝粤教育] 中国地质大学 大学物理(上) 复习题 (2)
  18. 曾遭周鸿祎全网封杀的360猛将 :草根打工到36岁身家上亿的逆袭!
  19. C语言答疑合集(一)
  20. Moore Voting

热门文章

  1. Java SSM框架学习之Mybatis篇
  2. java 数字与金额_java 数字金额转换中文金额
  3. java同时启动多个 无法打印_java实现多线程交替打印两个数
  4. android.mk官网介绍,转载:Android.mk语法介绍
  5. stm32l0的停止模式怎么唤醒_关于Mac睡眠模式,你不知道的那些事
  6. 不同类型的官网应该如何设计?
  7. 2020年的UI设计师需要会什么软件
  8. cuSPARSE库:(一)函数的异步执行
  9. Execution Environment for Non-64-bit Modes 和 64-bit Modes
  10. Linux进程管理:进程调度之完全公平调度算法