大二下學期應用密碼學課程設計
已同步github項目:
url:https://github.com/EricLi404/Java-Demos/tree/master/Des-Demo
git:https://github.com/EricLi404/Java-Demos.git
實作了des算法,具體的每一步的輸出都有記錄,沒有加入工作模式,支援加密的輸入為英文和數字混合的字元串,填充方式采用的無限填充0的做法。下面是源碼。
// 主類,含有一些調試資訊,各種輸出
package cryptology;
import java.util.Scanner;
/**
* Created by leif on 2016/3/26 0026.
*/
public class des {
public static void main(String[] args) {
System.out.println("**********************************************************");
System.out.println(" DES加解密分步示範 ");
System.out.println("**********************************************************");
System.out.println();
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
System.out.print("請輸入明文(支援任意長度字母數字組合):");
String mmmmmm = in.nextLine();
System.out.print("請輸入密鑰(支援任意格式輸入):");
String kkkkkk = in.nextLine();
String[] M = util.all2string(mmmmmm);
char[] K = util.keypre(kkkkkk);
descore descore = new descore();
String mimi = descore.en(M, K);
String demimi = descore.de(util.all222string(mimi), K);
String demimistring = util.byte2string(demimi);
System.out.println("*************************************************");
System.out.println("**********************結果***********************");
System.out.println("明文:"+mmmmmm);
System.out.println("------------------------------------------------------------");
System.out.println("加密結果:");
System.out.println("二進制:"+ mimi);
System.out.println("十六進制:"+util.two2hex(mimi));
System.out.println("------------------------------------------------------------");
System.out.println("解密結果:");
System.out.println("二進制:"+demimi);
System.out.println("十六進制:"+util.two2hex(demimi));
System.out.println("編碼後:"+demimistring);
}
}
// 核心算法類
package cryptology;
/**
* Created by leif on 2016/3/26 0026.
*/
public class descore {
/**
* 初始置換
* @param M char[64]
* @return char[56]
*/
private char[] initReplace(char[] M){
char[] tM = new char[];
for (int i = ; i < ; i++){
tM[i] = M[data.IP[i]-];
}
return tM;
}
/**
* 密鑰置換 1
* @param K char[64]
* @return char[56]
*/
private char[] keyReplace1(char[] K){
char[] tK = new char[];
for (int i = ; i < ; i++){
tK[i] = K[data.PC_1[i]-];
}
return tK;
}
/**
* 生成子密鑰
* @param K char[56]
* @param offset 左移位數 int
* @return char[56]
*/
private char[] loopKey(char[] K, int offset){
String k1 = new String();
String k2 = new String();
String k = new String(K);
k1 = (k.substring(,)+k.substring(,)).substring(offset,offset+);
k2 = (k.substring(,)+k.substring(,)).substring(offset,offset+);
return (k1+k2).toCharArray();
}
/**
* 密鑰置換2
* @param K char[56]
* @return char[48]
*/
private char[] keyReplace2(char[] K){
char[] tK = new char[];
for (int i = ; i < ; i++){
tK[i] = K[data.PC_2[i]-];
}
return tK;
}
/**
* 生成16輪的輪密鑰
* @param K char[64]
* @return
*/
private char[][] getKey(char[] K){
char[][] tK = new char[][];
char[][] ttK = new char[][];
char[] k1 = new char[];
k1 = keyReplace1(K);
tK[] = loopKey(k1,data.LeftMove[]);
for (int i = ; i < ; i++){
tK[i] = loopKey(tK[i-],data.LeftMove[i]);
}
for(int i = ; i < ; i++){
ttK[i] = keyReplace2(tK[i]);
}
return ttK;
}
/**
* E 表置換(拓展置換)
* @param R char[32]
* @return char[48]
*/
private char[] eReplace(char[] R){
char[] tR = new char[];
for (int i = ;i < ; i++){
tR[i] = R[data.E[i]-];
}
return tR;
}
/**
* xor異或操作
* @param tR char[48]
* @param K char[48] 輪密鑰
* @return
*/
private char[] xor(char[] tR, char[] K){
String x = new String();
for (int i = ; i < tR.length; i++){
x += tR[i] ^ K[i];
}
return x.toCharArray();
}
/**
* s 盒置換
* @param xorR char[48]
* @return char[32]
*/
private char[] sReplace(char[] xorR){
char[][] tR = new char[][];
/* String nn = new String(R);
System.out.println(nn+nn.length());*/
String sr = new String();
for (int i = ; i < ; i++){
for (int j = ; j < ; j++){
tR[i][j] = xorR[i*+j];
}
int p = util.two2ten(String.valueOf(tR[i][])+String.valueOf(tR[i][]));
int q = util.two2ten(String.valueOf(tR[i][])+String.valueOf(tR[i][])+String.valueOf(tR[i][])+String.valueOf(tR[i][]));
sr += String.format("%04d",Integer.parseInt(Integer.toBinaryString(data.S_Box[i][p][q])));
// sr += String.format("%04d",Integer.parseInt(Integer.toBinaryString(data.S_Box[i][(tR[i][0] << 1) + tR[i][5]][(tR[i][1] << 3) + (tR[i][2] << 2) + (tR[i][3] << 1) + tR[i][4]])));
}
return sr.toCharArray();
}
/**
* p 表置換
* @param sR char[32]
* @return char[32]
*/
private char[] pReplace(char[] sR){
char[] pR = new char[];
for (int i = ; i < ; i++){
pR[i] = sR[data.P[i]-];
}
return pR;
}
/**
* 終結置換
* @param R char[64]
* @return char[64]
*/
private char[] init_1Replace(char[] R){
char[] tR = new char[];
for (int i = ; i < ; i++){
tR[i] = R[data.IP_1[i]-];
}
return tR;
}
/**
* 輪置換
* @param R char[32]
* @param K char[32]
* @return char[32]
*/
public char[] core(char[] R, char[] K){
char[] eR = eReplace(R);
System.out.println("Etable置換結果---"+new String(eR)+"-----"+util.two2hex(new String(eR)));
System.out.println("輪密鑰---"+new String(K)+"-----"+util.two2hex(new String(K)));
char[] xorR = xor(eR,K);
System.out.println("xor-1結果---"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
char[] sR = sReplace(xorR);
System.out.println("Sbox置換結果---"+new String(sR)+"-----"+util.two2hex(new String(sR)));
char[] pR = pReplace(sR);
System.out.println("Ptable置換結果---"+new String(pR)+"-----"+util.two2hex(new String(pR)));
@SuppressWarnings("unused")
String pp = new String(pR);
return pR;
}
public String enCode(char[] M, char[] K){
System.out.println("#########################");
System.out.println(" ===== === == == = = 開始加密");
System.out.println("比特流為---"+new String(M)+"-----"+util.two2hex(new String(M)));
System.out.println("密鑰為---"+new String(K)+"-----"+util.two2hex(new String(K)));
char[][] L = new char[][];
char[][] R = new char[][];
char[][] key = new char[][];
char[] res = new char[];
char[] r = new char[];
M = initReplace(M);
System.out.println("IP置換結果---"+new String(M)+"-----"+util.two2hex(new String(M)));
key = getKey(K);
for (int i = ; i < ; i++){
L[][i] = M[i];
R[][i] = M[i+];
}
for (int i = ; i < ; i++){
System.out.println("===================第 "+i+" 輪==================");
char[] xorR = xor(L[i-],core(R[i-],key[i-]));
System.out.println("xor-2結果"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
for (int j = ; j < ; j++){
L[i][j] = R[i-][j];
R[i][j] = xorR[j];
}
}
for (int i = ; i < ; i++){
res[i] = R[][i];
res[i+] = L[][i];
}
r = init_1Replace(res);
String rr = new String(r);
System.out.println("終結置換結果---"+new String(rr)+"-----"+util.two2hex(new String(rr)));
return rr;
}
public String deCode(char[] M, char[] K){
System.out.println("#########################");
System.out.println(" ===== === == == = = 開始解密");
System.out.println("比特流為---"+new String(M)+"-----"+util.two2hex(new String(M)));
System.out.println("密鑰為---"+new String(K)+"-----"+util.two2hex(new String(K)));
char[][] L = new char[][];
char[][] R = new char[][];
char[][] key = new char[][];
char[] res = new char[];
char[] r = new char[];
M = initReplace(M);
System.out.println("IP置換結果---"+new String(M)+"-----"+util.two2hex(new String(M)));
key = getKey(K);
for (int i = ; i < ; i++){
L[][i] = M[i];
R[][i] = M[i+];
}
for (int i = ; i < ; i++){
System.out.println("===================第 "+i+" 輪==================");
char[] xorR = xor(L[i-],core(R[i-],key[-i]));
System.out.println("xor-2結果"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
for (int j = ; j < ; j++){
L[i][j] = R[i-][j];
R[i][j] = xorR[j];
}
}
for (int i = ; i < ; i++){
res[i] = R[][i];
res[i+] = L[][i];
}
r = init_1Replace(res);
String rr = new String(r);
return rr;
}
public String en(String[] mm, char[] kk) {
String mi = "";
for(int i = ; i < mm.length; i++){
char[] charrr = mm[i].toCharArray();
mi += enCode(charrr, kk);
}
return mi;
}
public String de(String[] mm, char[] kk) {
String mi = "";
for(int i = ; i < mm.length; i++){
char[] charrr = mm[i].toCharArray();
mi += deCode(charrr, kk);
}
return mi;
}
}
// des算法置換過程需要用到的一些置換表
package cryptology;
/**
* Created by leif on 2016/3/26 0026.
*/
public class data {
// 聲明常量位元組數組
static int length = ;
public static int getLength() {
return length;
}
public static void setLength(int length) {
data.length = length;
}
/**
* 初始置換
*/
static final int[] IP = {
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , ,
}; // 64
/**
*
*/
static final int[] IP_1 = {
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , ,
}; // 64
/**
* 密鑰置換 1
*/
static final int[] PC_1 = {
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
,
}; // 56
/**
* 密鑰置換 2
*/
static final int[] PC_2 = {
, , , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , ,
}; // 48
/**
* E表置換(将密鑰的右32置換為48)
*/
static final int[] E = {
, , , , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , ,
, , , , , , , , , ,
}; // 48
static final int[] P = {
, , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , ,
}; // 32
static final int[][][] S_Box = {
{
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[1]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[2]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[3]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[4]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[5]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[6]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
},
{ // S_Box[7]
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , }
} // S_Box[8]
};
static final int[] LeftMove = {
, , , , , , , , , , , , , , ,
}; // 左移位置清單
}
// 系統裡用到的一些公共的功能性函數
package cryptology;
import java.util.HashMap;
/**
* Created by leif on 2016/6/21.
*/
public class util {
/**
* 二進制轉十進制
* @param two 二進制 string
* @return 十進制 int
*/
public static int two2ten(String two){
String s = two;
int x = ;
int pow = ;
for (int i = s.length() - ; i >= ; i--) {
x += Math.pow(, pow) * (s.charAt(i) == '1' ? : );
pow ++;
}
return x;
}
/**
* 二進制轉十六進制
* @param two 二進制 string
* @return 十六進制 int
*/
public static String two2hex(String bString){
if (bString == null || bString.equals("") || bString.length() % != )
return null;
StringBuffer tmp = new StringBuffer();
int iTmp = ;
for (int i = ; i < bString.length(); i += )
{
iTmp = ;
for (int j = ; j < ; j++)
{
iTmp += Integer.parseInt(bString.substring(i + j, i + j + )) << ( - j - );
}
tmp.append(Integer.toHexString(iTmp));
}
return tmp.toString();
}
/**
* 将64位int數組轉化為64位char數組
* @param mm int[64]
* @return char[64]
*/
public static char[] int64tochar64(int[] mm){
@SuppressWarnings("unused")
char[] g = new char[];
String gg = new String();
for (int i = ; i < ; i++){
gg += mm[i];
}
return gg.toCharArray();
}
public static HashMap<Integer,char[]> preMI(String mmmmmm){
String lmmmmmm = "";
for(int i = ; i < mmmmmm.length(); i++){
lmmmmmm += Integer.toBinaryString(Integer.parseInt(mmmmmm.substring(i,i+)));
}
HashMap<Integer, char[] > tmmm = new HashMap<>();
char mmmmm[] = lmmmmmm.toCharArray();
char rm[] = new char[];
int j = ;
for(int i = ; i < lmmmmmm.length(); i++){
rm[i%] = mmmmm[i];
if (i % == ) {
tmmm.put(j, rm);
j++;
}
}
return tmmm;
}
/**
* 明文初始化處理,将每一位轉為一個64bit長度的string
* @param all
* @return
*/
public static String[] all2string(String all) {
byte byteall[] = all.getBytes();
String allstring[] = new String[all.length()];
for(int i = ; i < byteall.length; i++){
allstring[i] = String.format("%064d", Integer.parseInt(Integer.toBinaryString(byteall[i])));
}
return allstring;
}
/**
* 密文解密預處理,将密文每64bit截取成一個string
* @param all
* @return
*/
public static String[] all222string(String all) {
String allstring[] = new String[all.length()/];
for(int i = ; i < allstring.length; i++){
allstring[i] = all.substring(i*,(i+)*);
}
return allstring;
}
/**
* 将解密結果的byte轉為string,還原密文
* @param all
* @return
*/
public static String byte2string(String all) {
byte allstring[] = new byte[all.length()/];
for(int i = ; i < allstring.length; i++){
allstring[i] = (byte) two2ten(all.substring(i*,(i+)*).substring(, ));
}
return new String(allstring);
}
/**
* 将任意格式的密鑰擷取hash值,格式化為char[64]
* @param k
* @return
*/
public static char[] keypre(String k) {
String ha = String.format("%08d", k.hashCode());
String kk = "";
for(int i = ; i < ; i++){
kk += String.format("%08d", Integer.parseInt(Integer.toBinaryString(Integer.parseInt(ha.substring(i, i+)))));
}
return kk.toCharArray();
}
}