您的位置:首页 > 编程语言 > Java开发

C#解密(DES)Java的加密结果

2018-03-05 10:43 344 查看
工作需要,要工C#实现Java的加密解密功能。
资料有
1.Java代码package com.sitech.crmpd.security;
/**
* 两级界面集成 加解密
* meixy 2013-03-14
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class IntegrationDESPlus {

private static final String ALGORITHM = "DES";
private static SecretKey secretKey = null;
//初始化 密钥存放的相对路径(视具体情况修改)
private static String KeyFilePath = "secretekey351.dat";

//加载密钥文件
public IntegrationDESPlus(){
loadSecretKey(true,KeyFilePath);
}
//加载密钥文件
public IntegrationDESPlus(String kf){
setKeyFile(kf);
loadSecretKey(true,KeyFilePath);
}

public String getKeyFile() {
return KeyFilePath;
}

public void setKeyFile(String kf) {
if("".equals(kf) || kf == null)
return;
KeyFilePath = kf;

}

//加解密 测试
public static void main(String args[]){

IntegrationDESPlus sd = new IntegrationDESPlus();
//加密
String enc_result=sd.encrypt("111111");
System.out.println("351 encrypt result="+enc_result);
//解密
String dec_result=sd.decrypt(enc_result);
System.out.println("351 decrypt result="+dec_result);

}

/**
* 加密
* @return original plain text
*/
public String encrypt(String source) {
String result = null;
//loadSecretKey(local,SERVERKEY);
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherByte = cipher.doFinal(source.getBytes());

result = byte2hex(cipherByte);
} catch (Exception e) {
e.printStackTrace();
}

return result;
}

/**
* 解密
* @return original plain text
*/
public String decrypt(String source) {
String result = null;
//loadSecretKey(local,SERVERKEY);

try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);

byte[] clearByte = cipher.doFinal(hex2byte(source));
result = new String(clearByte);
} catch (Exception e) {
e.printStackTrace();
}

return result;
}

/**
* 加载密钥文件
*/

private void loadSecretKey(boolean local,String SERVERKEY) {

/**
* if this program is not execute in container,
* i.e. local is true, we should confirm weather
* secretekey file exist or not, it doesn't
* exist, we should generate it.
*/
//if (local) {
//generateKey("secretekey.dat");
//}

try {
SERVERKEY = this.getClass().getResource("").getPath()+SERVERKEY;
System.out.println("SERVERKEY="+SERVERKEY);
InputStream inStream = new FileInputStream(SERVERKEY);
ObjectInputStream is = new ObjectInputStream(inStream);
secretKey = (SecretKey)is.readObject();
is.close();
} catch (NullPointerException e) {
StringBuffer msg = new StringBuffer();
msg.append("Secret Key file can not be found, so: \r\n");
msg.append("1: find and install the corresponding");
msg.append(" keyFile.\r\n");
msg.append("2: generate a new key file, encrypt the ");
msg.append("password and set the configuration file ");
msg.append("again. \r\n");
System.out.println(msg.toString());
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* convert bytes to hex,
* the result is ideal to store and transfer.
* @param bytes byte array
* @return hex string
*/
private String byte2hex(byte[] bytes) {
String result = "";
String temp = "";
for (int i = 0; i < bytes.length; i++) {
temp = (Integer.toHexString(bytes[i] & 0XFF));
if (temp.length() == 1) {
result += "0" + temp;
} else {
result += temp;
}
}

return result.toUpperCase();
}

/**
* convert hex to byte array,
* result byte array ready for calculation
* @param bytes byte array
* @return hex string
*/
private byte[] hex2byte(String hex) {
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}

/**
* in DES arithmetic, we must store secret key
* we store the key in a dat file for following usage,
* in addition, we should use certain secret key!
*/
public void generateKey(String fileName) {
try {
File keyFile = new File(fileName);
if (!keyFile.exists()) {
KeyGenerator keygen = KeyGenerator.getInstance(ALGORITHM);
SecretKey secretKey = keygen.generateKey();
ObjectOutputStream os = new ObjectOutputStream(
new BufferedOutputStream(
new java.io.FileOutputStream(keyFile)));
os.writeObject(secretKey);
os.flush(); os.close();
} else {
System.out.println("Secret Key file has exist.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}2. 一个编码样例String type="01";
String user="admin";
String sn="123456";
String orisn="123456789dgdfgdg";
String cust_id="123143324324324";

admin <=> 4500A125845A2CF0
http://10.210.42.8/idcBusiness.do? type=7E54F48557F4C326&user=4500A125845A2CF0&sn=A988E19289AAE29D&orisn=AD97DA31EB80205CDE6250D2CE4C50A9120ABD5247750190&;cust_id=92087F4E9D696F1FBBE2B543B858A462
01 admin 123456 123456789dgdfgdg 123143324324324
type=7E54F48557F4C326
user=4500A125845A2CF0
sn=A988E19289AAE29D
orisn=AD97DA31EB80205CDE6250D2CE4C50A9120ABD5247750190
cust_id=92087F4E9D696F1FBBE2B543B858A462

3. 一个secretekey351.dat文件
目标:在ASP.Net后台实现解密工作。

方案有两个,一个是理解Java并用c#实现,或者寻找别人写好的实现代码;一个是用C#加载Java,这个有可能,估计会需要安装Java的运行环境。

先理解一下前面的Java代码:
    1.从文件中加载SecretKey,这个文件说白了是SecretKey的序列化。
InputStream inStream = new FileInputStream(SERVERKEY);
ObjectInputStream is = new ObjectInputStream(inStream);
secretKey = (SecretKey)is.readObject();    2.用key解密字符串 /**
* 解密
* @return original plain text
*/
public String decrypt(String source) {
String result = null;
//loadSecretKey(local,SERVERKEY);

try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);

byte[] clearByte = cipher.doFinal(hex2byte(source));
result = new String(clearByte);
} catch (Exception e) {
e.printStackTrace();
}

return result;
}关键的类是SecretKey和Cipher,如果要加密还需要KeyGenerator类,都在javax.crypto里面。
ALGORITHM = "DES"说明是EDS算法。

搜索“C#调用javax.crypto”找到和我有相同需求的帖子:
资料1:http://bbs.csdn.net/topics/390569120?page=1 (大家好,我这里有个java加密方法,我想写成C#的,本人能力有限,希望大神们帮帮吗)

资料2:http://www.cnblogs.com/-lzb/articles/4942031.html (Java aes加密C#解密的取巧方法)

参考资料:
资料3:https://www.cnblogs.com/liluping860122/p/4026015.html()

核心知识:
Java与C#的Byte类型值范围不同,Java的Byte范围为-128至127,c#的Byte范围是0-255。

如果能转换的话,关键还是要从文件中获取转换用的参数,从文件读取SecretKey并获取参数。这个需要c#能实现ReadObject类似的功能

搭建Java环境(Java7+Eclipse),创建项目运行,查看SecretKey



-113 13 38 -26 88 -48 -74 -98
查看secretekey351.dat文件,通过比较另外生成的多个生成的.dat文件,发现只有一部分是有差异的



8F0D26E658D0B69E
HexConvert(): private static byte[] HexConvert(string hex)
{
hex = hex.ToUpper();
int len = (hex.Length / 2);
byte[] result = new byte[len];
char[] achar = hex.ToCharArray();
for (int i = 0; i < len; i++)
{
int pos = i * 2;
string by = new string(new char[] { achar[pos], achar[pos + 1] });
result[i] = Convert.ToByte(by, 16);
}
return result;
}
转换成byte:143 13 38 230 88 208 182 158 (C#)
跟前面的比较:-113 13 38 -26 88 -48 -74 -98 (Java)
加上知识:Java的Byte范围为-128至127,c#的Byte范围是0-255
写一个函数模拟转换成Jave的byte private static int[] HexConvertJava(string hex)
{
hex = hex.ToUpper();
int len = (hex.Length / 2);
int[] result = new int[len];
char[] achar = hex.ToCharArray();
for (int i = 0; i < len; i++)
{
int pos = i * 2;
string by = new string(new char[] { achar[pos], achar[pos + 1] });
result[i] = Convert.ToByte(by, 16);
if (result[i] > 127)
{
result[i] -= 256;
}
}
return result;
}确实转换为:-113 13 38 -26 88 -48 -74 -98。
第一步,解析secretekey351.dat得到8F0D26E658D0B69E,手动完成。
第二步,尝试解密。
明文:admin,密文:4500A125845A2CF0,秘钥 :8F0D26E658D0B69E

一般的C#DES加密解密过程
参考资料:http://blog.csdn.net/kebi007/article/details/70158945
加密解密核心方法:
/// <summary>
/// C# DES加密方法
/// </summary>
/// <param name="by">要加密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>加密后的字符串</returns>
public static byte[] DESEncrypt(byte[] by, byte[] key, byte[] iv)
{
using (DESCryptoServiceProvider sa
= new DESCryptoServiceProvider { Key = key, IV = iv })
{
using (ICryptoTransform ct = sa.CreateEncryptor())
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
cs.Write(by, 0, by.Length);
cs.FlushFinalBlock();
}
return ms.ToArray();
}
}
}
}

/// <summary>
/// C# DES解密方法
/// </summary>
/// <param name="byt">待解密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>解密后的字符串</returns>
public static byte[] DESDecrypt(byte[] byt, byte[] key, byte[] iv)
{
using (DESCryptoServiceProvider sa =
new DESCryptoServiceProvider
{ Key = key, IV = iv })
{
using (ICryptoTransform ct = sa.CreateDecryptor())
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
cs.Write(byt, 0, byt.Length);
cs.FlushFinalBlock();
}
return ms.ToArray();
}
}
}
}参数和结果都是byte,但是实际上byte是从string得到,并转换成string结果的,如: /// <summary>
/// C# DES加密方法
/// </summary>
/// <param name="encryptedValue">要加密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>加密后的字符串</returns>
public static string DESEncryptByUTF8Base64(string originalValue, string key, string iv)
{
return Convert.ToBase64String(DESEncrypt(Encoding.UTF8.GetBytes(originalValue),Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv)));
}

/// <summary>
/// C# DES解密方法
/// </summary>
/// <param name="encryptedValueBase64">待解密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>解密后的字符串</returns>
public static string DESDecryptByUTF8Base64(string encryptedValueBase64, string key, string iv)
{
return Encoding.UTF8.GetString(DESDecrypt(Convert.FromBase64String(encryptedValueBase64), Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv)));
}

/// <summary>
/// C# DES加密方法
/// </summary>
/// <param name="encryptedValue">要加密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>加密后的字符串</returns>
public static string DESEncryptByGBKHex(string originalValue, string key, string iv)
{
return BytesToHex(DESEncrypt(Encoding.GetEncoding("GBK").GetBytes(originalValue), Encoding.GetEncoding("GBK").GetBytes(key), Encoding.GetEncoding("GBK").GetBytes(iv)));
}

/// <summary>
/// C# DES解密方法
/// </summary>
/// <param name="encryptedValueHex">待解密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>解密后的字符串</returns>
public static string DESDecryptByByGBKHex(string encryptedValueHex, string key, string iv)
{
return Encoding.GetEncoding("GBK").GetString(DESDecrypt(HexToBytes(encryptedValueHex), Encoding.GetEncoding("GBK").GetBytes(key), Encoding.GetEncoding("GBK").GetBytes(iv)));
}这里的转换有各种方式,明文的转换可以是UTF8,可以是GBK;密文的转换可以是Base64,可以是Hex。
其中转换函数 private static byte[] HexToBytes(string hex)
{
hex = hex.ToUpper();
int len = (hex.Length / 2);
byte[] result = new byte[len];
char[] achar = hex.ToCharArray();
for (int i = 0; i < len; i++)
{
int pos = i * 2;
string by = new string(new char[] { achar[pos], achar[pos + 1] });
result[i] = Convert.ToByte(by, 16);
}
return result;
}

private static string BytesToHex(byte[] bytes)
{
StringBuilder ret = new StringBuilder();
foreach (byte b in bytes)
{
ret.AppendFormat("{0:X2}", b); //{0:X2} 大写
}
var hex = ret.ToString();
return hex;
}使用时要用相同的转换方式: string content = "admin";
Console.WriteLine("原文:" + content);

string keyText = "12345678";
string ivText = "87654321";

string resultEncrypt = DESEncryptByUTF8Base64(content, keyText, ivText);
string resultDecrypt = DESDecryptByUTF8Base64(resultEncrypt, keyText, ivText);
Console.WriteLine("加密结果1:" + resultEncrypt);
Console.WriteLine("解密结果1:" + resultDecrypt);

string resultEncrypt2 = DESEncryptByGBKHex(content, keyText, ivText);
string resultDecrypt2 = DESDecryptByByGBKHex(resultEncrypt2, keyText, ivText);
Console.WriteLine("加密结果2:" + resultEncrypt2);
Console.WriteLine("解密结果2:" + resultDecrypt2);尝试用现有资料界面,参考前面资料1用GBK编码。 string keyHex = "8F0D26E658D0B69E";
byte[] keyBytes = HexToBytes(keyHex);

byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };

string user = "admin";
byte[] userBytes= Encoding.GetEncoding("GBK").GetBytes(user);

byte[] encryptResultBytes = DESEncrypt(userBytes, keyBytes, ivBytes);
string encryptResult = BytesToHex(encryptResultBytes);

byte[] decryptResultBytes = DESDecrypt(encryptResultBytes, keyBytes, ivBytes);
string decryptResult = Encoding.GetEncoding("GBK").GetString(decryptResultBytes);
Console.WriteLine("原文:" + user);
Console.WriteLine("加密结果:" + encryptResult);
Console.WriteLine("解密结果:" + decryptResult);结果:



成功了!
再测试其他的 private static void TestEncryptDecrypt()
{
TestEncryptDecrypt("01", "7E54F48557F4C326");
TestEncryptDecrypt("admin", "4500A125845A2CF0");
TestEncryptDecrypt("123456", "A988E19289AAE29D");
TestEncryptDecrypt("123456789dgdfgdg", "AD97DA31EB80205CDE6250D2CE4C50A9120ABD5247750190");
TestEncryptDecrypt("123143324324324", "92087F4E9D696F1FBBE2B543B858A462");
}

/// <param name="text">明文</param>
/// <param name="result">预期密文</param>
private static void TestEncryptDecrypt(string text,string result)
{
string keyHex = "8F0D26E658D0B69E";
byte[] keyBytes = HexToBytes(keyHex);

byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };

//string user = "admin";
byte[] userBytes = Encoding.GetEncoding("GBK").GetBytes(text);

byte[] encryptResultBytes = DESEncrypt(userBytes, keyBytes, ivBytes);
string encryptResult = BytesToHex(encryptResultBytes);

byte[] decryptResultBytes = DESDecrypt(encryptResultBytes, keyBytes, ivBytes);
string decryptResult = Encoding.GetEncoding("GBK").GetString(decryptResultBytes);

Console.WriteLine("原文:{0,-20}加密结果:{1,-50}解密结果:{2}", text, encryptResult,decryptResult);
Console.WriteLine("原文:{0,-20}预期结果:{1,-50}是否相同:{2}\n", text, result, encryptResult == result);
}结果:



字符长度少时没问题,长度多了后就不行了,只有最前面部分是相同的。
另外,用预期密文解密会出现异常。



怎么回事呢?
秘钥和解密的过程应该是没问题的。
观察,应该是8个字符明文对应生成16个字符密文,8个一组,
尝试将12314332 4324324分成2组加密,结果:



12314332加密结果是32位的字符串,但是前半部分和预期结果的前半部分相同。

4324324加密结果是和预期结果的后半部分相同。

有搞头
考虑分组加密、解密。
是对string分组还是对byte分组?
两种都试试 /// <param name="text">明文</param>
/// <param name="result">预期密文</param>
private static void TestEncryptDecrypt_StringList(string text, string result)
{
string keyHex = "8F0D26E658D0B69E";
byte[] keyBytes = HexToBytes(keyHex);
byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
var stringList = GetStringList(text);//每8个字符串为一组
Console.WriteLine("原文:{0}", text);
for (int i = 0; i < stringList.Count; i++)
{
string item = stringList[i];
byte[] userBytes = Encoding.GetEncoding("GBK").GetBytes(item);
byte[] encryptResultBytes = DESEncrypt(userBytes, keyBytes, ivBytes);
string encryptResult = BytesToHex(encryptResultBytes);
Console.WriteLine("加密结果[{0}]:{1,-50}", i, encryptResult);
}
Console.WriteLine();
}

private static List<string> GetStringList(string text)
{
List<string> stringList = new List<string>();
string temp = null;
for (int i = 0; i < text.Length; i++)
{
int j = i%8;
if (j == 0)
{
if (temp != null)
{
stringList.Add(temp);
}
temp = "";
}
if (temp != null)
temp += text[i];
}
if (temp != null)
{
stringList.Add(temp);
}
return stringList;
}

/// <param name="text">明文</param>
/// <param name="result">预期密文</param>
private static void TestEncryptDecrypt_ByteList(string text, string result)
{
string keyHex = "8F0D26E658D0B69E";
byte[] keyBytes = HexToBytes(keyHex);
byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] userBytes = Encoding.GetEncoding("GBK").GetBytes(text);
//var bytesList = GetBytesArray(userBytes);//每8个byte为一组,不能用这个
var bytesList = GetBytesList(userBytes);//每8个byte为一组
Console.WriteLine("原文:{0}", text);
for (int i = 0; i < bytesList.Count; i++)
{
byte[] encryptResultBytes = DESEncrypt(bytesList[i].ToArray(), keyBytes, ivBytes);
string encryptResult = BytesToHex(encryptResultBytes);
Console.WriteLine("加密结果[{0}]:{1,-50}", i, encryptResult);
}
Console.WriteLine();
}

private static List<List<byte>> GetBytesList(byte[] userBytes)
{
List<List<byte>> bytesList = new List<List<byte>>();
List<byte> temp = null;
for (int i = 0; i < userBytes.Length; i++)
{
int j = i % 8;
if (j == 0)
{
if (temp != null)
{
bytesList.Add(temp);
}
temp =new List<byte>();
}
if (temp != null)
{
temp.Add(userBytes[i]);
}
}
if (temp != null)
{
bytesList.Add(temp);
}
return bytesList;
}

private static List<byte[]> GetBytesArray(byte[] userBytes)
{
List<byte[]> bytesList = new List<byte[]>();
byte[] temp = null;
for (int i = 0; i < userBytes.Length; i++)
{
int j = i % 8;
if (j == 0)
{
if (temp != null)
{
bytesList.Add(temp);
}
temp = new byte[8];
}
if (temp != null)
temp[j] = userBytes[i];
}
if (temp != null)
{
bytesList.Add(temp);
}
return bytesList;
}结果一样



考虑以后可能出现的中文,使用byte分组的方式继续。 /// <param name="text">明文</param>
/// <param name="result">预期密文</param>
private static void TestEncryptDecrypt_ByteList(string text, string result)
{
string keyHex = "8F0D26E658D0B69E";
byte[] keyBytes = HexToBytes(keyHex);
byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] userBytes = Encoding.GetEncoding("GBK").GetBytes(text);
//var bytesList = GetBytesArray(userBytes);//每8个byte为一组,不能用这个
var bytesList = GetBytesList(userBytes);//每8个byte为一组
Console.WriteLine("原文:{0}", text);
string encryptResult = "";
for (int i = 0; i < bytesList.Count; i++)
{
byte[] encryptResultPartBytes = DESEncrypt(bytesList[i].ToArray(), keyBytes, ivBytes);//加密
string encryptResultPart = BytesToHex(encryptResultPartBytes);

byte[] decryptResultPartBytes = DESDecrypt(encryptResultPartBytes, keyBytes, ivBytes);//解密
string decryptResultPart = Encoding.GetEncoding("GBK").GetString(decryptResultPartBytes);

string beforePart= encryptResultPart.Substring(0, 16);//取前半部分
encryptResult += beforePart;

string decryptResultPart2 = "";
//byte[] encryptResultPartBytes2 = HexToBytes(beforePart);
//byte[] decryptResultPartBytes2 = DESDecrypt(encryptResultPartBytes2, keyBytes, ivBytes);//解密
//decryptResultPart2 = Encoding.GetEncoding("GBK").GetString(decryptResultPartBytes2);

Console.WriteLine("加密结果[{0}]:{1,-50}解密结果[{0}]:{2}\t{3}", i, encryptResultPart, decryptResultPart, decryptResultPart2);
}
Console.WriteLine("加密结果:{0}", encryptResult);
Console.WriteLine("预期结果:{0}", result);
Console.WriteLine("是否相同:{0}", result== encryptResult);

Console.WriteLine();
}
将分组的加密结果组织起来能够得到和Java一样的结果但是!将预期的密文分组解密还是会出现前面的“不正确的数据”的异常。
通过研究资料1中提供的代码,理解了des.Padding = PaddingMode.None的含义,在加密和解密前都加上: if (by.Length%8 == 0)//已经对其
{
//sa.Mode = CipherMode.CBC;
sa.Padding = PaddingMode.None;//默认是PKCS7,在by没有对其时使用
}能够分组解密了。
测试TestEncryptDecrypt_ByteList函数



123143324324324可以了,123456789dgdfgdg还是不行。

怀疑是123456789dgdfgdg后面跟了一个不可见的字符串,但是空格 \n \t都不是。

不考虑加密,尝试对92087F4E9D696F1FBBE2B543B858A462和
AD97DA31EB80205CDE6250D2CE4C50A9120ABD5247750190进行解密试试。
120ABD5247750190部分解密的结果是byte[] {8,8,8,8,8,8,8,8},变为字符串的话是\b\b\b\b\b\b\b\b,不可见的。将这部分去除就是正确的解密结果了。

接下来做开始的获取秘钥的代码,前面是手动获取的,接下来要写代码。
通过代码知道.dat文件的大小是263,key的位置是169开始。 private static string LoadKeyFromFile(string path)
{
byte[] bytes = LoadFile(path);
int index = FindKeyIndex(bytes);//和手动获取的Key比较找到位置
//index=169
byte[] keyBytes2=new byte[8];
Array.Copy(bytes, index, keyBytes2, 0, 8);
string hex = BytesToHex(keyBytes2);
return hex;
}

private static int FindKeyIndex(byte[] bytes)
{
byte[] keyBytes = HexToBytes("8F0D26E658D0B69E");
int index = 0;
for (int i = 0; i < bytes.Length; i++)
{
if (bytes[i] == keyBytes[0])
{
int j = 0;
for (; j < keyBytes.Length; j++)
{
if (keyBytes[j] != bytes[i + j])
{
break;
}
}
if (j == 8)
{
index = i;
}
}
}
return index;
}

private static byte[] LoadFile(string path)
{
FileStream fs = new FileStream(path, FileMode.Open);
//获取文件大小
long size = fs.Length;
byte[] array = new byte[size];
//将文件读到byte数组中
fs.Read(array, 0, array.Length);
fs.Close();

return array;
}

最后将现有的代码都整理一下,写成一个类using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace DESTest
{
/// <summary>
/// DES加密解密(结果和Java的代码一致)
/// </summary>
public class DESCipher
{
private static byte[] EncryptionIV4
{
get
{
return new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
}
}

public byte[] SecretKey;

public DESCipher(string keyFilePath)
{
SecretKey = LoadKeyFromFile(keyFilePath);
}

public DESCipher(byte[] secretKey)
{
SecretKey = secretKey;
}

private static byte[] LoadKeyFromFile(string path)
{
byte[] bytes = ByteHelper.LoadFile(path); //大小是263
int index = 169; //固定位置
byte[] keyBytes2 = new byte[8];
Array.Copy(bytes, index, keyBytes2, 0, 8);
return keyBytes2;
}

/// <summary>
/// 解密
/// </summary>
public string Decrypt(string source)
{
byte[] bytes = ByteHelper.HexToBytes(source);
var bytesList = ByteHelper.GetBytesList(bytes);//每8个byte为一组
string decryptResult = "";
for (int i = 0; i < bytesList.Count; i++)
{
byte[] decryptResultPartBytes = DESDecrypt(bytesList[i].ToArray(), SecretKey, EncryptionIV4);//解密
string decryptResultPart = ByteHelper.BytesToString(decryptResultPartBytes);
decryptResult += decryptResultPart;
}
return decryptResult;
}

/// <summary>
/// 加密
/// </summary>
/// <param name="source"></param>
public string Encrypt(string source)
{
byte[] userBytes = Encoding.GetEncoding("GBK").GetBytes(source);
var bytesList = ByteHelper.GetBytesList(userBytes);//每8个byte为一组
if (userBytes.Length % 8 == 0)//不知道是否有必要
{
bytesList.Add(new List<byte>() { 8, 8, 8, 8, 8, 8, 8, 8 });
}
string encryptResult = "";
for (int i = 0; i < bytesList.Count; i++)
{
byte[] encryptResultPartBytes = DESEncrypt(bytesList[i].ToArray(), SecretKey, EncryptionIV4);//加密
string encryptResultPart = ByteHelper.BytesToHex(encryptResultPartBytes);
encryptResult += encryptResultPart;
}
return encryptResult;
}

/// <summary>
/// C# DES加密方法
/// </summary>
/// <param name="by">要加密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>加密后的字符串</returns>
public static byte[] DESEncrypt(byte[] by, byte[] key, byte[] iv)
{
using (DESCryptoServiceProvider sa
= new DESCryptoServiceProvider { Key = key, IV = iv })
{
if (by.Length % 8 == 0)//已经对其
{
//sa.Mode = CipherMode.CBC;
sa.Padding = PaddingMode.None;//默认是PKCS7,在by没有对其时使用
}
using (ICryptoTransform ct = sa.CreateEncryptor())
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
try
{
cs.Write(by, 0, by.Length);
cs.FlushFinalBlock();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
return ms.ToArray();
}
}
}
}

/// <summary>
/// C# DES解密方法
/// </summary>
/// <param name="byt">待解密的字符串</param>
/// <param name="key">密钥</param>
/// <param name="iv">向量</param>
/// <returns>解密后的字符串</returns>
public static byte[] DESDecrypt(byte[] by, byte[] key, byte[] iv)
{
using (DESCryptoServiceProvider sa =
new DESCryptoServiceProvider
{ Key = key, IV = iv })
{
if (by.Length % 8 == 0)//已经对其
{
//sa.Mode = CipherMode.CBC;
sa.Padding = PaddingMode.None;//默认是PKCS7,在by没有对其时使用
}
using (ICryptoTransform ct = sa.CreateDecryptor())
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
try
{
cs.Write(by, 0, by.Length);
cs.FlushFinalBlock();
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
return ms.ToArray();
}
}
}
}
}

public static class ByteHelper
{
public static byte[] LoadFile(string path)
{
FileStream fs = new FileStream(path, FileMode.Open);
//获取文件大小
long size = fs.Length;
byte[] array = new byte[size];
//将文件读到byte数组中
fs.Read(array, 0, array.Length);
fs.Close();

return array;
}

/// <summary>
/// 每8个byte为一组
/// </summary>
/// <param name="userBytes"></param>
/// <returns></returns>
public static List<List<byte>> GetBytesList(byte[] userBytes)
{
List<List<byte>> bytesList = new List<List<byte>>();
List<byte> temp = null;
for (int i = 0; i < userBytes.Length; i++)
{
int j = i % 8;
if (j == 0)
{
if (temp != null)
{
bytesList.Add(temp);
}
temp = new List<byte>();
}
if (temp != null)
{
temp.Add(userBytes[i]);
}
}
if (temp != null)
{
bytesList.Add(temp);
}
return bytesList;
}

public static string BytesToString(byte[] bytes)
{
List<byte> list = new List<byte>();
foreach (byte b in bytes)
{
if (b > 8)
{
list.Add(b);
}
}
return Encoding.GetEncoding("GBK").GetString(list.ToArray());
}

public static byte[] HexToBytes(string hex)
{
hex = hex.ToUpper();
int len = (hex.Length/2);
byte[] result = new byte[len];
char[] achar = hex.ToCharArray();
for (int i = 0; i < len; i++)
{
int pos = i*2;
string by = new string(new char[] {achar[pos], achar[pos + 1]});
result[i] = Convert.ToByte(by, 16);
}
return result;
}

public static string BytesToHex(byte[] bytes)
{
StringBuilder ret = new StringBuilder();
foreach (byte b in bytes)
{
ret.AppendFormat("{0:X2}", b); //{0:X2} 大写
}
var hex = ret.ToString();
return hex;
}
}
}
好了,两天的研究成果。
有空再研究一下方案二,C#调用Java。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: