java 与c des_Java和C/C++进行DES/AES密文传输
本来觉得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密文传输相关推荐
- 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 ...
- java中的DES,AES,BASE64,MD5和Cipher类\MessageDigest类
Cipher类位于javax.crypto包下,声明为 public class Cipher extends Object 此类为加密和解密提供密码功能.它构成了 Java Cryptographi ...
- RC4算法原理、Java实现RC4加密算法、DES AES RC4算法比较
DES AES RC4算法比较 根据密钥类型的不同,加密算法分为对称和非对称两种.对称加密系统是指加密和解密均采用同一把密钥. 对称加密算法是最常用的加密算法,优势在于算法公开,计算量小,加密效率高. ...
- Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA
[最简单的加密] 1.简单的概念 明文:加密前的信息 密文:机密后的信息 算法:加密或解密的算法 密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao) 2.简单的例子 ...
- java aes密钥生成_如何在Java(Android)中生成与.Net中相同的AES密钥?
我需要从.Net WebService提供的salt和密码生成 Java( Android)中的AES密钥.我需要使用与.net生成的密钥相同的密钥和相同的密码和盐(使用Rfc2898DeriveBy ...
- 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 ...
- Linux下运行java DES AES加解密
2019独角兽企业重金招聘Python工程师标准>>> DES java源代码如下: import java.security.InvalidKeyException; import ...
- Java基础23 网络编程 socket套接字流 TCP传输总结
一.网络编程的概念 1.计算机网络:将不同地区的计算机,使用网络来进行连接 实现不同地区的数据的交互与共享(互联时代) 2. 网络编程的三要素:IP地址 端口号 协议 3. ip地址:是在网络连接中 ...
- aes加密算法python语言实现_C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现[转载]...
原文:http://outofmemory.cn/code-snippet/35524/AES-with-javascript-java-csharp-python-or-php c#里面的AES加密 ...
最新文章
- 蚂蚁金服AAAI论文:基于长短期老师的样本蒸馏方法和自动车险定损系统的最新突破...
- 【LeetCode】121.买卖股票的最佳时机
- Python执行 shell 命令并实时打印输出
- 让你一目了然的ip划分!
- Eclipse将引用了第三方jar包的Java项目打包成jar文件
- 微博:第二批共处置10106个账号 十万粉丝到一百万粉丝的账号8个
- 华为认证考试HCIA H12-811 Datacom数通考试真题题库【带答案刷题必过】【第二部分】
- 界面控件DotNetBar for WinForms使用教程:LayoutControl布局与通用代码设置(三)
- CVE-2018-18311 阿里云漏洞修复 RHSA-2019:0109-Important: perl secur
- 微软背叛wintel联盟,Intel似乎正陷入四面楚歌之中
- mysql hugepage_mysql启用hugepage-阿里云开发者社区
- 分布式锁的一些细节问题,值得收藏
- AD7606数据转换
- 数据库复习题选择题+判断题+填空题(考试续命必备
- 天文常用网站:数据库软件工具code
- 盘点经典免费录屏软件,短视频创作必备
- [渝粤教育] 中国地质大学 大学物理(上) 复习题 (2)
- 曾遭周鸿祎全网封杀的360猛将 :草根打工到36岁身家上亿的逆袭!
- C语言答疑合集(一)
- Moore Voting
热门文章
- Java SSM框架学习之Mybatis篇
- java 数字与金额_java 数字金额转换中文金额
- java同时启动多个 无法打印_java实现多线程交替打印两个数
- android.mk官网介绍,转载:Android.mk语法介绍
- stm32l0的停止模式怎么唤醒_关于Mac睡眠模式,你不知道的那些事
- 不同类型的官网应该如何设计?
- 2020年的UI设计师需要会什么软件
- cuSPARSE库:(一)函数的异步执行
- Execution Environment for Non-64-bit Modes 和 64-bit Modes
- Linux进程管理:进程调度之完全公平调度算法