对国库数据加密解密

/**
*
* 说明:对国库数据加密、解密
*/

package com.cfcc.tas.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Calendar;
import java.util.Random;


public class TreasuryEncrypt {

//二维数组,61*8;
private final static String ENCRYPT_KEY [][]=
{{"?1i%d3Kx"},{"s8@8$!*i"},{"d7J:SFw4"},{"l6piz3Gn"},
{"Rs5t|o&#"},{"4s*m-y4;"},{"3o34%x:W"},{"a2e+FDKQ"},
{"s{OCS$1?"},{"sAUI<>2a"},{"2_gf<3vQ"},{"b8&o<fH]"},
{"7ds?.asd"},{"sd6sft4V"},{"ds5QTP{q"},{"n4^/?Sys"},
{"sfdteib8"},{"b2s?>LK}"},{"1/dti[qr"},{"a!bfo[[e"},
{"U3v$@h89"},{"8n$Lfv?2"},{"b7bwetjw"},{"bc6ertlx"},
{"h4532:KE"},{"k46SFTTR"},{"3XdrFGty"},{"2nVI%#dM"},
{"1af;mes,"},{"cb$yu.sx"},{"G4s?2+-s"},{"v83+V#OU"},
{"b7|ET&Nd"},{"n6b(G$><"},{"n5fsre65"},{"4lQfaftk"},
{"SDF{}3rd"},{"fert2<db"},{"s246<M19"},{"%dfgd45d"},
{"d5gsb2x!"},{"s8f:oewZ"},{"7d~twpot"},{"y6dsf34s"},
{"k59{_JH:"},{"4hvet*&e"},{"3m;SFsft"},{"sd2JLYI^"},
{"bf*F&^Cn"},{"h^sft.e4"},{"b6[do94)"},{"8gq=0&Fk"},
{"b`ewU<X|"},{"zb6rtx#@"},{"5oj79h:h"},{"sf7lakv%"},
{"SFETE3xd"},{"bvler-2s"},{"1d)(*V>d"},{"&ftwetrr"},
{"00000000"}};


/*
* 密钥的长度
*/
private final static int KEY_LENGTH = ENCRYPT_KEY[0][0].length();

//文件标志(windows)
private final static byte[] WIN_FILE_SIGNAL = {13,10};
private final static byte[] WIN_STR_SIGNAL = {35,35};
private final static int MAX_HEAD_LEN = 4;

//分节符类型
public final static int SIGNAL_TYPE_NULL = -1;
public final static int SIGNAL_TYPE_STR = 0;
public final static int SIGNAL_TYPE_FILE = 1;

//加密和解密字符串时使用,如果字符串中不包含解密用的key,解密字符串时传入改值.
public final static int KEY_NULL = -1;



/*
* 说明: 在TCBS中主要使用了对文件中的内容进行加解密.
* 在TBS中,对字符串加密使用了两种方式,一种是使用回车换行(换行)做为分割密钥和字符串的标志,
* 一种是使用两个'#', 就是WIN_FILE_SIGNAL 和 WIN_STR_SIGNAL.
* 文件内容的加密使用WIN_STR_SIGNAL.
* 修改解密方法,文件加密有两种:一种首行为密钥索引,一种不是
*/


/**
* 对字符串加密
* @param srcStr
* @param sinalType 分节符类型 0:字符串类型 其它:文件类型
* @return
* @throws Exception
*/
public static String Encrypt(String srcStr, int sinalType) throws Exception{
if(srcStr == null || srcStr.trim().length() == 0){
throw new Exception("被加密的字符串不能为空!");
}

//
if(sinalType == SIGNAL_TYPE_STR){
return encryptStr(srcStr, WIN_STR_SIGNAL);
}else{
return encryptStr(srcStr, WIN_FILE_SIGNAL);
}
}

/**
* 对字符串解密 (gkfxjmzjstr)
* @param srcStr : 被加密后的字符串,可以带密钥也可以不带密钥. 不带密钥时需要在参数nKeyIndex传入密文使用的密钥;
* @param nKeyIndex : 参数srcStr中没有有密钥时,使用 nKeyIndex <= 60 并且 nKeyIndex >= 0;
* @param sinalType : 字符串中没有密钥时,该值无效;文件中使用回车换行(\r\n或\n)做为分割符.
* @return
* @throws Exception
*/
public static String Decrypt(String srcStr, int nKeyIndex, int sinalType) throws Exception {
//
byte keyIndex = 0;
byte decrypt[] = null;

//不在key范围内的字符串的key,认为字符串中包含key, 字符串中包含key
if(nKeyIndex < 0 || nKeyIndex > 60){
if(srcStr == null || srcStr.trim().length() == 0){
throw new Exception("被解密的字符串不能为空!");
}else if(srcStr.trim().length() <= MAX_HEAD_LEN){
throw new Exception("被解密的字符串格式错误!");
}

//
if(sinalType < SIGNAL_TYPE_STR){
throw new Exception("被解密的字符串格式错误!");
}

//取key
int idx = 0;
if(sinalType == SIGNAL_TYPE_STR){
idx = srcStr.indexOf(new String(WIN_STR_SIGNAL));
keyIndex = (byte)Integer.parseInt(srcStr.substring(0, idx));
}else{
idx = srcStr.indexOf(new String(WIN_FILE_SIGNAL));
keyIndex = (byte)readStrSignal(srcStr);
}

//
if(keyIndex > 60) {
throw new Exception("字符串格式错误!");
}
if(idx < 0) return null;

decrypt = srcStr.substring(idx + 2, srcStr.length()).getBytes();
}else{
keyIndex = (byte)nKeyIndex;
decrypt = srcStr.getBytes();
}

return new String(decrypt(decrypt, decrypt.length, keyIndex));
}


/**
* 对文件加密(gkjmzj)
* @param srcFile
* @param dstFile
* @throws Exception
*/
public static void Encrypt(String srcFile, String dstFile) throws Exception{

File inFile = new File(srcFile);
if(!inFile.exists()){
throw new Exception("被加密的文件不存在!");
}
//空文件;
if(inFile.length() == 0){
throw new Exception("被加密的文件为空!");
}

File outFile = new File(dstFile);
//
if(!outFile.exists()){
outFile.createNewFile();
}

//使用缓存的方式输入
DataInputStream fin = new DataInputStream(
new BufferedInputStream(
new FileInputStream(inFile)));


//使用缓存的方式输出
DataOutputStream fout = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(outFile)));


//
byte nKeyIndex = genKeyIndex();

//文件开始标志
fout.write(String.valueOf(nKeyIndex).getBytes());
fout.write(WIN_FILE_SIGNAL);

byte[] srcBuff = new byte[1024];
int readLen = -1;
//加密文件
try {
while(true){

readLen = fin.read(srcBuff);
if(readLen < 0){
break;
}

fout.write(encrypt(srcBuff, readLen, nKeyIndex));
}
}catch(EOFException e){
throw new Exception(e.getMessage());
}finally{
fout.flush();
fin.close();
fout.close();
}
}

/**
* 解密文件(gkfxjmzj)
* @param srcFile
* @param dstFile
* @bFisrtLineEncrypt 文件内容的首行是密钥吗?
* @throws Exception
*/
public static void Decrypt(String srcFile, String dstFile, boolean bKeyIsFirstLine) throws Exception{

File inFile = new File(srcFile);
if(!inFile.exists()){
throw new Exception("被解密的文件不存在!");
}

//空文件;
if(inFile.length() == 0){
throw new Exception("被解密的文件为空!");
}

File outFile = new File(dstFile);
//判断文件能否打开
if(!outFile.exists()){
outFile.createNewFile();
}

//
outFile.createNewFile();
//使用缓存的方式输入
DataInputStream fin = new DataInputStream(
new BufferedInputStream(
new FileInputStream(inFile)));


//使用缓存的方式输出
DataOutputStream fout = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(outFile)));


byte keyIndex = 0;
//读文件的首行
if(!bKeyIsFirstLine){
//读文件的首行,直接写入文件;
String line = readLine(fin);
if(line == null || line.trim().length() == 0){
throw new Exception("文件格式错误!");
}
//
line += "\r\n";
fout.write(line.getBytes());
}

//读密钥
keyIndex = (byte)readFileSignal(fin);
if(keyIndex > ENCRYPT_KEY.length || keyIndex < 0){
throw new Exception("文件格式错误!");
}

byte[] srcBuff = new byte[1024];
int readLen = -1;
//解密文件
try{
while(true){
readLen = fin.read(srcBuff);
if(readLen < 0){
break;
}

fout.write(decrypt(srcBuff, readLen, keyIndex));
}
}catch(EOFException e){
throw new Exception(e.getMessage());
}finally{
fin.close();
fout.flush();
fout.close();
}
}


/**
* @deprecated
* gkjmzjfl
* @param inFileName
* @param outFileName
* @param key
* @return
*/
public static void EncryptUnix(String srcFile, String dstFile) throws Exception{
//判断文件能否打开
File inFile = new File(srcFile);
if(!inFile.exists()){
throw new Exception("被加密的文件不存在!");
}
//空文件;
if(inFile.length() == 0){
throw new Exception("被加密的文件为空!");
}

File outFile = new File(dstFile);
//
if(!outFile.exists()){
outFile.createNewFile();
}

//使用缓存的方式输入
DataInputStream fin = new DataInputStream(
new BufferedInputStream(
new FileInputStream(inFile)));


//使用缓存的方式输出
DataOutputStream fout = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(outFile)));

//
byte keyIndex = genKeyIndex();

byte firstLine = 0;
byte srcByte;
byte dstByte;
//
byte keyBytes[] = ENCRYPT_KEY[keyIndex][0].getBytes();
int keyBytesIdx = 0;

try{
while(true){
//
srcByte = fin.readByte();

if(firstLine == 2){
dstByte = xor(srcByte, keyBytes[keyBytesIdx++ % KEY_LENGTH]);
//
if(keyBytesIdx == KEY_LENGTH){
keyBytesIdx = 0;
}
}else{
dstByte = srcByte;
}

fout.write(dstByte);

//
if(dstByte == 13 && firstLine == 0){
firstLine = 1;
}

if(dstByte == 10 && firstLine == 1){
fout.write(keyIndex);
firstLine = 2;
}
}
}catch(EOFException e){

}

fin.close();
fout.close();
}

/**
* @deprecated
* 原名:DLL_Encrypt
* @param inKey : 密钥
* @param inData: 被加密或解密的数据
* @param bFlag : true 使用 inKey 对 inData 加密
* false 使用 inKey 对 inData 解密;
* @return
*/

public static String Encrypt(String inKey, String inData, boolean bFlag) throws Exception {

if(inKey == null || inKey.trim().length() == 0 ||
inData == null || inData.trim().length() == 0){
throw new Exception("密钥和数据不能为空!");
}
//
byte[] keyBytes = inKey.getBytes();
byte[] dataBytes = inData.getBytes();

int keyLen = keyBytes.length;
int dataLen = dataBytes.length;

ByteBuffer buff = null;

//计算key的和
int keySum = 0;
for(int i = 0; i < keyLen; i++){
keySum += keyBytes[i];
}

//
int keyValue = 0;
//加密
if(bFlag){
//
buff = ByteBuffer.allocate(dataLen * 5);
//
for(int i = 0; i < dataLen; i++){
keyValue = keySum;
//
keyValue += dataBytes[i];
//
keyValue ^= keyBytes[0];
//
buff.put(String.format("%05d", keyValue).getBytes());
}
} else {

//解密
String subData = "";
//被加密后的数据是5的整数倍
if(dataLen % 5!=0){
throw new Exception("数据格式错误!");
}
//实际数据的长度
dataLen = dataLen / 5;
buff = ByteBuffer.allocate(dataLen);

//
for(int i = 0; i < dataLen; i++)
{
subData = inData.substring(i * 5, (i + 1) * 5);
//
keyValue = Integer.valueOf(subData).intValue();
//
keyValue ^= keyBytes[0];
//
keyValue -= keySum;
//
buff.put((byte)keyValue);
}
}

return new String(buff.array());
}


/**
* 对字符串加密(gkjmzjstr)
* @param srcStr
* @param sinal : 分节符类型 字符类型和文件类型
* @return
* @throws Exception
*/
private static String encryptStr(String srcStr, byte sinal[]) throws Exception{
if(srcStr == null || srcStr.trim().length() == 0){
throw new Exception("被加密的字符串不能为空!");
}

//取密钥
byte keyIndex = genKeyIndex();

//取字节流
byte srcBytes[] = srcStr.getBytes();
ByteBuffer buff = ByteBuffer.allocate(srcBytes.length + 2);

//写密钥标志
buff.put(sinal);

//
buff.put(encrypt(srcBytes, srcBytes.length, keyIndex));

return Integer.toString(keyIndex)+ new String(buff.array());
}

/**
* 对字节数组加密
* @param srcBytes
* @param nSrcBytes
* @param keyIndex
* @return
* @throws Exception
*/
private static byte[] encrypt(byte[] srcBytes, int nSrcBytes, byte keyIndex) throws Exception{
ByteBuffer buff = ByteBuffer.allocate(nSrcBytes);
//加密
byte keyBytes[] = ENCRYPT_KEY[keyIndex][0].getBytes();
int keyByteIdx = 0;
for(int i = 0; i< nSrcBytes; i++) {
buff.put(xor(srcBytes[i], keyBytes[keyByteIdx++]));
//
if(keyByteIdx == KEY_LENGTH){
keyByteIdx = 0;
}
}

return buff.array();
}

/**
* 对字节数据解密
* @param srcBytes
* @param nSrcBytes
* @param keyIndex
* @return
* @throws Exception
*/
private static byte[] decrypt(byte[] srcBytes, int nSrcBytes, byte keyIndex) throws Exception {
//校验密钥索引
if(keyIndex > 60) {
throw new Exception("字符串格式错误!");
}

//解密
ByteBuffer outBuff = ByteBuffer.allocate(nSrcBytes);
byte keyItems[] = ENCRYPT_KEY[keyIndex][0].getBytes();
int keyItemIdx = 0;
for(int i = 0; i < nSrcBytes; i++)
{
outBuff.put(xor(srcBytes[i], keyItems[keyItemIdx++]));

if(keyItemIdx == KEY_LENGTH){
keyItemIdx = 0;
}
}

return outBuff.array();
}


/**
* 使用 格林威治标准时间作为随机数的种子,生成密钥索引
* @return
*/
private static byte genKeyIndex(){
//生成随机数
Random rand = new Random(Calendar.getInstance().getTimeInMillis());
long randValue = rand.nextInt();

//取无符号数据;
if(randValue < 0){
randValue = (0xFFFFFFFFL + randValue) + 1;
}

//取模
Long result = randValue % 60;

//
return result.byteValue();
}

/**
* 异或操作(不能对字节进行异或操作,所以添加该方法)
* @param src1
* @param src2
* @return
*/
private static byte xor(byte src1, byte src2){
int result = Byte.valueOf(src1).intValue() ^ Byte.valueOf(src2).intValue();
return Integer.valueOf(result).byteValue();
}

/**
* 取文件头部的标志
* @param fin
* @return
* @throws IOException
* Windows中使用'\r\n'(0xD 0xA)回车换行, Linux 或 Unix 中使用'\n'(0xA)表示回车换行;
*/
private static int readFileSignal(DataInputStream fin) throws IOException{

String sIndex = readKeyIndex(fin);
if(sIndex != null){
return Integer.parseInt(sIndex);
}else{
return -1;
}
}

/**
* 取文件头部的标志
* @param fin
* @return
* @throws IOException
*/
private static int readStrSignal(String fin) throws IOException{

String sIndex = readKeyIndex(fin);
if(sIndex != null){
return Integer.parseInt(sIndex);
}else{
return -1;
}
}

/**
* 取文件中密钥的索引
* @param fin
* @return
* @throws IOException
*/
private static String readKeyIndex(DataInputStream fin) throws IOException {
char c = 0;
String sIndex = "";
int len = 0;

//索引 + 标记不超过 6 个字节
while(len < 6){
c = (char)fin.readByte();
len++;

if(c == '\n' || c == '\r'){
if(c == '\r'){
c = (char)fin.readByte();
len++;
if(c == '\n'){
return sIndex;
}else{
sIndex += c;
}
}else{
return sIndex;
}
}else{
sIndex += c;
}
}

return null;
}

/**
* 取文件中密钥的索引
* @param lines
* @return
* @throws IOException
*/
private static String readKeyIndex(String lines) throws IOException {
char c = 0;
String sIndex = "";
int len = 0;

//索引 + 标记不超过 6 个字节, 由密钥数组大小决定
while(len < 6){
c = lines.charAt(len++);

if(c == '\n' || c == '\r'){
if(c == '\r'){
c = lines.charAt(len++);
if(c == '\n'){
return sIndex;
}else{
sIndex += c;
}
}else{
return sIndex;
}
}else{
sIndex += c;
}
}

return null;
}


/**
* 取文件中密钥的索引
* @param fin
* @return
* @throws IOException
*/
private static String readLine(DataInputStream fin) throws IOException {
char c = 0;
String sLine = "";
int len = 0;

try{
//索引 + 标记不超过 6 个字节
while(true){
c = (char)fin.readByte();
len++;

if(c == '\n' || c == '\r'){
if(c == '\r'){
c = (char)fin.readByte();
len++;
if(c == '\n'){
return sLine;
}else{
sLine += c;
}
}else{
return sLine;
}
}else{
sLine += c;
}
}
}catch(EOFException e){
return sLine;
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值