DES加密ECB模式的Java和C++实现
远程采集终端说明
⼀、⽅案详细说明
更新内容: 报⽂添加加密功能
使⽤终端: RTU
加密⽅式: DES加密
DES加密模式: ECB模式
填充⽅式: zeropadding
⼆、简单测试案例
1、⽰例1:
密⽂(hex): 8bb47a0cf0a9626d2b166ab8314d8fb5
密码: 12345678
对应明⽂: 0123456789
2、⽰例2:
密⽂(hex):
ff0d7d28f151afcb5c9c0bed5868c88b1530b0aec5f424d81f4c3e9dbc520c59e90fbfb9913e3c1b7e6cd019df36016de 09a41a1b9b4bf265f6a7d528e394f39d38377496afb736d9555bb58a1e67357188fbd94a9d5ca52bee263f693ac45c7 2f5cb2e7a220696ed2c134f03a8135b2d9b3d4e0deb60708474aa8116f476cc20c6da503b069dcd418a76ed28d157a de3d7595a98bff809d
密码: 12345678
明⽂:
EB910048648961079140002C01000001010704050225A5C1B1010000000000000063413AE13A42D8F5C343A4 0C2943B4D5A2406AE148413051C99E90FF97412C85F200000000CA7B
三、后台解析程序
约定密码: 12345678
解密程序: 前期已提供测试,备份在⽂件夹中。
1、对应的Java实现(ECB模式,zeropadding填充⽅式)代码DES.java如下:
package com.ybu.des;
import java.security.SecureRandom;
pto.spec.DESKeySpec;
pto.spec.SecretKeySpec;
pto.SecretKeyFactory;
pto.SecretKey;
pto.Cipher;
/**
* 注意:DES加密和解密过程中,密钥长度都必须是8的倍数
*/
public class DES {
public DES(){
}
// 测试
public static void main(String args[]){
// 待加密内容
String str ="0123456789";
java源代码加密// 密码,长度要是8的倍数
String password ="12345678";
byte[] result = Bytes(), password);
// System.out.println("加密后:----" + new String(result));
System.out.println("加密后:----"+byteToHex(result));
// 直接将如上内容解密
try{
byte[] decryResult = DES.decrypt(result, password);
System.out.println("解密后:----"+new String(decryResult));
}catch(Exception e1){
e1.printStackTrace();
}
}
/
**
* 加密
*
* @param datasource byte[]
* @param password String
* @return byte[]
*/
public static byte[]encrypt(byte[] datasource, String password){
try{
SecureRandom random =new SecureRandom();
DESKeySpec desKey =new Bytes());
/
/ 创建⼀个密匙⼯⼚,然后⽤它把DESKeySpec转换成
SecretKeyFactory keyFactory = Instance("DES"); SecretKey securekey = ateSecret(desKey);
// Cipher对象实际完成加密操作
Cipher cipher = Instance("DES/ECB/NoPadding");
// ⽤密匙初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
// 现在,获取数据并加密
// 正式执⾏加密操作
return cipher.doFinal(addZero(datasource));
}catch(Throwable e){
e.printStackTrace();
}
return null;
}
/**
* 解密
*
* @param src byte[]
* @param password String
* @return byte[]
* @throws Exception
*/
public static byte[]decrypt(byte[] src, String password)throws Exception { // DES算法要求有⼀个可信任的随机数源
SecureRandom random =new SecureRandom();
// 创建⼀个DESKeySpec对象
DESKeySpec desKey =new DESKeySpec((Bytes()));
// 创建⼀个密匙⼯⼚
SecretKeyFactory keyFactory = Instance("DES");
// 将DESKeySpec对象转换成SecretKey对象
SecretKey securekey = ateSecret(desKey);
// Cipher对象实际完成解密操作
Cipher cipher = Instance("DES/ECB/NoPadding");
// ⽤密匙初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, securekey, random);
// 真正开始解密操作
return cipher.doFinal(src);
}
public static byte[]getKey(byte[] keyRule){
SecretKeySpec key = null;
byte[] keyByte = keyRule;
System.out.println(keyByte.length);
// 创建⼀个空的⼋位数组,默认情况下为0
byte[] byteTemp =new byte[8];
// 将⽤户指定的规则转换成⼋位数组
int i =0;
for(; i < byteTemp.length && i < keyByte.length; i++){
byteTemp[i]= keyByte[i];
}
key =new SecretKeySpec(byteTemp,"DES");
Encoded();
}
public static byte[]addZero(byte[] data){
byte[] dataByte = data;
if(data.length %8!=0){
byte[] temp =new byte[8- data.length %8];
dataByte =byteMerger(data, temp);
}
return dataByte;
}
// java 合并两个byte数组
// System.arraycopy()⽅法
public static byte[]byteMerger(byte[] bt1,byte[] bt2){
byte[] bt3 =new byte[bt1.length + bt2.length];
System.arraycopy(bt1,0, bt3,0, bt1.length);
System.arraycopy(bt2,0, bt3, bt1.length, bt2.length);
return bt3;
}
/**
* byte数组转hex
* @param bytes
* @return
*/
public static String byteToHex(byte[] bytes){
String strHex ="";
StringBuilder sb =new StringBuilder("");
for(int n =0; n < bytes.length; n++){
strHex = HexString(bytes[n]&0xFF);
sb.append((strHex.length()==1)?"0"+ strHex : strHex);// 每个字节由两个字符表⽰,位数不够,⾼位补0 }
String().trim();
}
}
2、使⽤openssl库实现DES加密和解密(ECB模式,zeropadding填充⽅式)
1、windows
编译openssl库,得到头⽂件include和链接库lib和dll
配置包含头⽂件⽬录和库⽬录
⼯程中设置链接指定的lib:libssl.lib,libcrypto.lib
将对应的dll拷贝到exe执⾏⽬录:libcrypto-1_1.dll, libssl-1_1.dll
2、linux
编译openssl库,得到头⽂件include和链接库a和so
配置包含头⽂件⽬录和库⽬录
⼯程中设置链接指定的lib:libcrypto.a 后者libcrypto.so
DES.h头⽂件
加密和解密实现如下
#ifndef _DES_ECB_H
#define _DES_ECB_H
typdedef std::string String;
#include "openssl/des.h"
// DES加密 ECB模式
static String encrypt_des_ecb(const String& mingwen,const String& keystr)
{
String strCipherText;
DES_cblock keyEncrypt;
memset(keyEncrypt,0,8);
memcpy(keyEncrypt, keystr.c_str(), keystr.size()>=8?8: keystr.size());
DES_key_schedule keySchedule;//密钥表
DES_set_key_unchecked(&keyEncrypt,&keySchedule);//设置密钥,且不检测密钥奇偶性// 循环加密,每8字节⼀次
const_DES_cblock inputText;
DES_cblock outputText;
Uint8Array vecCiphertext;
uint8 tmp[8];
Uint8Array vecFull((mingwen.size()+7)/8*8,0);
memcpy(vecFull.data(), mingwen.data(), mingwen.size());
for(int i =0; i < vecFull.size()/8; i++)
{
memcpy(inputText, vecFull.data()+ i *8,8);
DES_ecb_encrypt(&inputText,&outputText,&keySchedule, DES_ENCRYPT);//加密memcpy(tmp, outputText,8);
std::copy(tmp, tmp +8, std::back_inserter(vecCiphertext));
}
strCipherText.clear();
strCipherText.assign(vecCiphertext.begin(), d());
return strCipherText;
}
// DES解密 ECB模式
static String decrypt_des_ecb(const String& miwen,const String& keystr)
{
String clearText;
DES_cblock keyEncrypt;
memset(keyEncrypt,0,8);
memcpy(keyEncrypt, keystr.c_str(), keystr.size()>=8?8: keystr.size());
DES_key_schedule keySchedule;//密钥表
DES_set_key_unchecked(&keyEncrypt,&keySchedule);//设置密钥,且不检测密钥奇偶性// 循环解密,每8字节⼀次
const_DES_cblock inputText;
DES_cblock outputText;
Uint8Array vecCleartext;
uint8 tmp[8];
Uint8Array vecFull((miwen.size()+7)/8*8,0);
memcpy(vecFull.data(), miwen.data(), miwen.size());
for(int i =0; i < vecFull.size()/8; i++)
{
memcpy(inputText, vecFull.data()+ i *8,8);
DES_ecb_encrypt(&inputText,&outputText,&keySchedule, DES_DECRYPT);//解密memcpy(tmp, outputText,8);
std::copy(tmp, tmp +8, std::back_inserter(vecCleartext));
}
clearText.assign(vecCleartext.begin(), d());
return clearText;
}
#endif
测试代码main.cpp如下:
#include <iostream>
#include "DES.h"
// 转换hex到字符串显⽰
String hex2str(const char* buff,const size_t buffsize,const char* sep ="",bool is_case =false){ String out;
char ch[4];
const char* fmt = is_case ?"%02x":"%02X";
for(size_t i =0; i < buffsize; i++){
sprintf(ch, fmt, buff[i]&0xFF);
pty()){
out = ch;
}
else{
out += sep;
out += ch;
}
}
return out;
}
int main(int argc,char* argv[])
{
// 原始明⽂
// 待加密内容
String mingwenText ="0123456789";
std::cout <<"原始字符串为:"<< mingwenText << std::endl;
// des
std::cout <<"=== des ecb加解密 ==="<< std::endl;
// 密码,长度要是8的倍数
std::string desKey ="12345678";
String miwen = DES::encrypt_des_ecb(mingwenText, desKey);
String miwenStr =hex2str(miwen.data(), miwen.size());
std::cout <<"加密后的字符串: "<< miwenStr << std::endl;
String mingwen = DES::decrypt_des_ecb(miwen, desKey);
int lastPos = mingwen.find_first_of('\0');
mingwen = mingwen.substr(0, lastPos);
std::cout <<"解密后的字符串: "<< mingwen << std::endl;
system("pause");
return0;
}
参考资料
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论