一.加密
DES算法处理的数据对象是一组64比特的明文串。设该明文串为m=m1m2…m64 (mi=0或1)。明文串经过64比特的密钥K来加密,最后生成长度为64比特的密文E。其加密过程图示如下:
DES算法加密过程
对DES算法加密过程图示的说明如下:待加密的64比特明文串m,经过IP置换后,得到的比特串的下标列表如下:
IP 58 50 42 34 26 18 10 2
60 52 44 36 28 20 12 4
62 54 46 38 30 22 14 6
64 56 48 40 32 24 16 8
57 49 41 33 25 17 9 1
59 51 43 35 27 19 11 3
61 53 45 37 29 21 13 5
63 55 47 39 31 23 15 7
该比特串被分为32位的L0和32位的R0两部分。R0子密钥K1(子密钥的生成将在后面讲)经过变换f(R0,K1)(f变换将在下面讲)输出32位的比特串f1,f1与L0做不进位的二进制加法运算。运算规则为:
f1与L0做不进位的二进制加法运算后的结果赋给R1,R0则原封不动的赋给L1。L1与R0又做与以上完全相同的运算,生成L2,R2…… 一共经过16次运算。最后生成R16和L16。其中R16为L15与f(R15,K16)做不进位二进制加法运算的结果,L16是R15的直接赋值。
R16与L16合并成64位的比特串。值得注意的是R16一定要排在L16前面。R16与L16合并后成的比特串,经过置换IP-1后所得比特串的下标列表如下:
IP-1 40 8 48 16 56 24 64 32
39 7 47 15 55 23 63 31
38 6 46 14 54 22 62 30
37 5 45 13 53 21 61 29
36 4 44 12 52 20 60 28
35 3 43 11 51 19 59 27
34 2 42 10 50 18 58 26
33 1 41 9 49 17 57 25
经过置换IP-1后生成的比特串就是密文e.。
下面再讲一下变换f(Ri-1,Ki)。
它的功能是将32比特的输入再转化为32比特的输出。其过程如图所示:
对f变换说明如下:输入Ri-1(32比特)经过变换E后,膨胀为48比特。膨胀后的比特串的下标列表如下:
E: 32 1 2 3 4 5
4 5 6 7 8 9
8 9 10 11 12 13
12 13 14 15 16 17
16 17 18 19 20 21
20 21 22 23 24 25
24 25 26 27 28 29
28 29 30 31 32 31
膨胀后的比特串分为8组,每组6比特。各组经过各自的S盒后,又变为4比特(具体过程见后),合并后又成为32比特。该32比特经过P变换后,其下标列表如下:
P: 16 7 20 21
29 12 28 17
1 15 23 26
5 18 31 10
2 8 24 14
32 27 3 9
19 13 30 6
22 11 4 25
经过P变换后输出的比特串才是32比特的f (Ri-1,Ki)。
下面再讲一下S盒的变换过程。任取一S盒。见图:
在其输入b1,b2,b3,b4,b5,b6中,计算出x=b1*2+b6, y=b5+b4*2+b3*4+b2*8,再从Si表中查出x 行,y 列的值Sxy。将Sxy化为二进制,即得Si盒的输出。(S表如图所示)
至此,DES算法加密原理讲完了。在VC++6.0下的程序源代码为:
for(i=1;i=64;i++)
m1[i]=m[ip[i-1]];//64位明文串输入,经过IP置换。
下面进行迭代。由于各次迭代的方法相同只是输入输出不同,因此只给出其中一次。以第八次为例://进行第八次迭代。首先进行S盒的运算,输入32位比特串。
for(i=1;i=48;i++)//经过E变换扩充,由32位变为48位
RE1[i]=R7[E[i-1]];
for(i=1;i=48;i++)//与K8按位作不进位加法运算
RE1[i]=RE1[i]+K8[i];
for(i=1;i=48;i++)
{
if(RE1[i]==2)
RE1[i]=0;
}
for(i=1;i7;i++)//48位分成8组
{
s11[i]=RE1[i];
s21[i]=RE1[i+6];
s31[i]=RE1[i+12];
s41[i]=RE1[i+18];
s51[i]=RE1[i+24];
s61[i]=RE1[i+30];
s71[i]=RE1[i+36];
s81[i]=RE1[i+42];
}//下面经过S盒,得到8个数。S1,s2,s3,s4,s5,s6,s7,s8分别为S表
s[1]=s1[s11[6]+s11[1]*2][s11[5]+s11[4]*2+s11[3]*4+s11[2]*8];
s[2]=s2[s21[6]+s21[1]*2][s21[5]+s21[4]*2+s21[3]*4+s21[2]*8];
s[3]=s3[s31[6]+s31[1]*2][s31[5]+s31[4]*2+s31[3]*4+s31[2]*8];
s[4]=s4[s41[6]+s41[1]*2][s41[5]+s41[4]*2+s41[3]*4+s41[2]*8];
s[5]=s5[s51[6]+s51[1]*2][s51[5]+s51[4]*2+s51[3]*4+s51[2]*8];
s[6]=s6[s61[6]+s61[1]*2][s61[5]+s61[4]*2+s61[3]*4+s61[2]*8];
s[7]=s7[s71[6]+s71[1]*2][s71[5]+s71[4]*2+s71[3]*4+s71[2]*8];
s[8]=s8[s81[6]+s81[1]*2][s81[5]+s81[4]*2+s81[3]*4+s81[2]*8];
for(i=0;i8;i++)//8个数变换输出二进制
{
for(j=1;j5;j++)
{
temp[j]=s[i+1]%2;
s[i+1]=s[i+1]/2;
}
for(j=1;j5;j++)
f[4*i+j]=temp[5-j];
}
for(i=1;i33;i++)//经过P变换
frk[i]=f[P[i-1]];//S盒运算完成
for(i=1;i33;i++)//左右交换
L8[i]=R7[i];
for(i=1;i33;i++)//R8为L7与f(R,K)进行不进位二进制加法运算结果
{
R8[i]=L7[i]+frk[i];
if(R8[i]==2)
R8[i]=0;
}
[ 原创文档 本文适合中级读者 已阅读21783次 ] 文档 代码 工具
DES算法及其在VC++6.0下的实现(下)
作者:航天医学工程研究所四室 朱彦军
在《DES算法及其在VC++6.0下的实现(上)》中主要介绍了DES算法的基本原理,下面让我们继续:
二.子密钥的生成
64比特的密钥生成16个48比特的子密钥。其生成过程见图:
子密钥生成过程具体解释如下:
64比特的密钥K,经过PC-1后,生成56比特的串。其下标如表所示:
PC-1 57 49 41 33 25 17 9
1 58 50 42 34 26 18
10 2 59 51 43 35 27
19 11 3 60 52 44 36
63 55 47 39 31 23 15
7 62 54 46 38 30 22
14 6 61 53 45 37 29
21 13 5 28 20 12 4
该比特串分为长度相等的比特串C0和D0。然后C0和D0分别循环左移1位,得到C1和D1。C1和D1合并起来生成C1D1。C1D1经过PC-2变换后即生成48比特的K1。K1的下标列表为:
PC-2 14 17 11 24 1 5
3 28 15 6 21 10
23 19 12 4 26 8
16 7 27 20 13 2
41 52 31 37 47 55
30 40 51 45 33 48
44 49 39 56 34 53
46 42 50 36 29 32
C1、D1分别循环左移LS2位,再合并,经过PC-2,生成子密钥K2……依次类推直至生成子密钥K16。
注意:Lsi (I =1,2,….16)的数值是不同的。具体见下表:
迭代顺序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
左移位数 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1
生成子密钥的VC程序源代码如下:
for(i=1;i57;i++)//输入64位K,经过PC-1变为56位 k0[i]=k[PC_1[i-1]];
56位的K0,均分为28位的C0,D0。C0,D0生成K1和C1,D1。以下几次迭代方法相同,仅以生成K8为例。 for(i=1;i27;i++)//循环左移两位
{
C8[i]=C7[i+2];
D8[i]=D7[i+2];
}
C8[27]=C7[1];
D8[27]=D7[1];
C8[28]=C7[2];
D8[28]=D7[2];
for(i=1;i=28;i++)
{
C[i]=C8[i];
C[i+28]=D8[i];
}
for(i=1;i=48;i++)
K8[i]=C[PC_2[i-1]];//生成子密钥k8
注意:生成的子密钥不同,所需循环左移的位数也不同。源程序中以生成子密钥 K8为例,所以循环左移了两位。但在编程中,生成不同的子密钥应以Lsi表为准。
三.解密
DES的解密过程和DES的加密过程完全类似,只不过将16圈的子密钥序列K1,K2……K16的顺序倒过来。即第一圈用第16个子密钥K16,第二圈用K15,其余类推。
第一圈:
加密后的结果
L=R15, R=L15⊕f(R15,K16)⊕f(R15,K16)=L15
同理R15=L14⊕f(R14,K15), L15=R14。
同理类推:
得 L=R0, R=L0。
其程序源代码与加密相同。在此就不重写。
四.示例
例如:已知明文m=learning, 密钥 k=computer。
明文m的ASCII二进制表示:
m= 01101100 01100101 01100001 01110010
01101110 01101001 01101110 01100111
密钥k的ASCII二进制表示:
k=01100011 01101111 01101101 01110000
01110101 01110100 01100101 01110010
明文m经过IP置换后,得:
11111111 00001000 11010011 10100110 00000000 11111111 01110001 11011000
等分为左右两段:
L0=11111111 00001000 11010011 10100110 R0=00000000 11111111 01110001 11011000
经过16次迭代后,所得结果为:
L1=00000000 11111111 01110001 11011000 R1=00110101 00110001 00111011 10100101
L2=00110101 00110001 00111011 10100101 R2=00010111 11100010 10111010 10000111
L3=00010111 11100010 10111010 10000111 R3=00111110 10110001 00001011 10000100
L4=00111110101100010000101110000100 R4=11110111110101111111101000111110
L5=11110111110101111111101000111110 R5=10010110011001110100111111100101
L6=10010110011001110100111111100101 R6=11001011001010000101110110100111
L7=11001011001010000101110110100111 R7=01100011110011101000111011011001
L8=01100011110011101000111011011001 R8=01001011110100001111001000000100
L9=01001011110100001111001000000100 R9=00011101001101111010111011100001
L10=00011101001101111010111011100001 R10=11101110111110111111010100000101
L11=11101110111110111111010100000101 R11=01101101111011011110010111111000
L12=01101101111011011110010111111000 R12=11111101110011100111000110110111
L13=11111101110011100111000110110111 R13=11100111111001011010101000000100
L14=11100111111001011010101000000100 R14=00011110010010011011100001100001
L15=00011110010010011011100001100001 R15=01010000111001001101110110100011
L16=01010000111001001101110110100011 R16=01111101101010000100110001100001
其中,f函数的结果为:
f1=11001010001110011110100000000011 f2=00010111000111011100101101011111
f3=00001011100000000011000000100001 f4=11100000001101010100000010111001
f5=10101000110101100100010001100001 f6=00111100111111111010011110011001
f7=11110101101010011100000100111100 f8=10000000111110001010111110100011
f9=01111110111110010010000000111000 f10=10100101001010110000011100000001
f11=01110000110110100100101100011001 f12=00010011001101011000010010110010
f13=10001010000010000100111111111100 f14=11100011100001111100100111010110
f15=10110111000000010111011110100111 f16=01100011111000011111010000000000
16个子密钥为:
K1=11110000101111101110111011010000 K2=11100000101111101111011010010101
K3=11110100111111100111011000101000 K4=11100110111101110111001000011010
K5=11101110110101110111011100100110 K6=11101111110100110101101110001011
K7=00101111110100111111101111100110 K8=10111111010110011101101101010000
K9=00011111010110111101101101000100 K10=00111111011110011101110100001001
K11=00011111011011011100110101101000 K12=01011011011011011011110100001010
K13=11011101101011011010110110001111 K14=11010011101011101010111110000000
K15=11111001101111101010011011010011 K16=11110001101111100010111000000001
S盒中,16次运算时,每次的8 个结果为:
第一次:5,11,4,1,0,3,13,9;
第二次:7,13,15,8,12,12,13,1;
第三次:8,0,0,4,8,1,9,12;
第四次:0,7,4,1,7,6,12,4;
第五次:8,1,0,11,5,0,14,14;
第六次:14,12,13,2,7,15,14,10;
第七次:12,15,15,1,9,14,0,4;
第八次:15,8,8,3,2,3,14,5;
第九次:8,14,5,2,1,15,5,12;
第十次:2,8,13,1,9,2,10,2;
第十一次:10,15,8,2,1,12,12,3;
第十二次:5,4,4,0,14,10,7,4;
第十三次:2,13,10,9,2,4,3,13;
第十四次:13,7,14,9,15,0,1,3;
第十五次:3,1,15,5,11,9,11,4;
第十六次:12,3,4,6,9,3,3,0;
子密钥生成过程中,生成的数值为:
C0=0000000011111111111111111011 D0=1000001101110110000001101000
C1=0000000111111111111111110110 D1=0000011011101100000011010001
C2=0000001111111111111111101100 D2=0000110111011000000110100010
C3=0000111111111111111110110000 D3=0011011101100000011010001000
C4=0011111111111111111011000000 D4=1101110110000001101000100000
C5=1111111111111111101100000000 D5=0111011000000110100010000011
C6=1111111111111110110000000011 D6=1101100000011010001000001101
C7=1111111111111011000000001111 D7=0110000001101000100000110111
C8=1111111111101100000000111111 D8=1000000110100010000011011101
C9=1111111111011000000001111111 D9=0000001101000100000110111011
C10=1111111101100000000111111111 D10=0000110100010000011011101100
C11=1111110110000000011111111111 D11=0011010001000001101110110000
C12=1111011000000001111111111111 D12=1101000100000110111011000000
C13=1101100000000111111111111111 D13=0100010000011011101100000011
C14=0110000000011111111111111111 D14=0001000001101110110000001101
C15=1000000001111111111111111101 D15=0100000110111011000000110100
C16=0000000011111111111111111011 D16=1000001101110110000001101000
DES的基本原理是:(传统的)循环(迭代)移位法进行信息位的替换/交换,打乱原信息(数据)位的顺序从而达到信息加密的目的。
DES 的加密方法是:使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。
例如它采用下面的置换表对数据进行置换:
58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
即将输入的第58位换到第一位,第50位换到第2位,...,依此类推,最后一位是原来的第7位。
同时用置换表把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0 是右32位,例:设置换前的输入值为D1D2D3......D64,则经过初始置换后的结果为:L0=D58D50...D8;R0=D57D49...D7。
然后以同样置换方式进行多次的迭代,比如说16次迭代,得出L16,R16组成的数列密文的输出。
接收方只要用同样置换表进行逆变换即可解密出原文。
java加密字符串可以使用des加密算法,实例如下:
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* 加密解密
*
* @author shy.qiu
* @since
*/
public class CryptTest {
/**
* 进行MD5加密
*
* @param info
* 要加密的信息
* @return String 加密后的字符串
*/
public String encryptToMD5(String info) {
byte[] digesta = null;
try {
// 得到一个md5的消息摘要
MessageDigest alga = MessageDigest.getInstance("MD5");
// 添加要进行计算摘要的信息
alga.update(info.getBytes());
// 得到该摘要
digesta = alga.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将摘要转为字符串
String rs = byte2hex(digesta);
return rs;
}
/**
* 进行SHA加密
*
* @param info
* 要加密的信息
* @return String 加密后的字符串
*/
public String encryptToSHA(String info) {
byte[] digesta = null;
try {
// 得到一个SHA-1的消息摘要
MessageDigest alga = MessageDigest.getInstance("SHA-1");
// 添加要进行计算摘要的信息
alga.update(info.getBytes());
// 得到该摘要
digesta = alga.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将摘要转为字符串
String rs = byte2hex(digesta);
return rs;
}
// //////////////////////////////////////////////////////////////////////////
/**
* 创建密匙
*
* @param algorithm
* 加密算法,可用 DES,DESede,Blowfish
* @return SecretKey 秘密(对称)密钥
*/
public SecretKey createSecretKey(String algorithm) {
// 声明KeyGenerator对象
KeyGenerator keygen;
// 声明 密钥对象
SecretKey deskey = null;
try {
// 返回生成指定算法的秘密密钥的 KeyGenerator 对象
keygen = KeyGenerator.getInstance(algorithm);
// 生成一个密钥
deskey = keygen.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 返回密匙
return deskey;
}
/**
* 根据密匙进行DES加密
*
* @param key
* 密匙
* @param info
* 要加密的信息
* @return String 加密后的信息
*/
public String encryptToDES(SecretKey key, String info) {
// 定义 加密算法,可用 DES,DESede,Blowfish
String Algorithm = "DES";
// 加密随机数生成器 (RNG),(可以不写)
SecureRandom sr = new SecureRandom();
// 定义要生成的密文
byte[] cipherByte = null;
try {
// 得到加密/解密器
Cipher c1 = Cipher.getInstance(Algorithm);
// 用指定的密钥和模式初始化Cipher对象
// 参数:(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
c1.init(Cipher.ENCRYPT_MODE, key, sr);
// 对要加密的内容进行编码处理,
cipherByte = c1.doFinal(info.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
// 返回密文的十六进制形式
return byte2hex(cipherByte);
}
/**
* 根据密匙进行DES解密
*
* @param key
* 密匙
* @param sInfo
* 要解密的密文
* @return String 返回解密后信息
*/
public String decryptByDES(SecretKey key, String sInfo) {
// 定义 加密算法,
String Algorithm = "DES";
// 加密随机数生成器 (RNG)
SecureRandom sr = new SecureRandom();
byte[] cipherByte = null;
try {
// 得到加密/解密器
Cipher c1 = Cipher.getInstance(Algorithm);
// 用指定的密钥和模式初始化Cipher对象
c1.init(Cipher.DECRYPT_MODE, key, sr);
// 对要解密的内容进行编码处理
cipherByte = c1.doFinal(hex2byte(sInfo));
} catch (Exception e) {
e.printStackTrace();
}
// return byte2hex(cipherByte);
return new String(cipherByte);
}
// /////////////////////////////////////////////////////////////////////////////
/**
* 创建密匙组,并将公匙,私匙放入到指定文件中
*
* 默认放入mykeys.bat文件中
*/
public void createPairKey() {
try {
// 根据特定的算法一个密钥对生成器
KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA");
// 加密随机数生成器 (RNG)
SecureRandom random = new SecureRandom();
// 重新设置此随机对象的种子
random.setSeed(1000);
// 使用给定的随机源(和默认的参数集合)初始化确定密钥大小的密钥对生成器
keygen.initialize(512, random);// keygen.initialize(512);
// 生成密钥组
KeyPair keys = keygen.generateKeyPair();
// 得到公匙
PublicKey pubkey = keys.getPublic();
// 得到私匙
PrivateKey prikey = keys.getPrivate();
// 将公匙私匙写入到文件当中
doObjToFile("mykeys.bat", new Object[] { prikey, pubkey });
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 利用私匙对信息进行签名 把签名后的信息放入到指定的文件中
*
* @param info
* 要签名的信息
* @param signfile
* 存入的文件
*/
public void signToInfo(String info, String signfile) {
// 从文件当中读取私匙
PrivateKey myprikey = (PrivateKey) getObjFromFile("mykeys.bat", 1);
// 从文件中读取公匙
PublicKey mypubkey = (PublicKey) getObjFromFile("mykeys.bat", 2);
try {
// Signature 对象可用来生成和验证数字签名
Signature signet = Signature.getInstance("DSA");
// 初始化签署签名的私钥
signet.initSign(myprikey);
// 更新要由字节签名或验证的数据
signet.update(info.getBytes());
// 签署或验证所有更新字节的签名,返回签名
byte[] signed = signet.sign();
// 将数字签名,公匙,信息放入文件中
doObjToFile(signfile, new Object[] { signed, mypubkey, info });
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取数字签名文件 根据公匙,签名,信息验证信息的合法性
*
* @return true 验证成功 false 验证失败
*/
public boolean validateSign(String signfile) {
// 读取公匙
PublicKey mypubkey = (PublicKey) getObjFromFile(signfile, 2);
// 读取签名
byte[] signed = (byte[]) getObjFromFile(signfile, 1);
// 读取信息
String info = (String) getObjFromFile(signfile, 3);
try {
// 初始一个Signature对象,并用公钥和签名进行验证
Signature signetcheck = Signature.getInstance("DSA");
// 初始化验证签名的公钥
signetcheck.initVerify(mypubkey);
// 使用指定的 byte 数组更新要签名或验证的数据
signetcheck.update(info.getBytes());
System.out.println(info);
// 验证传入的签名
return signetcheck.verify(signed);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将二进制转化为16进制字符串
*
* @param b
* 二进制字节数组
* @return String
*/
public String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
/**
* 十六进制字符串转化为2进制
*
* @param hex
* @return
*/
public byte[] hex2byte(String hex) {
byte[] ret = new byte[8];
byte[] tmp = hex.getBytes();
for (int i = 0; i 8; i++) {
ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
}
return ret;
}
/**
* 将两个ASCII字符合成一个字节; 如:"EF"-- 0xEF
*
* @param src0
* byte
* @param src1
* byte
* @return byte
*/
public static byte uniteBytes(byte src0, byte src1) {
byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
.byteValue();
_b0 = (byte) (_b0 4);
byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
.byteValue();
byte ret = (byte) (_b0 ^ _b1);
return ret;
}
/**
* 将指定的对象写入指定的文件
*
* @param file
* 指定写入的文件
* @param objs
* 要写入的对象
*/
public void doObjToFile(String file, Object[] objs) {
ObjectOutputStream oos = null;
try {
FileOutputStream fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);
for (int i = 0; i objs.length; i++) {
oos.writeObject(objs[i]);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 返回在文件中指定位置的对象
*
* @param file
* 指定的文件
* @param i
* 从1开始
* @return
*/
public Object getObjFromFile(String file, int i) {
ObjectInputStream ois = null;
Object obj = null;
try {
FileInputStream fis = new FileInputStream(file);
ois = new ObjectInputStream(fis);
for (int j = 0; j i; j++) {
obj = ois.readObject();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
CryptTest jiami = new CryptTest();
// 执行MD5加密"Hello world!"
System.out.println("Hello经过MD5:" + jiami.encryptToMD5("Hello"));
// 生成一个DES算法的密匙
SecretKey key = jiami.createSecretKey("DES");
// 用密匙加密信息"Hello world!"
String str1 = jiami.encryptToDES(key, "Hello");
System.out.println("使用des加密信息Hello为:" + str1);
// 使用这个密匙解密
String str2 = jiami.decryptByDES(key, str1);
System.out.println("解密后为:" + str2);
// 创建公匙和私匙
jiami.createPairKey();
// 对Hello world!使用私匙进行签名
jiami.signToInfo("Hello", "mysign.bat");
// 利用公匙对签名进行验证。
if (jiami.validateSign("mysign.bat")) {
System.out.println("Success!");
} else {
System.out.println("Fail!");
}
}
}
#include stdio.h #include string.h #include windows.h #include conio.h #include "Schedle.h" class CShift{ public: DWORDLONG mask[16]; int step[16]; CShift(){ for(int i=0;i16;i++){ step[i]=2; mask[i]=0xc000000; } step[0]=step[1]=step[8]=step[15]=1; mask[0]=mask[1]=mask[8]=mask[15]=0x8000000; } }; class CDES{ public: CDES(){ m_dwlKey=0; m_dwlData=0; ConvertTableToMask(dwlKey_PC_1,64); //PrintTable(dwlKey_PC_1,7,8); ConvertTableToMask(dwlKey_PC_2,56); ConvertTableToMask(dwlData_IP,64); ConvertTableToMask(dwlData_Expansion,32); ConvertTableToMask(dwlData_FP,64); ConvertTableToMask(dwlData_P,32); Generate_S(); } void PrintBit(DWORDLONG); void EncryptKey(char *); unsigned char* EncryptData(unsigned char *); unsigned char* DescryptData(unsigned char*); private: void ConvertTableToMask(DWORDLONG *,int); void Generate_S(void); void PrintTable(DWORDLONG*,int,int); DWORDLONG ProcessByte(unsigned char*,BOOL); DWORDLONG PermuteTable(DWORDLONG,DWORDLONG*,int); void Generate_K(void); void EncryptKernel(void); DWORDLONG Generate_B(DWORDLONG,DWORDLONG*); /*For verify schedule permutation only*/ DWORDLONG UnPermuteTable(DWORDLONG,DWORDLONG*,int); /**************************************/ DWORDLONG dwlData_S[9][4][16]; CShift m_shift; DWORDLONG m_dwlKey; DWORDLONG m_dwlData; DWORDLONG m_dwl_K[17]; }; void CDES::EncryptKey(char *key){ printf("\nOriginal Key: %s",key); m_dwlKey=ProcessByte((unsigned char*)key,TRUE); // PrintBit(m_dwlKey); m_dwlKey=PermuteTable(m_dwlKey,dwlKey_PC_1,56); // PrintBit(m_dwlKey); Generate_K(); // printf("\n******************************************\n"); } void CDES::Generate_K(void){ DWORDLONG C[17],D[17],tmp; C[0]=m_dwlKey28; D[0]=m_dwlKey0xfffffff; for(int i=1;i=16;i++){ tmp=(C[i-1]m_shift.mask[i-1])(28-m_shift.step[i-1]); C[i]=((C[i-1]m_shift.step[i-1])|tmp)0x0fffffff; tmp=(D[i-1]m_shift.mask[i-1])(28-m_shift.step[i-1]); D[i]=((D[i-1]m_shift.step[i-1])|tmp)0x0fffffff; m_dwl_K[i]=(C[i]28)|D[i]; m_dwl_K[i]=PermuteTable(m_dwl_K[i],dwlKey_PC_2,48); } } DWORDLONG CDES::ProcessByte(unsigned char *key,BOOL shift){ unsigned char tmp; DWORDLONG byte=0; int i=0; while(i8){ while(*key){ if(byte!=0) byte=8; tmp=*key; if(shift) tmp=1; byte|=tmp; i++; key++; } if(i8) byte=8; i++; } return byte; } DWORDLONG CDES::PermuteTable(DWORDLONG dwlPara,DWOR 基于des算法的rfid安全系统
DLONG* dwlTable,int nDestLen){ int i=0; DWORDLONG tmp=0,moveBit; while(inDestLen){ moveBit=1; if(dwlTable[i]dwlPara){ moveBit=nDestLen-i-1; tmp|=moveBit; } i++; } return tmp; } DWORDLONG CDES::UnPermuteTable(DWORDLONG dwlPara,DWORDLONG* dwlTable,int nDestLen){ DWORDLONG tmp=0; int i=nDestLen-1; while(dwlPara!=0){ if(dwlPara0x01) tmp|=dwlTable[i]; dwlPara=1; i--; } return tmp; } void CDES::PrintTable(DWORDLONG *dwlPara,int col,int row){ int i,j; for(i=0;irow;i++){ printf("\n"); getch(); for(j=0;jcol;j++) PrintBit(dwlPara[i*col+j]); } } void CDES::PrintBit(DWORDLONG bitstream){ char out[76]; int i=0,j=0,space=0; while(bitstream!=0){ if(bitstream0x01) out[i++]='1'; else out[i++]='0'; j++; if(j%8==0){ out[i++]=' '; space++; } bitstream=bitstream1; } out[i]='\0'; strcpy(out,strrev(out)); printf("%s **:%d\n",out,i-space); } void CDES::ConvertTableToMask(DWORDLONG *mask,int max){ int i=0; DWORDLONG nBit=1; while(mask[i]!=0){ nBit=1; nBit=max-mask[i]; mask[i++]=nBit; } } void CDES::Generate_S(void){ int i; int j,m,n; m=n=0; j=1; for(i=0;i512;i++){ dwlData_S[j][m][n]=OS[i]; n=(n+1)%16; if(!n){ m=(m+1)%4; if(!m) j++; } } } unsigned char * CDES::EncryptData(unsigned char *block){ unsigned char *EncrytedData=new unsigned char(15); printf("\nOriginal Data: %s\n",block); m_dwlData=ProcessByte(block,0); // PrintBit(m_dwlData); m_dwlData=PermuteTable(m_dwlData,dwlData_IP,64); EncryptKernel(); // PrintBit(m_dwlData); DWORDLONG bit6=m_dwlData; for(int i=0;i11;i++){ EncrytedData[7-i]=(unsigned char)(bit60x3f)+46; bit6=6; } EncrytedData[11]='\0'; printf("\nAfter Encrypted: %s",EncrytedData); for(i=0;i8;i++){ EncrytedData[7-i]=(unsigned char)(m_dwlData0xff); m_dwlData=8; } EncrytedData[8]='\0'; return EncrytedData; } void CDES::EncryptKernel(void){ int i=1; DWORDLONG L[17],R[17],B[9],EK,PSB; L[0]=m_dwlData32; R[0]=m_dwlData0xffffffff; for(i=1;i=16;i++){ L[i]=R[i-1]; R[i-1]=PermuteTable(R[i-1],dwlData_Expansion,48); //Expansion R EK=R[i-1]^m_dwl_K[i]; //E Permutation PSB=Generate_B(EK,B); //P Permutation R[i]=L[i-1]^PSB; } R[16]=32; m_dwlData=R[16]|L[16]; m_dwlData=PermuteTable(m_dwlData,dwlData_FP,64); } unsigned char* CDES::DescryptData(unsigned char *desData){ int i=1; unsigned char *DescryptedData=new unsigned char(15); DWORDLONG L[17],R[17],B[9],EK,PSB; DWORDLONG dataPara; dataPara=ProcessByte(desData,0); dataPara=PermuteTable(dataPara,dwlData_IP,64); R[16]=dataPara32; L[16]=dataPara0xffffffff; for(i=16;i=1;i--){ R[i-1]=L[i]; L[i]=PermuteTable(L[i],dwlData_Expansion,48); //Expansion L EK=L[i]^m_dwl_K[i]; //E Permutation PSB=Generate_B(EK,B); //P Permutation L[i-1]=R[i]^PSB; } L[0]=32; dataPara=L[0]|R[0]; dataPara=PermuteTable(dataPara,dwlData_FP,64); // PrintBit(dataPara); for(i=0;i8;i++){ DescryptedData[7-i]=(unsigned char)(dataPara0xff); dataPara=8; } DescryptedData[8]='\0'; printf("\nAfter Decrypted: %s\n",DescryptedData); return DescryptedData; } DWORDLONG CDES::Generate_B(DWORDLONG EKPara,DWORDLONG *block){ int i,m,n; DWORDLONG tmp=0; for(i=8;i0;i--){ block[i]=EKPara0x3f; m=(int)(block[i]0x20)4; m|=block[i]0x01; n=(int)(block[i]1)2; block[i]=dwlData_S[i][m][n]; EKPara=6; } for(i=1;i=8;i++){ tmp|=block[i]; tmp=4; } tmp=4; tmp=PermuteTable(tmp,dwlData_P,32); return tmp; } void main(void){ CDES des; des.EncryptKey("12345678"); unsigned char *result=des.EncryptData((unsigned char*)"DemoData"); des.DescryptData(result); }[1]