這個DES源碼,但如何對STRING或FILE加解密呀? |
答題得分者是:wnhoo
|
hua2000
中階會員 發表:102 回覆:200 積分:65 註冊:2006-11-04 發送簡訊給我 |
這個DES源碼,但如何對STRING或FILE加解密呀? 能不能舉幾個具體的例子呀?
或做一個發向fair@army.com
如:對EDIT1中字串加解密或對數據庫中的字串加密!
如:對D:\ddd.dat文件加解密? 源碼如下: (code)
unit DesUnit; interface type
TBits64 = packed array [0..63] of Byte;
TBits4 = packed array [0..3] of Byte;
TBits6 = packed array [0..3] of Byte;
TBits48 = packed array [0..48] of Byte; procedure DES (var Data; const Keys; cLoop: Integer);
//Data: 待加密数据,64字节,每字节代表一位;
//Keys:密钥数据,48*CLoop字节,每字节代表一位,一次迭代用48字节(48位)
//cLoop:迭代次数,标准DES为16。
procedure UNDES (var Data; const Keys; cLoop: Integer);
//Data: 待解密数据,64字节,每字节代表一位;
//Keys:密钥数据,48*CLoop字节,每字节代表一位,一次迭代用48字节(48位)
//cLoop:迭代次数,标准DES为16。
procedure SetBits(const Source; var Dest; cByte: Integer);
//把每字节1位的数据转换为每字节8位的数据,cByte为转换后的字节数
procedure GetBits(const Source; var Dest; cByte: Integer);
//把每字节8位的数据转换为每字节1位的数据,cByte为转换前字节数。
procedure MakeDesKeyData(const Key; var KeyData);
//用DES标准密钥生成方法生成密钥数据。
//Key为密钥,8字节,每字节使用低7位,共使用56位。
//Dest为密钥数据,48*16字节,每字节保存1位。 {
加密:
生成48*16字节密钥数据(KeyData)
以8字节为一组,对每一组:
GetBits(当前组, Data, 8);
Des(Data, KeyData, 16);
SetBits(Data, 当前组, 8);
直到处理完毕 解密:
生成48*16字节密钥数据(KeyData)//与加密时要相同
以8字节为一组,对每一组:
GetBits(当前组, Data, 8);
UnDes(Data, KeyData, 16);
SetBits(Data, 当前组, 8);
直到处理完毕 }
implementation (************************from: http://www.online.ee/~sateks/des-how-to.html****
How to implement the Data Encryption Standard (DES) A step by step tutorial
Version 1.2 by
Matthew Fischer (mfischer@heinous.isca.uiowa.edu) Introduction The Data Encryption Standard (DES) algorithm, adopted by the U.S. government
in 1977, is a block cipher that transforms 64-bit data blocks under a 56-bit
secret key, by means of permutation and substitution. It is officially described
in FIPS PUB 46. The DES algorithm is used for many applications within the
government and in the private sector. This is a tutorial designed to be clear and compact, and to provide a newcomer
to the DES with all the necessary information to implement it himself, without
having to track down printed works or wade through C source code. I welcome
any comments. Here's how to do it, step by step: 1 - Process the key
1.1 Get a 64-bit key from the user. (Every 8th bit is considered a parity bit.
For a key to have correct parity, each byte should contain an odd number
of "1" bits.) 1.2 Calculate the key schedule. 1.2.1 Perform the following permutation on the 64-bit key. (The parity bits are
discarded, reducing the key to 56 bits. Bit 1 of the permuted block is bit
57 of the original key, bit 2 is bit 49, and so on with bit 56 being bit 4
of the original key.) Permuted Choice 1 (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 1.2.2 Split the permuted key into two halves. The first 28 bits are called C[0]
and the last 28 bits are called D[0]. 1.2.3 Calculate the 16 subkeys. Start with i = 1. 1.2.3.1 Perform one or two circular left shifts on both C[i-1] and D[i-1] to get
C[i] and D[i], respectively. The number of shifts per iteration are
given in the table below. Iteration # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Left Shifts 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1.2.3.2 Permute the concatenation C[i]D[i] as indicated below. This will yield
K[i], which is 48 bits long. Permuted Choice 2 (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 1.2.3.3 Loop back to 1.2.3.1 until K[16] has been calculated. 2 - Process a 64-bit data block
2.1 Get a 64-bit data block. If the block is shorter than 64 bits, it should be
padded as appropriate for the application. 2.2 Perform the following permutation on the data block. Initial Permutation (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 2.3 Split the block into two halves. The first 32 bits are called L[0], and the
last 32 bits are called R[0]. 2.4 Apply the 16 subkeys to the data block. Start with i = 1. 2.4.1 Expand the 32-bit R[i-1] into 48 bits according to the bit-selection
function below. Expansion (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 1 2.4.2 Exclusive-or E(R[i-1]) with K[i]. 2.4.3 Break E(R[i-1]) xor K[i] into eight 6-bit blocks. Bits 1-6 are B[1], bits
7-12 are B[2], and so on with bits 43-48 being B[8]. 2.4.4 Substitute the values found in the S-boxes for all B[j]. Start with j = 1.
All values in the S-boxes should be considered 4 bits wide. 2.4.4.1 Take the 1st and 6th bits of B[j] together as a 2-bit value (call it m)
indicating the row in S[j] to look in for the substitution. 2.4.4.2 Take the 2nd through 5th bits of B[j] together as a 4-bit value (call it
n) indicating the column in S[j] to find the substitution. 2.4.4.3 Replace B[j] with S[j][m][n]. Substitution Box 1 ( S[1]) 14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7
0 15 7 4 14 2 13 1 10 6 12 11 9 5 3 8
4 1 14 8 13 6 2 11 15 12 9 7 3 10 5 0
15 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13
S[2] 15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10
3 13 4 7 15 2 8 14 12 0 1 10 6 9 11 5
0 14 7 11 10 4 13 1 5 8 12 6 9 3 2 15
13 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9
S[3] 10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8
13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1
13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7
1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12
S[4] 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15
13 8 11 5 6 15 0 3 4 7 2 12 1 10 14 9
10 6 9 0 12 11 7 13 15 1 3 14 5 2 8 4
3 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14
S[5] 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9
14 11 2 12 4 7 13 1 5 0 15 10 3 9 8 6
4 2 1 11 10 13 7 8 15 9 12 5 6 3 0 14
11 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3
S[6] 12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11
10 15 4 2 7 12 9 5 6 1 13 14 0 11 3 8
9 14 15 5 2 8 12 3 7 0 4 10 1 13 11 6
4 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13
S[7] 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1
13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6
1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2
6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12
S[8] 13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7
1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2
7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8
2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11 2.4.4.4 Loop back to 2.4.4.1 until all 8 blocks have been replaced. 2.4.5 Permute the concatenation of B[1] through B[8] as indicated below. Permutation 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 2.4.6 Exclusive-or the resulting value with L[i-1]. Thus, all together, your
R[i] = L[i-1] xor P(S[1](B[1])...S[8](B[8])), where B[j] is a 6-bit block
of E(R[i-1]) xor K[i]. (The function for R[i] is written as, R[i] = L[i-1]
xor f(R[i-1], K[i]).) 2.4.7 L[i] = R[i-1]. 2.4.8 Loop back to 2.4.1 until K[16] has been applied. 2.5 Perform the following permutation on the block R[16]L[16]. Final Permutation (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 This has been a description of how to use the DES algorithm to encrypt one
64-bit block. To decrypt, use the same process, but just use the keys K[i] in
reverse order. That is, instead of applying K[1] for the first iteration, apply
K[16], and then K[15] for the second, on down to K[1]. 3 - Summaries
Key schedule: C[0]D[0] = PC1(key)
for 1 <= i <= 16
C[i] = LS[i](C[i-1])
D[i] = LS[i](D[i-1])
K[i] = PC2(C[i]D[i]) Encipherment:
L[0]R[0] = IP(plain block)
for 1 <= i <= 16
L[i] = R[i-1]
R[i] = L[i-1] xor f(R[i-1], K[i])
cipher block = FP(R[16]L[16]) Decipherment:
R[16]L[16] = IP(cipher block)
for 1 <= i <= 16
R[i-1] = L[i]
L[i-1] = R[i] xor f(L[i], K[i]) plain block = FP(L[0]R[0]) 4 - Complements
To encrypt or decrypt more than 64 bits there are four official modes (defined
in FIPS PUB 81). One is to go through the above-described process for each block
in succession. This is called Electronic Codebook (ECB) mode. A stronger method
is to exclusive-or each plaintext block with the preceding ciphertext block
prior to encryption. (The first block is exclusive-or'ed with a secret 64-bit
initialization vector (IV).) This is called Cipher Block Chaining (CBC) mode.
The other two modes are Output Feedback (OFB) and Cipher Feedback (CFB). When it comes to padding the data block, there are several options. One is to
simply append zeros. Two suggested by FIPS PUB 81 are, if the data is binary
data, fill up the block with bits that are the opposite of the last bit of data,
or, if the data is ASCII data, fill up the block with random bytes and put the
ASCII character for the number of pad bytes in the last byte of the block.
Another technique is to pad the block with random bytes and in the last 3 bits
store the original number of data bytes. The DES algorithm can also be used to calculate checksums up to 64 bits long
(see FIPS PUB 113). If the number of data bits to be checksummed is not a
multiple of 64, the last data block should be padded with zeros. If the data is
ASCII data, the first bit of each byte should be set to 0. The data is then
encrypted in CBC mode with IV = 0. The leftmost n bits (where 16 <= n <= 64, and
n is a multiple of 8) of the final ciphertext block are an n-bit checksum. ***************************************************************************) const tblIP: packed array [0..63] of Byte =
(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); tblUnIP: packed array [0..63] of Byte =
(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); tblE: packed array [0..47] of Byte =
(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,1); tblS: packed array [0..7, 0..3, 0..15] of Byte =
(((14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7),
(0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8),
(4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0),
(15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13)),
((15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10),
(3,13,4,7,15,2,8,15,12,0,1,10,6,9,11,5),
(0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15),
(13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9)),
((10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8),
(13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1),
(13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7),
(1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12)),
((7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15),
(13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9),
(10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4),
(3,15,0,6,10,10,13,8,9,4,5,11,12,7,2,14)),
((2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9),
(14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6),
(4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14),
(11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3)),
((12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11),
(10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8),
(9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6),
(4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13)),
((4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1),
(13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6),
(1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2),
(6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12)),
((13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7),
(1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2),
(7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8),
(2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11))); tblP: packed array [0..31] of Byte =
(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); procedure DES (var Data; const Keys; cLoop: Integer);
var
Bits: packed array [0..1,0..1,0..31] of Byte; //0..127
Bit48s: packed array [0..47] of Byte; //128..175
KeysAddr: Cardinal; //176..179
LoopCount: Cardinal; //180..183
DataAddr: Cardinal; //184..187
Current: Cardinal; //188..191
Next: Cardinal; //192..195
asm
PUSHAD;
MOV DWORD PTR KeysAddr, EDX; //KeysAddr
MOV DWORD PTR LoopCount, ECX; //LoopCount
MOV DWORD PTR DataAddr, EAX; //DataAddr
//IP
XOR EDI, EDI;
LEA EBX, tblIP;
LEA ESI, BITS;
XOR ECX, ECX;
@IP1:
MOV CL, [EBX][EDI];
DEC CL;
MOV DL, [EAX][ECX];
MOV [ESI][EDI],DL;
INC EDI;
CMP EDI, 64;
JL @IP1; MOV DWORD PTR Current, 64; //Current
MOV DWORD PTR Next, 0; //Next
// for i := 1 to cLoop do
// begin
MOV ECX, LoopCount;//Loop;
@LOOPKEY1:
PUSH ECX;
XOR DWORD PTR Current, 64;//Current
XOR DWORD PTR Next, 64; //Next //L(i)= R(i-1)
MOV ECX, 8;
LEA ESI, BITS
MOV EDI, ESI;
ADD ESI, Current;//Current
ADD EDI, Next;//Next
ADD ESI, 32;
REP MOVSD; //R(i-1) => 48
LEA ESI, Bit48s;
LEA EBX, tblE;
LEA EAX, Bits;
ADD EAX, Current;
ADD EAX, 32;
XOR EDI, EDI;
XOR ECX, ECX;
@EXT1:
MOV CL, [EBX][EDI];
DEC CL;
MOV DL, [EAX][ECX];
MOV [ESI][EDI],DL;
INC EDI;
CMP EDI, 48;
JL @EXT1; //R(i-1) ^ Key(i-1)
XOR EDI, EDI;
MOV EBX, KeysAddr;
@USEK1:
MOV EAX, [EBX][EDI];
XOR [ESI][EDI], EAX;
ADD EDI, 4;
CMP EDI, 48;
JL @USEK1;
ADD EBX, 48;
MOV KeysAddr, EBX; //S(Ri-1)
LEA EDI, BITS;
ADD EDI, Current;
ADD EDI, 32;
LEA EBX, tblS;
MOV ECX,4
@S1:
XOR EDX, EDX;
XOR EAX, EAX;
MOV DL, [ESI];
SHL DL, 1;
OR DL, [ESI][5];
SHL EDX, CL;
MOV AL,[ESI][1];
SHL AL, 1;
OR AL, [ESI][2];
SHL AL, 1;
OR AL, [ESI][3];
SHL AL, 1;
OR AL, [ESI][4];
ADD EDX, EAX;
XOR EAX,EAX;
MOV AL, [EBX][EDX]
ROR EAX, CL;
ROL EAX, 1;
MOV [EDI], AL;
ROL EAX, 1;
AND AL, 1;
MOV [EDI][1], AL;
ROL EAX, 1;
AND EAX, 1;
MOV [EDI][2], AL;
ROL EAX, 1;
AND AL,1;
MOV [EDI][3], AL;
ADD ESI, 6;
ADD EDI, 4;
INC CH;
CMP CH, 8;
JL @S1; //P(Ri)
LEA EBX, tblP;
LEA ESI, BITS;
ADD ESI, 32;
MOV EDI, ESI;
ADD ESI, CURRENT;
ADD EDI, NEXT;
XOR EAX,EAX;
XOR ECX,ECX;
@P1:
MOV AL, [EBX][ECX];
DEC AL
MOV DL, [ESI][EAX];
MOV [EDI][ECX],DL;
INC ECX;
CMP ECX, 32
JL @P1; //R(i) = Li-1 ^ Ri-1
XOR ECX, ECX
SUB ESI, 32;
@L1:
MOV EAX, [ESI][ECX];
XOR [EDI][ECX], EAX;
ADD ECX, 4;
CMP ECX, 32;
JL @L1;
// end;
POP ECX;
//LOOP @LOOPKEY1;
DEC ECX;
JNZ @LOOPKEY1; // Left = R16
LEA ESI, BITS;
MOV EDI, ESI;
ADD ESI, NEXT;
ADD EDI, CURRENT;
ADD ESI, 32
MOV ECX, 8;
REP MOVSD;
// R=L16
LEA ESI, BITS;
MOV EDI, ESI;
ADD ESI, NEXT;
ADD EDI, CURRENT;
ADD EDI, 32
MOV ECX, 8;
REP MOVSD; XOR NEXT, 64; // UnIP
LEA ESI, BITS;
ADD ESI, NEXT;
LEA EBX, tblUnIP;
MOV EDI, DataAddr;
XOR EAX, EAX;
XOR ECX, ECX;
@UNIP1:
MOV AL, [EBX][ECX];
DEC AL;
MOV DL, [ESI][EAX];
MOV [EDI][ECX], DL;
INC ECX;
CMP ECX, 64;
JL @UNIP1; POPAD;
end; procedure UNDES (var Data; const Keys; cLoop: Integer);
var
Bits: packed array [0..1,0..1,0..31] of Byte; //0..127
Bit48s: packed array [0..47] of Byte; //128..175
KeysAddr: Cardinal; //176..179
LoopCount: Cardinal; //180..183
DataAddr: Cardinal; //184..187
Current: Cardinal; //188..191
Next: Cardinal; //192..195
asm PUSHAD;
MOV DWORD PTR LoopCount, ECX; //LoopCount
IMUL ECX, 48;
ADD EDX, ECX;
MOV DWORD PTR KeysAddr, EDX; //KeysAddr
MOV DWORD PTR DataAddr, EAX; //DataAddr
// IP
XOR EDI, EDI;
LEA EBX, tblIP;
LEA ESI, BITS
XOR ECX, ECX;
@IP1:
MOV CL, [EBX][EDI];
DEC CL;
MOV DL, [EAX][ECX];
MOV [ESI][EDI],DL;
INC EDI;
CMP EDI, 64;
JL @IP1; //R16= Left
LEA ESI, BITS;
MOV EDI, ESI;
ADD EDI, 64;
ADD ESI, 32
MOV ECX, 8;
REP MOVSD;
//L16=Right
LEA ESI, BITS;
MOV EDI, ESI;
ADD EDI, 64;
ADD EDI, 32
MOV ECX, 8;
REP MOVSD; MOV DWORD PTR Current, 0; //Current
MOV DWORD PTR Next, 64; //Next
//for i := 16 downto 1 do
//begin
MOV ECX, LoopCount;//Loop;
@Loop1:
PUSH ECX;
XOR DWORD PTR Current, 64;//Current
XOR DWORD PTR Next, 64; //Next //R(i-1) = L(i)
MOV ECX, 8;
LEA ESI, BITS;
MOV EDI, ESI;
ADD ESI, Current;//Current
ADD EDI, Next;//Next
ADD EDI, 32;
REP MOVSD; //48b(Li)
LEA ESI, Bit48s;
LEA EBX, tblE;
LEA EAX, Bits;
ADD EAX, Current;
XOR EDI, EDI;
XOR ECX, ECX;
@EXT1:
MOV CL, [EBX][EDI];
DEC CL;
MOV DL, [EAX][ECX];
MOV [ESI][EDI],DL;
INC EDI;
CMP EDI, 48;
JL @EXT1; //Li ^ Key i-1
XOR EDI, EDI;
MOV EBX, KeysAddr;
SUB EBX, 48;
@USEK1:
MOV EAX, [EBX][EDI];
XOR [ESI][EDI], EAX;
ADD EDI, 4;
CMP EDI, 48;
JL @USEK1;
MOV KeysAddr, EBX; //S(Li)
LEA EDI, BITS;
ADD EDI, Current;
LEA EBX, tblS;
MOV ECX,4
@S1:
XOR EDX, EDX;
XOR EAX, EAX;
MOV DL, [ESI];
SHL DL, 1;
OR DL, [ESI][5];
SHL EDX, CL;
MOV AL,[ESI][1];
SHL AL, 1;
OR AL, [ESI][2];
SHL AL, 1;
OR AL, [ESI][3];
SHL AL, 1;
OR AL, [ESI][4];
ADD EDX, EAX;
XOR EAX,EAX;
MOV AL, [EBX][EDX]
ROR EAX, CL;
ROL EAX, 1;
MOV [EDI], AL;
ROL EAX, 1;
AND AL, 1;
MOV [EDI][1], AL;
ROL EAX, 1;
AND EAX, 1;
MOV [EDI][2], AL;
ROL EAX, 1;
AND AL,1;
MOV [EDI][3], AL;
ADD ESI, 6;
ADD EDI, 4;
INC CH;
CMP CH, 8;
JL @S1; //P(Li)
LEA EBX, tblP;
LEA ESI, BITS;
MOV EDI, ESI;
ADD ESI, CURRENT;
ADD EDI, NEXT;
XOR EAX,EAX;
XOR ECX,ECX;
@P1:
MOV AL, [EBX][ECX];
DEC AL;
MOV DL, [ESI][EAX];
MOV [EDI][ECX],DL;
INC ECX;
CMP ECX, 32
JL @P1; //L(i-1) = R(i) ^ Li
XOR ECX, ECX
ADD ESI, 32;
@L1:
MOV EAX, [ESI][ECX];
XOR [EDI][ECX], EAX;
ADD ECX, 4;
CMP ECX, 32;
JL @L1;
//end;
POP ECX;
DEC ECX;
JNZ @LOOP1; //UnIP
LEA ESI, BITS;
ADD ESI, NEXT;
LEA EBX, tblUnIP;
MOV EDI, DataAddr;
XOR EAX, EAX;
XOR ECX, ECX;
@UNIP1:
MOV AL, [EBX][ECX];
DEC AL;
MOV DL, [ESI][EAX];
MOV [EDI][ECX], DL;
INC ECX;
CMP ECX, 64;
JL @UNIP1; POPAD;
end; procedure GetBits(const Source; var Dest; cByte: Integer);
asm
PUSH EBX;
PUSH EDI;
PUSH ESI;
XOR EDI, EDI;
XOR ESI, ESI;
XOR EBX,EBX
@LOOP1:
MOV BL, [EAX][ESI];
ROR EBX,7;
AND BL,1;
MOV [EDX][EDI], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 1], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 2], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 3], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 4], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 5], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 6], BL;
ROL EBX,1;
AND BL,1;
MOV [EDX][EDI 7], BL;
ADD EDI, 8;
INC ESI;
LOOP @LOOP1
POP ESI;
POP EDI;
POP EBX;
end; procedure SetBits(const Source; var Dest; cByte: Integer);
asm
PUSH EBX;
PUSH EDI;
PUSH ESI; XOR EDI, EDI;
XOR ESI, ESI;
@LOOP1:
MOV BL, [EAX][ESI];
SHL BL, 1;
OR BL, [EAX][ESI 1];
SHL BL, 1;
OR BL, [EAX][ESI 2];
SHL BL, 1;
OR BL, [EAX][ESI 3];
SHL BL, 1;
OR BL, [EAX][ESI 4];
SHL BL, 1;
OR BL, [EAX][ESI 5];
SHL BL, 1;
OR BL, [EAX][ESI 6];
SHL BL, 1;
OR BL, [EAX][ESI 7];
MOV [EDX][EDI], BL
ADD ESI, 8;
INC EDI;
LOOP @LOOP1 POP ESI;
POP EDI;
POP EBX;
end; procedure MakeDesKeyData(const Key; var KeyData); assembler;
const
Idx56In64: packed array [0..55] of Byte =
(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 );
Idx48In56: packed array[0..47] of Byte =
(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);
KeyShift: packed array [0..15] of Integer =
(1,1,2,2,
2,2,2,2,
1,2,2,2,
2,2,2,1);
var
Key64: packed array [0..63] of Byte;
Key56: packed array [0..55] of Byte;
KeyTemp: packed array [0..55] of Byte;
KeyDataAdr: Cardinal;
asm
// Get64Bits
PUSH ESI;
PUSH EDI;
PUSH EBX;
MOV KeyDataAdr, EDX;
LEA EDX, Key64;
MOV ECX, 8;
CALL GetBits;
//64 Bits ==> 56 Bits
LEA EDI, Key56;
LEA ESI, Key64;
LEA EBX, Idx56In64;
XOR EAX, EAX;
XOR ECX, ECX;
@1:
MOV AL, [EBX][ESI];
DEC AL;
MOV CL, [ESI][EAX];
MOV [EDI][ESI], CL;
INC CH;
CMP CH, 56;
JL @1; XOR EDX,EDX;
@2:
// L <<< move[i];
LEA ESI,Key56;
LEA EDI,KeyTemp;
XOR ECX,ECX;
LEA EBX,KeyShift;
MOV BYTE PTR CL, [EDX][EBX];
REP MOVSB; LEA EDI, Key56;
MOV ESI, EDI;
MOV CL, [EBX][EDX];
ADD ESI, ECX;
MOV ECX, 28;
SUB CL, [EBX][EDX];
REP MOVSB; LEA ESI, KeyTemp;
MOV CL, [EBX][EDX];
REP MOVSB; // R <<< move[i];
LEA ESI,Key56[28];
LEA EDI,KeyTemp;
XOR ECX,ECX;
LEA EBX,KeyShift;
MOV BYTE PTR CL, [EDX][EBX];
REP MOVSB; LEA EDI, Key56[28];
MOV ESI, EDI;
MOV CL, [EBX][EDX];
ADD ESI, ECX;
MOV ECX, 28;
SUB CL, [EBX][EDX];
REP MOVSB; LEA ESI, KeyTemp;
MOV CL, [EBX][EDX];
REP MOVSB; // Get48Bits
MOV EAX, EDX;
IMUL EAX, 48;
MOV EDI, KeyDataAdr;
ADD EDI, EAX;
LEA ESI, Key56;
LEA EBX, Idx48In56;
XOR EAX, EAX;
XOR ECX, ECX;
@3:
MOV AL, [EBX][ESI];
DEC AL;
MOV CL, [ESI][EAX];
MOV [EDI][ESI], CL;
INC CH;
CMP CH, 56;
JL @3; INC EDX;
CMP EDX, 16;
JL @2;
end; end.
(/code)
|
wnhoo
高階會員 發表:75 回覆:443 積分:198 註冊:2003-04-22 發送簡訊給我 |
procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
s1:array[1..100] of integer;
begin
s1[1]:=1;
s1[2]:=3;
s1[3]:=2;
s:='abcdefg';
GetBits(s1, s, 8);
Des(s, 'sss', 16);
SetBits(s, s1, 8);
showmessage(s);
end; 风花雪月 e梦情缘
------
风花雪月 e梦情缘 |
hua2000
中階會員 發表:102 回覆:200 積分:65 註冊:2006-11-04 發送簡訊給我 |
|
wnhoo
高階會員 發表:75 回覆:443 積分:198 註冊:2003-04-22 發送簡訊給我 |
|
hua2000
中階會員 發表:102 回覆:200 積分:65 註冊:2006-11-04 發送簡訊給我 |
unit DesUnit; interface type TBits64 = packed array [0..63] of Byte; TBits4 = packed array [0..3] of Byte; TBits6 = packed array [0..3] of Byte; TBits48 = packed array [0..48] of Byte; procedure DES (var Data; const Keys; cLoop: Integer); //Data: 待加密数据,64字节,每字节代表一位; //Keys:密钥数据,48*CLoop字节,每字节代表一位,一次迭代用48字节(48位) //cLoop:迭代次数,标准DES为16。 procedure UNDES (var Data; const Keys; cLoop: Integer); //Data: 待解密数据,64字节,每字节代表一位; //Keys:密钥数据,48*CLoop字节,每字节代表一位,一次迭代用48字节(48位) //cLoop:迭代次数,标准DES为16。 procedure SetBits(const Source; var Dest; cByte: Integer); //把每字节1位的数据转换为每字节8位的数据,cByte为转换后的字节数 procedure GetBits(const Source; var Dest; cByte: Integer); //把每字节8位的数据转换为每字节1位的数据,cByte为转换前字节数。 procedure MakeDesKeyData(const Key; var KeyData); //用DES标准密钥生成方法生成密钥数据。 //Key为密钥,8字节,每字节使用低7位,共使用56位。 //Dest为密钥数据,48*16字节,每字节保存1位。 { 加密: 生成48*16字节密钥数据(KeyData) 以8字节为一组,对每一组: GetBits(当前组, Data, 8); Des(Data, KeyData, 16); SetBits(Data, 当前组, 8); 直到处理完毕 解密: 生成48*16字节密钥数据(KeyData)//与加密时要相同 以8字节为一组,对每一组: GetBits(当前组, Data, 8); UnDes(Data, KeyData, 16); SetBits(Data, 当前组, 8); 直到处理完毕 } implementation (************************from: http://www.online.ee/~sateks/des-how-to.html**** How to implement the Data Encryption Standard (DES) A step by step tutorial Version 1.2 by Matthew Fischer (mfischer@heinous.isca.uiowa.edu) Introduction The Data Encryption Standard (DES) algorithm, adopted by the U.S. government in 1977, is a block cipher that transforms 64-bit data blocks under a 56-bit secret key, by means of permutation and substitution. It is officially described in FIPS PUB 46. The DES algorithm is used for many applications within the government and in the private sector. This is a tutorial designed to be clear and compact, and to provide a newcomer to the DES with all the necessary information to implement it himself, without having to track down printed works or wade through C source code. I welcome any comments. Here's how to do it, step by step: 1 - Process the key 1.1 Get a 64-bit key from the user. (Every 8th bit is considered a parity bit. For a key to have correct parity, each byte should contain an odd number of "1" bits.) 1.2 Calculate the key schedule. 1.2.1 Perform the following permutation on the 64-bit key. (The parity bits are discarded, reducing the key to 56 bits. Bit 1 of the permuted block is bit 57 of the original key, bit 2 is bit 49, and so on with bit 56 being bit 4 of the original key.) Permuted Choice 1 (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 1.2.2 Split the permuted key into two halves. The first 28 bits are called C[0] and the last 28 bits are called D[0]. 1.2.3 Calculate the 16 subkeys. Start with i = 1. 1.2.3.1 Perform one or two circular left shifts on both C[i-1] and D[i-1] to get C[i] and D[i], respectively. The number of shifts per iteration are given in the table below. Iteration # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Left Shifts 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1.2.3.2 Permute the concatenation C[i]D[i] as indicated below. This will yield K[i], which is 48 bits long. Permuted Choice 2 (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 1.2.3.3 Loop back to 1.2.3.1 until K[16] has been calculated. 2 - Process a 64-bit data block 2.1 Get a 64-bit data block. If the block is shorter than 64 bits, it should be padded as appropriate for the application. 2.2 Perform the following permutation on the data block. Initial Permutation (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 2.3 Split the block into two halves. The first 32 bits are called L[0], and the last 32 bits are called R[0]. 2.4 Apply the 16 subkeys to the data block. Start with i = 1. 2.4.1 Expand the 32-bit R[i-1] into 48 bits according to the bit-selection function below. Expansion (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 1 2.4.2 Exclusive-or E(R[i-1]) with K[i]. 2.4.3 Break E(R[i-1]) xor K[i] into eight 6-bit blocks. Bits 1-6 are B[1], bits 7-12 are B[2], and so on with bits 43-48 being B[8]. 2.4.4 Substitute the values found in the S-boxes for all B[j]. Start with j = 1. All values in the S-boxes should be considered 4 bits wide. 2.4.4.1 Take the 1st and 6th bits of B[j] together as a 2-bit value (call it m) indicating the row in S[j] to look in for the substitution. 2.4.4.2 Take the 2nd through 5th bits of B[j] together as a 4-bit value (call it n) indicating the column in S[j] to find the substitution. 2.4.4.3 Replace B[j] with S[j][m][n]. Substitution Box 1 ( S[1]) 14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7 0 15 7 4 14 2 13 1 10 6 12 11 9 5 3 8 4 1 14 8 13 6 2 11 15 12 9 7 3 10 5 0 15 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13 S[2] 15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10 3 13 4 7 15 2 8 14 12 0 1 10 6 9 11 5 0 14 7 11 10 4 13 1 5 8 12 6 9 3 2 15 13 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9 S[3] 10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8 13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1 13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7 1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12 S[4] 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15 13 8 11 5 6 15 0 3 4 7 2 12 1 10 14 9 10 6 9 0 12 11 7 13 15 1 3 14 5 2 8 4 3 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14 S[5] 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9 14 11 2 12 4 7 13 1 5 0 15 10 3 9 8 6 4 2 1 11 10 13 7 8 15 9 12 5 6 3 0 14 11 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3 S[6] 12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11 10 15 4 2 7 12 9 5 6 1 13 14 0 11 3 8 9 14 15 5 2 8 12 3 7 0 4 10 1 13 11 6 4 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13 S[7] 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1 13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6 1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2 6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12 S[8] 13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7 1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2 7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8 2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11 2.4.4.4 Loop back to 2.4.4.1 until all 8 blocks have been replaced. 2.4.5 Permute the concatenation of B[1] through B[8] as indicated below. Permutation 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 2.4.6 Exclusive-or the resulting value with L[i-1]. Thus, all together, your R[i] = L[i-1] xor P(S[1](B[1])...S[8](B[8])), where B[j] is a 6-bit block of E(R[i-1]) xor K[i]. (The function for R[i] is written as, R[i] = L[i-1] xor f(R[i-1], K[i]).) 2.4.7 L[i] = R[i-1]. 2.4.8 Loop back to 2.4.1 until K[16] has been applied. 2.5 Perform the following permutation on the block R[16]L[16]. Final Permutation (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 This has been a description of how to use the DES algorithm to encrypt one 64-bit block. To decrypt, use the same process, but just use the keys K[i] in reverse order. That is, instead of applying K[1] for the first iteration, apply K[16], and then K[15] for the second, on down to K[1]. 3 - Summaries Key schedule: C[0]D[0] = PC1(key) for 1 <= i <= 16 C[i] = LS[i](C[i-1]) D[i] = LS[i](D[i-1]) K[i] = PC2(C[i]D[i]) Encipherment: L[0]R[0] = IP(plain block) for 1 <= i <= 16 L[i] = R[i-1] R[i] = L[i-1] xor f(R[i-1], K[i]) cipher block = FP(R[16]L[16]) Decipherment: R[16]L[16] = IP(cipher block) for 1 <= i <= 16 R[i-1] = L[i] L[i-1] = R[i] xor f(L[i], K[i]) plain block = FP(L[0]R[0]) 4 - Complements To encrypt or decrypt more than 64 bits there are four official modes (defined in FIPS PUB 81). One is to go through the above-described process for each block in succession. This is called Electronic Codebook (ECB) mode. A stronger method is to exclusive-or each plaintext block with the preceding ciphertext block prior to encryption. (The first block is exclusive-or'ed with a secret 64-bit initialization vector (IV).) This is called Cipher Block Chaining (CBC) mode. The other two modes are Output Feedback (OFB) and Cipher Feedback (CFB). When it comes to padding the data block, there are several options. One is to simply append zeros. Two suggested by FIPS PUB 81 are, if the data is binary data, fill up the block with bits that are the opposite of the last bit of data, or, if the data is ASCII data, fill up the block with random bytes and put the ASCII character for the number of pad bytes in the last byte of the block. Another technique is to pad the block with random bytes and in the last 3 bits store the original number of data bytes. The DES algorithm can also be used to calculate checksums up to 64 bits long (see FIPS PUB 113). If the number of data bits to be checksummed is not a multiple of 64, the last data block should be padded with zeros. If the data is ASCII data, the first bit of each byte should be set to 0. The data is then encrypted in CBC mode with IV = 0. The leftmost n bits (where 16 <= n <= 64, and n is a multiple of 8) of the final ciphertext block are an n-bit checksum. ***************************************************************************) const tblIP: packed array [0..63] of Byte = (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); tblUnIP: packed array [0..63] of Byte = (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); tblE: packed array [0..47] of Byte = (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,1); tblS: packed array [0..7, 0..3, 0..15] of Byte = (((14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7), (0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8), (4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0), (15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13)), ((15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10), (3,13,4,7,15,2,8,15,12,0,1,10,6,9,11,5), (0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15), (13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9)), ((10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8), (13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1), (13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7), (1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12)), ((7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15), (13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9), (10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4), (3,15,0,6,10,10,13,8,9,4,5,11,12,7,2,14)), ((2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9), (14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6), (4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14), (11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3)), ((12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11), (10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8), (9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6), (4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13)), ((4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1), (13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6), (1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2), (6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12)), ((13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7), (1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2), (7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8), (2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11))); tblP: packed array [0..31] of Byte = (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); procedure DES (var Data; const Keys; cLoop: Integer); var Bits: packed array [0..1,0..1,0..31] of Byte; //0..127 Bit48s: packed array [0..47] of Byte; //128..175 KeysAddr: Cardinal; //176..179 LoopCount: Cardinal; //180..183 DataAddr: Cardinal; //184..187 Current: Cardinal; //188..191 Next: Cardinal; //192..195 asm PUSHAD; MOV DWORD PTR KeysAddr, EDX; //KeysAddr MOV DWORD PTR LoopCount, ECX; //LoopCount MOV DWORD PTR DataAddr, EAX; //DataAddr //IP XOR EDI, EDI; LEA EBX, tblIP; LEA ESI, BITS; XOR ECX, ECX; @IP1: MOV CL, [EBX][EDI]; DEC CL; MOV DL, [EAX][ECX]; MOV [ESI][EDI],DL; INC EDI; CMP EDI, 64; JL @IP1; MOV DWORD PTR Current, 64; //Current MOV DWORD PTR Next, 0; //Next // for i := 1 to cLoop do // begin MOV ECX, LoopCount;//Loop; @LOOPKEY1: PUSH ECX; XOR DWORD PTR Current, 64;//Current XOR DWORD PTR Next, 64; //Next //L(i)= R(i-1) MOV ECX, 8; LEA ESI, BITS MOV EDI, ESI; ADD ESI, Current;//Current ADD EDI, Next;//Next ADD ESI, 32; REP MOVSD; //R(i-1) => 48 LEA ESI, Bit48s; LEA EBX, tblE; LEA EAX, Bits; ADD EAX, Current; ADD EAX, 32; XOR EDI, EDI; XOR ECX, ECX; @EXT1: MOV CL, [EBX][EDI]; DEC CL; MOV DL, [EAX][ECX]; MOV [ESI][EDI],DL; INC EDI; CMP EDI, 48; JL @EXT1; //R(i-1) ^ Key(i-1) XOR EDI, EDI; MOV EBX, KeysAddr; @USEK1: MOV EAX, [EBX][EDI]; XOR [ESI][EDI], EAX; ADD EDI, 4; CMP EDI, 48; JL @USEK1; ADD EBX, 48; MOV KeysAddr, EBX; //S(Ri-1) LEA EDI, BITS; ADD EDI, Current; ADD EDI, 32; LEA EBX, tblS; MOV ECX,4 @S1: XOR EDX, EDX; XOR EAX, EAX; MOV DL, [ESI]; SHL DL, 1; OR DL, [ESI][5]; SHL EDX, CL; MOV AL,[ESI][1]; SHL AL, 1; OR AL, [ESI][2]; SHL AL, 1; OR AL, [ESI][3]; SHL AL, 1; OR AL, [ESI][4]; ADD EDX, EAX; XOR EAX,EAX; MOV AL, [EBX][EDX] ROR EAX, CL; ROL EAX, 1; MOV [EDI], AL; ROL EAX, 1; AND AL, 1; MOV [EDI][1], AL; ROL EAX, 1; AND EAX, 1; MOV [EDI][2], AL; ROL EAX, 1; AND AL,1; MOV [EDI][3], AL; ADD ESI, 6; ADD EDI, 4; INC CH; CMP CH, 8; JL @S1; //P(Ri) LEA EBX, tblP; LEA ESI, BITS; ADD ESI, 32; MOV EDI, ESI; ADD ESI, CURRENT; ADD EDI, NEXT; XOR EAX,EAX; XOR ECX,ECX; @P1: MOV AL, [EBX][ECX]; DEC AL MOV DL, [ESI][EAX]; MOV [EDI][ECX],DL; INC ECX; CMP ECX, 32 JL @P1; //R(i) = Li-1 ^ Ri-1 XOR ECX, ECX SUB ESI, 32; @L1: MOV EAX, [ESI][ECX]; XOR [EDI][ECX], EAX; ADD ECX, 4; CMP ECX, 32; JL @L1; // end; POP ECX; //LOOP @LOOPKEY1; DEC ECX; JNZ @LOOPKEY1; // Left = R16 LEA ESI, BITS; MOV EDI, ESI; ADD ESI, NEXT; ADD EDI, CURRENT; ADD ESI, 32 MOV ECX, 8; REP MOVSD; // R=L16 LEA ESI, BITS; MOV EDI, ESI; ADD ESI, NEXT; ADD EDI, CURRENT; ADD EDI, 32 MOV ECX, 8; REP MOVSD; XOR NEXT, 64; // UnIP LEA ESI, BITS; ADD ESI, NEXT; LEA EBX, tblUnIP; MOV EDI, DataAddr; XOR EAX, EAX; XOR ECX, ECX; @UNIP1: MOV AL, [EBX][ECX]; DEC AL; MOV DL, [ESI][EAX]; MOV [EDI][ECX], DL; INC ECX; CMP ECX, 64; JL @UNIP1; POPAD; end; procedure UNDES (var Data; const Keys; cLoop: Integer); var Bits: packed array [0..1,0..1,0..31] of Byte; //0..127 Bit48s: packed array [0..47] of Byte; //128..175 KeysAddr: Cardinal; //176..179 LoopCount: Cardinal; //180..183 DataAddr: Cardinal; //184..187 Current: Cardinal; //188..191 Next: Cardinal; //192..195 asm PUSHAD; MOV DWORD PTR LoopCount, ECX; //LoopCount IMUL ECX, 48; ADD EDX, ECX; MOV DWORD PTR KeysAddr, EDX; //KeysAddr MOV DWORD PTR DataAddr, EAX; //DataAddr // IP XOR EDI, EDI; LEA EBX, tblIP; LEA ESI, BITS XOR ECX, ECX; @IP1: MOV CL, [EBX][EDI]; DEC CL; MOV DL, [EAX][ECX]; MOV [ESI][EDI],DL; INC EDI; CMP EDI, 64; JL @IP1; //R16= Left LEA ESI, BITS; MOV EDI, ESI; ADD EDI, 64; ADD ESI, 32 MOV ECX, 8; REP MOVSD; //L16=Right LEA ESI, BITS; MOV EDI, ESI; ADD EDI, 64; ADD EDI, 32 MOV ECX, 8; REP MOVSD; MOV DWORD PTR Current, 0; //Current MOV DWORD PTR Next, 64; //Next //for i := 16 downto 1 do //begin MOV ECX, LoopCount;//Loop; @Loop1: PUSH ECX; XOR DWORD PTR Current, 64;//Current XOR DWORD PTR Next, 64; //Next //R(i-1) = L(i) MOV ECX, 8; LEA ESI, BITS; MOV EDI, ESI; ADD ESI, Current;//Current ADD EDI, Next;//Next ADD EDI, 32; REP MOVSD; //48b(Li) LEA ESI, Bit48s; LEA EBX, tblE; LEA EAX, Bits; ADD EAX, Current; XOR EDI, EDI; XOR ECX, ECX; @EXT1: MOV CL, [EBX][EDI]; DEC CL; MOV DL, [EAX][ECX]; MOV [ESI][EDI],DL; INC EDI; CMP EDI, 48; JL @EXT1; //Li ^ Key i-1 XOR EDI, EDI; MOV EBX, KeysAddr; SUB EBX, 48; @USEK1: MOV EAX, [EBX][EDI]; XOR [ESI][EDI], EAX; ADD EDI, 4; CMP EDI, 48; JL @USEK1; MOV KeysAddr, EBX; //S(Li) LEA EDI, BITS; ADD EDI, Current; LEA EBX, tblS; MOV ECX,4 @S1: XOR EDX, EDX; XOR EAX, EAX; MOV DL, [ESI]; SHL DL, 1; OR DL, [ESI][5]; SHL EDX, CL; MOV AL,[ESI][1]; SHL AL, 1; OR AL, [ESI][2]; SHL AL, 1; OR AL, [ESI][3]; SHL AL, 1; OR AL, [ESI][4]; ADD EDX, EAX; XOR EAX,EAX; MOV AL, [EBX][EDX] ROR EAX, CL; ROL EAX, 1; MOV [EDI], AL; ROL EAX, 1; AND AL, 1; MOV [EDI][1], AL; ROL EAX, 1; AND EAX, 1; MOV [EDI][2], AL; ROL EAX, 1; AND AL,1; MOV [EDI][3], AL; ADD ESI, 6; ADD EDI, 4; INC CH; CMP CH, 8; JL @S1; //P(Li) LEA EBX, tblP; LEA ESI, BITS; MOV EDI, ESI; ADD ESI, CURRENT; ADD EDI, NEXT; XOR EAX,EAX; XOR ECX,ECX; @P1: MOV AL, [EBX][ECX]; DEC AL; MOV DL, [ESI][EAX]; MOV [EDI][ECX],DL; INC ECX; CMP ECX, 32 JL @P1; //L(i-1) = R(i) ^ Li XOR ECX, ECX ADD ESI, 32; @L1: MOV EAX, [ESI][ECX]; XOR [EDI][ECX], EAX; ADD ECX, 4; CMP ECX, 32; JL @L1; //end; POP ECX; DEC ECX; JNZ @LOOP1; //UnIP LEA ESI, BITS; ADD ESI, NEXT; LEA EBX, tblUnIP; MOV EDI, DataAddr; XOR EAX, EAX; XOR ECX, ECX; @UNIP1: MOV AL, [EBX][ECX]; DEC AL; MOV DL, [ESI][EAX]; MOV [EDI][ECX], DL; INC ECX; CMP ECX, 64; JL @UNIP1; POPAD; end; procedure GetBits(const Source; var Dest; cByte: Integer); asm PUSH EBX; PUSH EDI; PUSH ESI; XOR EDI, EDI; XOR ESI, ESI; XOR EBX,EBX @LOOP1: MOV BL, [EAX][ESI]; ROR EBX,7; AND BL,1; MOV [EDX][EDI], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 1], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 2], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 3], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 4], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 5], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 6], BL; ROL EBX,1; AND BL,1; MOV [EDX][EDI 7], BL; ADD EDI, 8; INC ESI; LOOP @LOOP1 POP ESI; POP EDI; POP EBX; end; procedure SetBits(const Source; var Dest; cByte: Integer); asm PUSH EBX; PUSH EDI; PUSH ESI; XOR EDI, EDI; XOR ESI, ESI; @LOOP1: MOV BL, [EAX][ESI]; SHL BL, 1; OR BL, [EAX][ESI 1]; SHL BL, 1; OR BL, [EAX][ESI 2]; SHL BL, 1; OR BL, [EAX][ESI 3]; SHL BL, 1; OR BL, [EAX][ESI 4]; SHL BL, 1; OR BL, [EAX][ESI 5]; SHL BL, 1; OR BL, [EAX][ESI 6]; SHL BL, 1; OR BL, [EAX][ESI 7]; MOV [EDX][EDI], BL ADD ESI, 8; INC EDI; LOOP @LOOP1 POP ESI; POP EDI; POP EBX; end; procedure MakeDesKeyData(const Key; var KeyData); assembler; const Idx56In64: packed array [0..55] of Byte = (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 ); Idx48In56: packed array[0..47] of Byte = (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); KeyShift: packed array [0..15] of Integer = (1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1); var Key64: packed array [0..63] of Byte; Key56: packed array [0..55] of Byte; KeyTemp: packed array [0..55] of Byte; KeyDataAdr: Cardinal; asm // Get64Bits PUSH ESI; PUSH EDI; PUSH EBX; MOV KeyDataAdr, EDX; LEA EDX, Key64; MOV ECX, 8; CALL GetBits; //64 Bits ==> 56 Bits LEA EDI, Key56; LEA ESI, Key64; LEA EBX, Idx56In64; XOR EAX, EAX; XOR ECX, ECX; @1: MOV AL, [EBX][ESI]; DEC AL; MOV CL, [ESI][EAX]; MOV [EDI][ESI], CL; INC CH; CMP CH, 56; JL @1; XOR EDX,EDX; @2: // L <<< move[i]; LEA ESI,Key56; LEA EDI,KeyTemp; XOR ECX,ECX; LEA EBX,KeyShift; MOV BYTE PTR CL, [EDX][EBX]; REP MOVSB; LEA EDI, Key56; MOV ESI, EDI; MOV CL, [EBX][EDX]; ADD ESI, ECX; MOV ECX, 28; SUB CL, [EBX][EDX]; REP MOVSB; LEA ESI, KeyTemp; MOV CL, [EBX][EDX]; REP MOVSB; // R <<< move[i]; LEA ESI,Key56[28]; LEA EDI,KeyTemp; XOR ECX,ECX; LEA EBX,KeyShift; MOV BYTE PTR CL, [EDX][EBX]; REP MOVSB; LEA EDI, Key56[28]; MOV ESI, EDI; MOV CL, [EBX][EDX]; ADD ESI, ECX; MOV ECX, 28; SUB CL, [EBX][EDX]; REP MOVSB; LEA ESI, KeyTemp; MOV CL, [EBX][EDX]; REP MOVSB; // Get48Bits MOV EAX, EDX; IMUL EAX, 48; MOV EDI, KeyDataAdr; ADD EDI, EAX; LEA ESI, Key56; LEA EBX, Idx48In56; XOR EAX, EAX; XOR ECX, ECX; @3: MOV AL, [EBX][ESI]; DEC AL; MOV CL, [ESI][EAX]; MOV [EDI][ESI], CL; INC CH; CMP CH, 56; JL @3; INC EDX; CMP EDX, 16; JL @2; end; end.上面的代碼按說不會有錯的呀,我在一網站上復制過來的。 有意的話,可以復制試一下。 |
wnhoo
高階會員 發表:75 回覆:443 積分:198 註冊:2003-04-22 發送簡訊給我 |
|
hua2000
中階會員 發表:102 回覆:200 積分:65 註冊:2006-11-04 發送簡訊給我 |
|
hua2000
中階會員 發表:102 回覆:200 積分:65 註冊:2006-11-04 發送簡訊給我 |
|
wnhoo
高階會員 發表:75 回覆:443 積分:198 註冊:2003-04-22 發送簡訊給我 |
[转帖]http://www.chinaithr.com/bbs/bbs11/20.xml 下面是我用这几个函数做的DES加密的一个实现(生成密钥数据时没有用标准的DES方法):
unit DesEncryptor; interface uses
Classes, SysUtils; type
EDesError = class(Exception)
end; TDesEncryptor = class
private
KeyData: array [0..15] of array [0..47] of Byte;
Key: String;
procedure MakeKeyData;
public
function GetMaxEncodeSize(DataSize:Integer): Integer;
//计算对DataSize字节的明文加密后密文的最大长度
function GetMaxDecodeSize(DataSize:Integer): Integer;
//计算对DataSize字节的密文解密后明文的最大长度
function EncodeMem(var Data; DataSize: Integer):Integer;
//对Data中DataSize字节的数据加密,密文存放在Data中,返回回值为密文长度。
function DecodeMem(var Data; DataSize: Integer):Integer;
//对Data中的DataSize字节的数据解密,明文存放在Data中,返回值为明文长度。
procedure EncodeVar(var Data: OleVariant);
//对Data加密,Data应为Variant Array of Byte类型,密文存放在Data中,
//Data的元素个数将发生变化,因此不能是被锁住的。。
procedure DecodeVar(var Data: OleVariant);
//对Data加密,Data应为Variant Array of Byte类型,密文存放在Data中,
//Data的元素个数将发生变化,因此不能是被锁住的。。
procedure Encode(const InStream, OutStream: TStream);
//对InStream中的内容加密,密文存入OutStream中。InStream和OutStream可以是同一对象。
procedure Decode(const InStream, OutStream: TStream);
//对InStream中的内容加密,密文存入OutStream中。InStream和OutStream可以是同一对象。
procedure SetKey(theKey: String);
{ Protected declarations }
public
constructor Create;
destructor Destroy; override;
end; implementation uses MD5, DesUtil, Windows, Variants; type
TByteAry = array [0..32767] of Byte;
PByteAry = ^TByteAry;
TByteVarAry = array of Byte;
PByteVarAry = ^TByteVarAry; resourcestring
SErrorDesBadcryptograph = '密文已被损坏,无法解密。'; function FindByteBack(Pattern: Byte; const Data; DataSize: Integer): Integer; assembler;
asm
PUSH EDI;
LEA EDI, [EDX + ECX - 1];
STD;
CMP ECX, 1;
REPNE SCASB;
MOV EAX, ECX;
CLD;
JE @FOUND;
MOV EAX, -1;
@FOUND:
POP EDI;
end; procedure TDesEncryptor.SetKey(theKey: String);
begin
Key := theKey;
MakeKeyData;
end; procedure TDesEncryptor.DecodeVar(var Data: OleVariant);
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, DataSize, NewDataSize: Integer;
begin
Level := 16;
DataSize := VarArrayHighBound(Data, 1) - VarArrayLowBound(Data, 1) + 1;
if DataSize mod 8 <> 0 then
begin
DataSize := (DataSize Div 8) * 8;
VarArrayRedim(Data, DataSize + VarArrayLowBound(Data, 1) - 1);
end;
ptrData := VarArrayLock(Data);
try
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
NewDataSize := FindByteBack($FF, PtrData[0], DataSize);
finally
VarArrayUnlock(Data);
end;
if NewDataSize < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
VarArrayRedim(Data, NewDataSize + VarArrayLowBound(Data, 1) - 1);
end; procedure TDesEncryptor.EncodeVar(var Data: OleVariant);
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, DataSize, OldDataSize: Integer;
begin
Level := 16;
DataSize := VarArrayHighBound(Data, 1) - VarArrayLowBound(Data, 1) + 1;
OldDataSize := DataSize;
DataSize := (DataSize Div 8 +1) * 8;
VarArrayRedim(Data, DataSize - VarArrayLowBound(Data, 1) - 1);
ptrData := VarArrayLock(Data);
try
ptrData[OldDataSize] := $FF;
for I := OldDataSize + 1 to DataSize - 1 do
ptrData[I] := Random(255);
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
finally
VarArrayUnlock(Data);
end;
end; procedure TDesEncryptor.Decode(const InStream, OutStream: TStream);
const
BlockSize = 1024;
bBlockSize = BlockSize * 8;
var
DataBits: array[0..63] of Byte;
Data: array [0..BlockSize-1, 0..7] of Byte;
Level: Integer;
InSize, Progress, ReadPos, WritePos, SizeOfHoleBlock: Int64;
LastBlockSize, ProgressInBlock: Integer;
begin
Level := 16; InSize := InStream.Size;
InStream.Position := 0;
OutStream.Position := 0; Progress := 0;
ReadPos := 0;
WritePos := 0; SizeOfHoleBlock := ((InSize - 1) div BlockSize) * BlockSize; while Progress < SizeOfHoleBlock do
begin
InStream.Position := ReadPos;
InStream.Read(Data[0,0], bBlockSize); for ProgressInBlock := 0 to BlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end;
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], bBlockSize); Inc(ReadPos, bBlockSize);
Inc(WritePos, bBlockSize);
Inc(Progress, bBlocksize);
end; InSize := InSize - SizeOfHoleBlock; InStream.Position := ReadPos;
InStream.Read(Data, InSize); LastBlockSize := InSize div 8;
InSize := LastBlockSize * 8; for ProgressInBlock := 0 to LastBlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end; InSize := FindByteBack($FF, Data, InSize);
if InSize < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], InSize);
OutStream.Size := OutStream.Position;
end; procedure TDesEncryptor.Encode(const InStream, OutStream: TStream);
const
BlockSize = 1024;
bBlockSize = BlockSize * 8;
var
DataBits: array [0..63] of Byte;
Data: array [0..BlockSize-1, 0..7] of Byte;
Level: Integer;
InSize, Progress, ReadPos, WritePos, SizeOfHoleBlock: Int64;
LastBlockSize, ProgressInBlock: Integer;
I: Integer;
begin
Level := 16; InSize := InStream.Size;
InStream.Position := 0;
OutStream.Position := 0; Progress := 0;
ReadPos := 0;
WritePos := 0; SizeOfHoleBlock := InSize - InSize mod bBlockSize; while Progress < SizeOfHoleBlock do
begin
InStream.Position := ReadPos;
InStream.Read(Data[0,0], bBlockSize); for ProgressInBlock := 0 to BlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end; OutStream.Position := WritePos;
OutStream.Write(Data[0,0], bBlockSize); Inc(ReadPos, bBlockSize);
Inc(WritePos, bBlockSize);
Inc(Progress, bBlocksize);
end; InSize := InSize mod bBlockSize;
InStream.Position := ReadPos;
InStream.Read(Data, InSize); LastBlockSize := InSize div 8 + 1; PByteAry(@Data)^[InSize] := $FF;
for I := InSize + 1 to LastBlockSize * 8 - 1 do
PByteAry(@Data)^[I] := Random(255); for ProgressInBlock := 0 to LastBlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end;
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], LastBlockSize * 8);
OutStream.Size := SizeOfHoleBlock + LastBlockSize * 8;
end; procedure TDesEncryptor.MakeKeyData;
const
KeySuffixes: array [0..5] of String =
('dsafsda',
'rerwawe',
'32522asf',
',.[[]-\',
'`2304-`',
'va[0e324');
var
PackedKeyData: array[0..95] of Byte;
Temp: String;
I: Integer;
begin
for I := 0 to 5 do
begin
Temp := Key + KeySuffixes[I];
MD5Code(Temp[1], PackedKeyData[I *16], Length(Temp));
end;
for I := 0 to 15 do
GetBits(PackedKeyData[I*6], KeyData[I], 6);
end; destructor TDesEncryptor.Destroy;
begin
inherited;
end; constructor TDesEncryptor.Create;
begin
inherited Create;
SetKey('')
end; function TDesEncryptor.DecodeMem(var Data; DataSize: Integer): Integer;
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I: Integer;
begin
Level := 16;
if DataSize mod 8 <> 0 then
begin
DataSize := (DataSize Div 8) * 8;
end;
ptrData := @Data;
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
Result := FindByteBack($FF, Data, DataSize);
if Result < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
end; function TDesEncryptor.EncodeMem(var Data; DataSize: Integer): Integer;
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, OldDataSize: Integer;
begin
Level := 16;
OldDataSize := DataSize;
DataSize := (DataSize Div 8 + 1) * 8;
ptrData :=@Data;
PtrData[OldDataSize] := $FF;
for I := OldDataSize + 1 to DataSize - 1 do
PtrData[I] := Random(255); I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
Result := DataSize;
end; function TDesEncryptor.GetMaxDecodeSize(DataSize: Integer): Integer;
begin
Result := DataSize;
end; function TDesEncryptor.GetMaxEncodeSize(DataSize: Integer): Integer;
begin
Result := ((DataSize + 1) div 8 + 1) * 8;
end; initialization
Randomize;
end. 由于DES加密是以64位(8字节)为单位的,加密前必须把明文长度调整为8字节的整数倍。为了能够在解密时知道明文的准确长度,加密前在明文末尾追加加了一个#$FF,然后用不等于#$FF的随机数填充到8字节整数倍。在解密后从明文末尾向前查找第一个#$FF,从而确定明文的准确长度。 下面是对字符串加密和对文件加密的测试(Delphi 6): //Unit1.pas
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls; type
TForm1 = class(TForm)
btnTestStr: TButton;
edtKey: TLabeledEdit;
edtPlain: TLabeledEdit;
edtCipher: TLabeledEdit;
edtDecrypted: TLabeledEdit;
btnEncryptFile: TButton;
btnDecryptFile: TButton;
dlgOpen: TOpenDialog;
dlgSave: TSaveDialog;
procedure btnTestStrClick(Sender: TObject);
procedure btnDecryptFileClick(Sender: TObject);
procedure btnEncryptFileClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation uses
DesEncryptor; {$R *.dfm} procedure TForm1.btnTestStrClick(Sender: TObject);
var
Temp: String;
Encryptor: TDesEncryptor;
L: Integer;
Printable: String;
begin
Encryptor := TDesEncryptor.Create;
try
Encryptor.SetKey(edtKey.Text);
Temp := edtPlain.Text;
//加密
L := Length(Temp);
SetLength(Temp, Encryptor.GetMaxEncodeSize(Length(Temp)));
L := Encryptor.EncodeMem(Temp[1], L);
SetLength(Temp, L);
//显示密文(因为密文不是ASCII码,要转换一下才能显示)
SetLength(Printable, L *2);
BinToHex(PChar(Temp), PChar(Printable), L);
edtCipher.Text := Printable;
//解密
L := Length(Temp);
SetLength(Temp, Encryptor.GetMaxDecodeSize(L));
L := Encryptor.DecodeMem(Temp[1], L);
SetLength(Temp, L);
edtDecrypted.Text := Temp;
finally
Encryptor.Free;
end;
end; procedure TForm1.btnDecryptFileClick(Sender: TObject);
var
InStrm, OutStrm: TStream;
Encryptor: TDesEncryptor;
begin
InStrm := nil;
OutStrm := nil;
Encryptor := nil;
try
if dlgOpen.Execute and dlgSave.Execute then
begin
InStrm :=TFileStream.Create(dlgOpen.FileName, fmOpenRead);
OutStrm := TFileStream.Create(dlgSave.FileName,fmCreate);
Encryptor := TDesEncryptor.Create;
Encryptor.SetKey(edtKey.Text);
Encryptor.Decode(InStrm, OutStrm);
end;
finally
InStrm.Free;
OutStrm.Free;
Encryptor.Free;
end;
end; procedure TForm1.btnEncryptFileClick(Sender: TObject);
var
InStrm, OutStrm: TStream;
Encryptor: TDesEncryptor;
begin
InStrm := nil;
OutStrm := nil;
Encryptor := nil;
try
if dlgOpen.Execute and dlgSave.Execute then
begin
InStrm :=TFileStream.Create(dlgOpen.FileName, fmOpenRead);
OutStrm := TFileStream.Create(dlgSave.FileName,fmCreate);
Encryptor := TDesEncryptor.Create;
Encryptor.SetKey(edtKey.Text);
Encryptor.Encode(InStrm, OutStrm);
end;
finally
InStrm.Free;
OutStrm.Free;
Encryptor.Free;
end;
end; end. //Unit1.dfm
object Form1: TForm1
Left = 222
Top = 147
Width = 432
Height = 167
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object btnTestStr: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = '字符串测试'
TabOrder = 0
OnClick = btnTestStrClick
end
object edtKey: TLabeledEdit
Left = 120
Top = 8
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '密钥'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 1
end
object edtPlain: TLabeledEdit
Left = 120
Top = 40
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '明文'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 2
end
object edtCipher: TLabeledEdit
Left = 120
Top = 72
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '密文'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 3
end
object edtDecrypted: TLabeledEdit
Left = 120
Top = 104
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '解密'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 4
end
object btnEncryptFile: TButton
Left = 8
Top = 40
Width = 75
Height = 25
Caption = '加密文件'
TabOrder = 5
OnClick = btnEncryptFileClick
end
object btnDecryptFile: TButton
Left = 8
Top = 72
Width = 75
Height = 25
Caption = '解密文件'
TabOrder = 6
OnClick = btnDecryptFileClick
end
object dlgOpen: TOpenDialog
Left = 16
Top = 104
end
object dlgSave: TSaveDialog
Left = 48
Top = 104
end
end 风花雪月 e梦情缘
------
风花雪月 e梦情缘 |
wnhoo
高階會員 發表:75 回覆:443 積分:198 註冊:2003-04-22 發送簡訊給我 |
[转帖]http://www.chinaithr.com/bbs/bbs11/20.xml 下面是我用这几个函数做的DES加密的一个实现(生成密钥数据时没有用标准的DES方法):
unit DesEncryptor; interface uses
Classes, SysUtils; type
EDesError = class(Exception)
end; TDesEncryptor = class
private
KeyData: array [0..15] of array [0..47] of Byte;
Key: String;
procedure MakeKeyData;
public
function GetMaxEncodeSize(DataSize:Integer): Integer;
//计算对DataSize字节的明文加密后密文的最大长度
function GetMaxDecodeSize(DataSize:Integer): Integer;
//计算对DataSize字节的密文解密后明文的最大长度
function EncodeMem(var Data; DataSize: Integer):Integer;
//对Data中DataSize字节的数据加密,密文存放在Data中,返回回值为密文长度。
function DecodeMem(var Data; DataSize: Integer):Integer;
//对Data中的DataSize字节的数据解密,明文存放在Data中,返回值为明文长度。
procedure EncodeVar(var Data: OleVariant);
//对Data加密,Data应为Variant Array of Byte类型,密文存放在Data中,
//Data的元素个数将发生变化,因此不能是被锁住的。。
procedure DecodeVar(var Data: OleVariant);
//对Data加密,Data应为Variant Array of Byte类型,密文存放在Data中,
//Data的元素个数将发生变化,因此不能是被锁住的。。
procedure Encode(const InStream, OutStream: TStream);
//对InStream中的内容加密,密文存入OutStream中。InStream和OutStream可以是同一对象。
procedure Decode(const InStream, OutStream: TStream);
//对InStream中的内容加密,密文存入OutStream中。InStream和OutStream可以是同一对象。
procedure SetKey(theKey: String);
{ Protected declarations }
public
constructor Create;
destructor Destroy; override;
end; implementation uses MD5, DesUtil, Windows, Variants; type
TByteAry = array [0..32767] of Byte;
PByteAry = ^TByteAry;
TByteVarAry = array of Byte;
PByteVarAry = ^TByteVarAry; resourcestring
SErrorDesBadcryptograph = '密文已被损坏,无法解密。'; function FindByteBack(Pattern: Byte; const Data; DataSize: Integer): Integer; assembler;
asm
PUSH EDI;
LEA EDI, [EDX + ECX - 1];
STD;
CMP ECX, 1;
REPNE SCASB;
MOV EAX, ECX;
CLD;
JE @FOUND;
MOV EAX, -1;
@FOUND:
POP EDI;
end; procedure TDesEncryptor.SetKey(theKey: String);
begin
Key := theKey;
MakeKeyData;
end; procedure TDesEncryptor.DecodeVar(var Data: OleVariant);
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, DataSize, NewDataSize: Integer;
begin
Level := 16;
DataSize := VarArrayHighBound(Data, 1) - VarArrayLowBound(Data, 1) + 1;
if DataSize mod 8 <> 0 then
begin
DataSize := (DataSize Div 8) * 8;
VarArrayRedim(Data, DataSize + VarArrayLowBound(Data, 1) - 1);
end;
ptrData := VarArrayLock(Data);
try
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
NewDataSize := FindByteBack($FF, PtrData[0], DataSize);
finally
VarArrayUnlock(Data);
end;
if NewDataSize < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
VarArrayRedim(Data, NewDataSize + VarArrayLowBound(Data, 1) - 1);
end; procedure TDesEncryptor.EncodeVar(var Data: OleVariant);
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, DataSize, OldDataSize: Integer;
begin
Level := 16;
DataSize := VarArrayHighBound(Data, 1) - VarArrayLowBound(Data, 1) + 1;
OldDataSize := DataSize;
DataSize := (DataSize Div 8 +1) * 8;
VarArrayRedim(Data, DataSize - VarArrayLowBound(Data, 1) - 1);
ptrData := VarArrayLock(Data);
try
ptrData[OldDataSize] := $FF;
for I := OldDataSize + 1 to DataSize - 1 do
ptrData[I] := Random(255);
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
finally
VarArrayUnlock(Data);
end;
end; procedure TDesEncryptor.Decode(const InStream, OutStream: TStream);
const
BlockSize = 1024;
bBlockSize = BlockSize * 8;
var
DataBits: array[0..63] of Byte;
Data: array [0..BlockSize-1, 0..7] of Byte;
Level: Integer;
InSize, Progress, ReadPos, WritePos, SizeOfHoleBlock: Int64;
LastBlockSize, ProgressInBlock: Integer;
begin
Level := 16; InSize := InStream.Size;
InStream.Position := 0;
OutStream.Position := 0; Progress := 0;
ReadPos := 0;
WritePos := 0; SizeOfHoleBlock := ((InSize - 1) div BlockSize) * BlockSize; while Progress < SizeOfHoleBlock do
begin
InStream.Position := ReadPos;
InStream.Read(Data[0,0], bBlockSize); for ProgressInBlock := 0 to BlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end;
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], bBlockSize); Inc(ReadPos, bBlockSize);
Inc(WritePos, bBlockSize);
Inc(Progress, bBlocksize);
end; InSize := InSize - SizeOfHoleBlock; InStream.Position := ReadPos;
InStream.Read(Data, InSize); LastBlockSize := InSize div 8;
InSize := LastBlockSize * 8; for ProgressInBlock := 0 to LastBlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end; InSize := FindByteBack($FF, Data, InSize);
if InSize < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], InSize);
OutStream.Size := OutStream.Position;
end; procedure TDesEncryptor.Encode(const InStream, OutStream: TStream);
const
BlockSize = 1024;
bBlockSize = BlockSize * 8;
var
DataBits: array [0..63] of Byte;
Data: array [0..BlockSize-1, 0..7] of Byte;
Level: Integer;
InSize, Progress, ReadPos, WritePos, SizeOfHoleBlock: Int64;
LastBlockSize, ProgressInBlock: Integer;
I: Integer;
begin
Level := 16; InSize := InStream.Size;
InStream.Position := 0;
OutStream.Position := 0; Progress := 0;
ReadPos := 0;
WritePos := 0; SizeOfHoleBlock := InSize - InSize mod bBlockSize; while Progress < SizeOfHoleBlock do
begin
InStream.Position := ReadPos;
InStream.Read(Data[0,0], bBlockSize); for ProgressInBlock := 0 to BlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end; OutStream.Position := WritePos;
OutStream.Write(Data[0,0], bBlockSize); Inc(ReadPos, bBlockSize);
Inc(WritePos, bBlockSize);
Inc(Progress, bBlocksize);
end; InSize := InSize mod bBlockSize;
InStream.Position := ReadPos;
InStream.Read(Data, InSize); LastBlockSize := InSize div 8 + 1; PByteAry(@Data)^[InSize] := $FF;
for I := InSize + 1 to LastBlockSize * 8 - 1 do
PByteAry(@Data)^[I] := Random(255); for ProgressInBlock := 0 to LastBlockSize - 1 do
begin
GetBits(Data[ProgressInBlock,0], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, Data[ProgressInBlock,0], 8);
end;
OutStream.Position := WritePos;
OutStream.Write(Data[0,0], LastBlockSize * 8);
OutStream.Size := SizeOfHoleBlock + LastBlockSize * 8;
end; procedure TDesEncryptor.MakeKeyData;
const
KeySuffixes: array [0..5] of String =
('dsafsda',
'rerwawe',
'32522asf',
',.[[]-\',
'`2304-`',
'va[0e324');
var
PackedKeyData: array[0..95] of Byte;
Temp: String;
I: Integer;
begin
for I := 0 to 5 do
begin
Temp := Key + KeySuffixes[I];
MD5Code(Temp[1], PackedKeyData[I *16], Length(Temp));
end;
for I := 0 to 15 do
GetBits(PackedKeyData[I*6], KeyData[I], 6);
end; destructor TDesEncryptor.Destroy;
begin
inherited;
end; constructor TDesEncryptor.Create;
begin
inherited Create;
SetKey('')
end; function TDesEncryptor.DecodeMem(var Data; DataSize: Integer): Integer;
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I: Integer;
begin
Level := 16;
if DataSize mod 8 <> 0 then
begin
DataSize := (DataSize Div 8) * 8;
end;
ptrData := @Data;
I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
UNDES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
Result := FindByteBack($FF, Data, DataSize);
if Result < 0 then
raise EDesError.CreateRes(@SErrorDesBadcryptograph);
end; function TDesEncryptor.EncodeMem(var Data; DataSize: Integer): Integer;
var
DataBits: array [0..63] of Byte;
Level: Integer;
ptrData: PByteArray;
I, OldDataSize: Integer;
begin
Level := 16;
OldDataSize := DataSize;
DataSize := (DataSize Div 8 + 1) * 8;
ptrData :=@Data;
PtrData[OldDataSize] := $FF;
for I := OldDataSize + 1 to DataSize - 1 do
PtrData[I] := Random(255); I:= 0;
while (I < DataSize) do
begin
GetBits(ptrData^[I], DataBits, 8);
DES(DataBits, KeyData[0], Level);
SetBits(DataBits, ptrData^[I], 8);
Inc(I, 8);
end;
Result := DataSize;
end; function TDesEncryptor.GetMaxDecodeSize(DataSize: Integer): Integer;
begin
Result := DataSize;
end; function TDesEncryptor.GetMaxEncodeSize(DataSize: Integer): Integer;
begin
Result := ((DataSize + 1) div 8 + 1) * 8;
end; initialization
Randomize;
end. 由于DES加密是以64位(8字节)为单位的,加密前必须把明文长度调整为8字节的整数倍。为了能够在解密时知道明文的准确长度,加密前在明文末尾追加加了一个#$FF,然后用不等于#$FF的随机数填充到8字节整数倍。在解密后从明文末尾向前查找第一个#$FF,从而确定明文的准确长度。 下面是对字符串加密和对文件加密的测试(Delphi 6): //Unit1.pas
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls; type
TForm1 = class(TForm)
btnTestStr: TButton;
edtKey: TLabeledEdit;
edtPlain: TLabeledEdit;
edtCipher: TLabeledEdit;
edtDecrypted: TLabeledEdit;
btnEncryptFile: TButton;
btnDecryptFile: TButton;
dlgOpen: TOpenDialog;
dlgSave: TSaveDialog;
procedure btnTestStrClick(Sender: TObject);
procedure btnDecryptFileClick(Sender: TObject);
procedure btnEncryptFileClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation uses
DesEncryptor; {$R *.dfm} procedure TForm1.btnTestStrClick(Sender: TObject);
var
Temp: String;
Encryptor: TDesEncryptor;
L: Integer;
Printable: String;
begin
Encryptor := TDesEncryptor.Create;
try
Encryptor.SetKey(edtKey.Text);
Temp := edtPlain.Text;
//加密
L := Length(Temp);
SetLength(Temp, Encryptor.GetMaxEncodeSize(Length(Temp)));
L := Encryptor.EncodeMem(Temp[1], L);
SetLength(Temp, L);
//显示密文(因为密文不是ASCII码,要转换一下才能显示)
SetLength(Printable, L *2);
BinToHex(PChar(Temp), PChar(Printable), L);
edtCipher.Text := Printable;
//解密
L := Length(Temp);
SetLength(Temp, Encryptor.GetMaxDecodeSize(L));
L := Encryptor.DecodeMem(Temp[1], L);
SetLength(Temp, L);
edtDecrypted.Text := Temp;
finally
Encryptor.Free;
end;
end; procedure TForm1.btnDecryptFileClick(Sender: TObject);
var
InStrm, OutStrm: TStream;
Encryptor: TDesEncryptor;
begin
InStrm := nil;
OutStrm := nil;
Encryptor := nil;
try
if dlgOpen.Execute and dlgSave.Execute then
begin
InStrm :=TFileStream.Create(dlgOpen.FileName, fmOpenRead);
OutStrm := TFileStream.Create(dlgSave.FileName,fmCreate);
Encryptor := TDesEncryptor.Create;
Encryptor.SetKey(edtKey.Text);
Encryptor.Decode(InStrm, OutStrm);
end;
finally
InStrm.Free;
OutStrm.Free;
Encryptor.Free;
end;
end; procedure TForm1.btnEncryptFileClick(Sender: TObject);
var
InStrm, OutStrm: TStream;
Encryptor: TDesEncryptor;
begin
InStrm := nil;
OutStrm := nil;
Encryptor := nil;
try
if dlgOpen.Execute and dlgSave.Execute then
begin
InStrm :=TFileStream.Create(dlgOpen.FileName, fmOpenRead);
OutStrm := TFileStream.Create(dlgSave.FileName,fmCreate);
Encryptor := TDesEncryptor.Create;
Encryptor.SetKey(edtKey.Text);
Encryptor.Encode(InStrm, OutStrm);
end;
finally
InStrm.Free;
OutStrm.Free;
Encryptor.Free;
end;
end; end. //Unit1.dfm
object Form1: TForm1
Left = 222
Top = 147
Width = 432
Height = 167
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object btnTestStr: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = '字符串测试'
TabOrder = 0
OnClick = btnTestStrClick
end
object edtKey: TLabeledEdit
Left = 120
Top = 8
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '密钥'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 1
end
object edtPlain: TLabeledEdit
Left = 120
Top = 40
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '明文'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 2
end
object edtCipher: TLabeledEdit
Left = 120
Top = 72
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '密文'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 3
end
object edtDecrypted: TLabeledEdit
Left = 120
Top = 104
Width = 297
Height = 21
EditLabel.Width = 24
EditLabel.Height = 13
EditLabel.Caption = '解密'
LabelPosition = lpLeft
LabelSpacing = 3
TabOrder = 4
end
object btnEncryptFile: TButton
Left = 8
Top = 40
Width = 75
Height = 25
Caption = '加密文件'
TabOrder = 5
OnClick = btnEncryptFileClick
end
object btnDecryptFile: TButton
Left = 8
Top = 72
Width = 75
Height = 25
Caption = '解密文件'
TabOrder = 6
OnClick = btnDecryptFileClick
end
object dlgOpen: TOpenDialog
Left = 16
Top = 104
end
object dlgSave: TSaveDialog
Left = 48
Top = 104
end
end 风花雪月 e梦情缘
------
风花雪月 e梦情缘 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |