Java和C/C++进行DES/AES密文传输(借鉴)
Java和C/C++进行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/C++进行DES/AES密文传输(借鉴)的更多相关文章
- JAVA 加密算法初探DES&AES
开发项目中需要将重要数据缓存在本地以便在离线是读取,如果不对数据进行处理,很容易造成损失.所以,我们一般对此类数据进行加密处理.这里,主要介绍两种简单的加密算法:DES&AES. 先简单介绍一 ...
- Atitit.加密算法 des aes 各个语言不同的原理与解决方案java php c#
Atitit.加密算法 des aes 各个语言不同的原理与解决方案java php c# 1. 加密算法的参数::算法/模式/填充 1 2. 标准加密api使用流程1 2.1. Md5——16bi ...
- 密码学之DES/AES算法
本文示例代码详见:https://github.com/52fhy/crypt-demo DES DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算 ...
- Java对称与非对称加密解密,AES与RSA
加密技术可以分为对称与非对称两种. 对称加密,解密,即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等 而非对称技术,加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等 为什么 ...
- C#加密解密(DES,AES,Base64,md5,SHA256,RSA,RC4)
一:异或^简单加解密(数字类型) 1:原理: 异或用于比较两个二进制数的相应位,在执行按位"异或"运算时,如果两个二进制数的相应位都为1或者都为0,则返回0;如果两个二进制数的相应 ...
- 7.java 加解密技术系列之 AES
java 加解密技术系列之 AES 序 概念 原理 应用 代码实现 结束语 序 这篇文章继续介绍对称加密算法,至于今天的主角,不用说,也是个厉害的角色 — — AES.AES 的出现,就是为了来替代原 ...
- 常用对称加密算法(DES/AES)类(PHP)
看注释,啥也不说了,欢迎各种跨平台测试! /** * 常用对称加密算法类 * 支持密钥:64/128/256 bit(字节长度8/16/32) * 支持算法:DES/AES(根据密钥长度自动匹配使用: ...
- JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录
JAVA之旅(三十三)--TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录 我们继续网络编程 一.TCP 说完UDP,我们就来说下我们应该重点掌握的TCP了 TCP传输 Soc ...
- 谈谈《Dotnet core结合jquery的前后端加密解密密码密文传输的实现》一文中后端解密失败的原因
详情请看<Dotnet core结合jquery的前后端加密解密密码密文传输的实现>,正常来讲,这个博客里面的代码是没有问题的,但是我有时候却会直接报错,原因是后台解密失败:Interna ...
随机推荐
- 深入理解CSS网页布局-理论篇
在CSS网页开发布局中,需要对浮动和定位有深刻的理解才能在开发中游刃有余. 基于此,在博客园中做了本篇总结,这些总结来自实践经验和阅读一些书籍后的理解总结,主要内容为浮动,清除浮动,定位. (可点击屏 ...
- 一个通用的DataGridView导出Excel扩展方法(支持列数据格式化)
假如数据库表中某个字段存放的值“1”和“0”分别代表“是”和“否”,要在DataGridView中显示“是”和“否”,一般用两种方法,一种是在sql中直接判断获取,另一种是在DataGridView的 ...
- 任意阶幻方(魔方矩阵)C语言实现
魔方又称幻方.纵横图.九宫图,最早记录于我国古代的洛书.据说夏禹治水时,河南洛阳附近的大河里浮出了一只乌龟,背上有一个很奇怪的图形,古人认为是一种祥瑞,预示着洪水将被夏禹王彻底制服.后人称之为&quo ...
- 【PL/SQL系列】Oracle存储过程使用动态SQL
Oracle存储过程相信大家都比较了解,下面就为您介绍Oracle存储过程使用动态SQL的方法,希望对您能够有所帮助. CREATE OR REPLACE PROCEDURE P_STAT_SCORE ...
- phonegap开发经验谈之一命令行建立项目和准备工作
一安装与配置 安装命令行配置,这个可以参见网上的.3.0的最好用命令行配置. 大家在安装android sdk的时候,会发现里面自带了一个eclipse,并且继承了adt,直接用这个就好了.当然你已经 ...
- iOS - Xcode 插件
Xcode 插件 Xcode 插件安装目录: ~/library/Application Support/Developer/Shared/Xcode/Plug-ins Xcode 插件大全 http ...
- 16 SQL Tuning Overview
16.1 Introduction to SQL Tuning Identifying high load or top SQL statements that are responsible for ...
- Python学习(14)模块二
一:_name_ Python中if _name_ == '_main_'的解析 当你打开一个.py文件时,经常会在代码的最下面看到if __name__ == '__main__':,现在就来介 绍 ...
- 《高级Web应用程序设计》课程学习资料
任务1:什么是ASP.NET MVC 1.1 ASP.NET MVC简介 1.2 认识ASP.NET MVC项目结构 1.3 ASP.NET MVC生命周期 任务2:初识ASP.NET MVC项目开 ...
- 【原创】Mac os 10.10.3 安装xgboost
大家用的比较多的是Linux和windows,基于Mac os的安装教程不多, 所以在安装的过程中遇到很多问题,经过较长时间的尝试,可以正常安装和使用, [说在前面]由于新版本的Os操作系统不支持op ...