填充模式
加密操作前需要将明文分解成长度为8的块,若明文长度不是8的倍数则需要填充到8的倍数,以下是两张填充方式:
PKCS5:若数据需要填充n个字节才能对齐,则填充的每个字节值都是n;若数据已对齐,则填充一个长度为8的块,填充的每个字节值都是8
Zero:数据长度对齐时不填充,否则填充0
加密模式
ECB:电码本模式
CBC:密码分组链接模式
详细的加密流程参考 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
ECB模式加解密操作
设置填充模式PKCS5,加密模式不用设置默认为ECB,秘钥DESPACS5,加密文本:PB实现DES/ECB模式加解密
十六进制密文为:D256468E014B4313BBF2E07E5BBDA9F8E9C6CDF1021AD55AA4C15B702FBAF205
base64密文为:0lZGjgFLQxO78uB+W72p+OnGzfECGtVapMFbcC+68gU=
解密上一步得到的十六进制密文
解密得到的明文为:PB实现DES/ECB模式加解密
CBC模式加解密操作
设置填充模式PKCS5,加密模式CBC,秘钥DESPACS5,初始化向量INITVECT,加密文本:PB实现DES/CBC模式加解密
十六进制密文为:DDB06F50F8A3B23105B5B1A0FABEA2ACA93A6C785AF25C79DADC93AE7457BB86
base64密文为:3bBvUPijsjEFtbGg+r6irKk6bHha8lx52tyTrnRXu4Y=
解密上一步得到的base64密文
解密得到的明文为:PB实现DES/CBC模式加解密
源代码
几个依赖项、demo中使用到的类源代码:
n_func_blob
n_func_radix
n_base64
发现BUG请留言或私信,以便修正(QQ:768310524 TEL:18649713925)
代码拷贝到文本编辑器,另存为 n_des.sru
$PBExportHeader$n_des.sru
forward
global type n_des from nonvisualobject
end type
type stbl from structure within n_des
end type
type sbox from structure within n_des
end type
end forward
type stbl from structure
string s_list[]
end type
type sbox from structure
stbl s_table[]
end type
global type n_des from nonvisualobject autoinstantiate
end type
type variables
public:
CONSTANT STRING PKCS5 = 'PKCS5Padding'
CONSTANT STRING Zero = 'ZeroPadding'
CONSTANT STRING ECB = 'ECB'
CONSTANT STRING CBC = 'CBC'
private:
string padding = PKCS5
string mode = ECB
byte 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}
byte 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}
byte Rn[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}
byte 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}
byte BIT_SELECTION[] = {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}
byte 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}
byte 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}
string Kn[16]
char iv[]
SBOX S_BOX[]
n_func_blob fblob
end variables
forward prototypes
public subroutine setkey (blob key)
public subroutine setiv (blob ivector)
private subroutine calc_keys (blob key)
public subroutine setmode (string m)
public subroutine setpadding (string pd)
public function blob encode (blob buf)
public function blob decode (blob cypher)
private subroutine calc_blocks (string blocks[], boolean flag, ref string result[])
private function string calc_block (string block, boolean flag)
private function string fun (string r, string k)
end prototypes
public subroutine setkey (blob key);long length
length = len(key)
if length > 8 then
key = blobmid(key , 1 , 8)
elseif length < 8 then
key += fblob.fill(0 , 8 - length)
end if
calc_keys(key)
end subroutine
public subroutine setiv (blob ivector);long length
length = len(ivector)
if length > 8 then
ivector = blobmid(ivector , 1 , 8)
elseif length < 8 then
ivector += fblob.fill(0 , 8 - length)
end if
iv = fblob.Blob2Bin(ivector)
end subroutine
private subroutine calc_keys (blob key);char key_bit[]
char kn_bit[]
string c,d
char cd[]
char k_bit[]
int i,j
string k
key_bit = fblob.Blob2Bin(key)
for i = 1 to 56
kn_bit[i] = key_bit[PC_1[i]]
next
k = string(kn_bit)
c = left(k,28)
d = right(k,28)
for i = 1 to 16
c = mid(c,Rn[i] + 1) + left(c,Rn[i])
d = mid(d,Rn[i] + 1) + left(d,Rn[i])
cd = c + d
for j = 1 to 48
k_bit[j] = cd[PC_2[j]]
next
Kn[i] = k_bit
next
end subroutine
public subroutine setmode (string m);mode = m
end subroutine
public subroutine setpadding (string pd);padding = pd
end subroutine
public function blob encode (blob buf);blob rblob
int li_padding,li_value
char pchar[],hchar[],vchar[]
long i,j
long ll_len,ll_loop,ll_point
blob blockblob[]
string block[],cypher[],cypherhex[]
byte lbyte[],rbyte[]
string result
if upperbound(Kn) <= 0 then return rblob
if len(buf) <= 0 then return rblob
lbyte = GetByteArray(buf)
choose case padding
case PKCS5
li_padding = 8 - mod(len(buf),8)
li_value = li_padding
case Zero
li_padding = 8 - mod(len(buf),8)
if li_padding = 8 then li_padding = 0
li_value = 0
case else
return rblob
end choose
ll_len = upperbound(lbyte)
for i = 1 to li_padding
lbyte[ll_len + i] = li_value
next
ll_loop = fblob.slice(blob(lbyte) , 8 , blockblob)
for i = 1 to ll_loop
block[i] = fblob.Blob2Bin(blockblob[i])
next
calc_blocks(block , true , cypher)
for i = 1 to ll_loop
pchar = cypher[i]
ll_point = 1
for j = 1 to 8
rbyte[8 * i - 8 + j] = byte(pchar[ll_point]) * 128 +&
byte(pchar[ll_point + 1]) * 64 +&
byte(pchar[ll_point + 2]) * 32 +&
byte(pchar[ll_point + 3]) * 16 +&
byte(pchar[ll_point + 4]) * 8 +&
byte(pchar[ll_point + 5]) * 4 +&
byte(pchar[ll_point + 6]) * 2 +&
byte(pchar[ll_point + 7])
ll_point += 8
next
next
return blob(rbyte)
end function
public function blob decode (blob cypher);blob lblb
long ll_len,ll_loop,ll_point
long i,j
char bchar[]
blob blockblob[]
string block[],result[]
byte lbyte[]
int li_padding
ll_len = len(cypher)
if ll_len <= 0 then return lblb
if mod(ll_len,8) <> 0 then return lblb
ll_loop = fblob.slice(cypher , 8 , blockblob)
for i = 1 to ll_loop
block[i] = fblob.Blob2Bin(blockblob[i])
next
calc_blocks(block,false,result)
for i = 1 to ll_loop
bchar = result[i]
ll_point = 1
for j = 1 to 8
lbyte[8 * i - 8 + j] = byte(bchar[ll_point]) * 128 +&
byte(bchar[ll_point + 1]) * 64 +&
byte(bchar[ll_point + 2]) * 32 +&
byte(bchar[ll_point + 3]) * 16 +&
byte(bchar[ll_point + 4]) * 8 +&
byte(bchar[ll_point + 5]) * 4 +&
byte(bchar[ll_point + 6]) * 2 +&
byte(bchar[ll_point + 7])
ll_point += 8
next
next
choose case padding
case PKCS5
li_padding = lbyte[upperbound(lbyte)]
case Zero
case else
return lblb
end choose
lblb = blob(lbyte)
return blobmid(lblb,1,len(lblb) - li_padding)
end function
private subroutine calc_blocks (string blocks[], boolean flag, ref string result[]);int i,j
long ll_loop
char vchar[],pchar[]
ll_loop = upperbound(blocks)
choose case mode
case ECB
for i = 1 to ll_loop
result[i] = calc_block(blocks[i] , flag)
next
case CBC
vchar = iv
if flag then
for i = 1 to ll_loop
pchar = blocks[i]
for j = 1 to 64
if pchar[j] = vchar[j] then
pchar[j] = '0'
else
pchar[j] = '1'
end if
next
result[i] = calc_block(pchar , flag)
vchar = result[i]
next
else
for i = 1 to ll_loop
pchar = calc_block(blocks[i] , flag)
for j = 1 to 64
if pchar[j] = vchar[j] then
pchar[j] = '0'
else
pchar[j] = '1'
end if
next
result[i] = pchar
vchar = blocks[i]
next
end if
case else
end choose
end subroutine
private function string calc_block (string block, boolean flag);
char pchar[],vtempchar[],result[]
char lnchar[],rnchar[],ltempchar[],rtempchar[]
string vstr
int i,j
string l,r,k
pchar = block
for i = 1 to 64
vtempchar[i] = pchar[IP[i]]
next
vstr = vtempchar
lnchar = left(vstr,32)
rnchar = right(vstr,32)
for i = 1 to 16
ltempchar = lnchar
lnchar = rnchar
if flag then
k = Kn[i]
else
k = Kn[17 - i]
end if
rtempchar = fun(rnchar,k)
for j = 1 to 32
if ltempchar[j] = rtempchar[j] then
rnchar[j] = '0'
else
rnchar[j] = '1'
end if
next
next
vtempchar = string(rnchar) + string(lnchar)
for i = 1 to 64
result[i] = vtempchar[IP_1[i]]
next
return result
end function
private function string fun (string r, string k);char rchar[],echar[],kchar[],bchar[],schar[],result[]
string stemp
int i
byte row,col,vtemp
rchar = r
kchar = k
for i = 1 to 48
echar[i] = rchar[BIT_SELECTION[i]]
if echar[i] = kchar[i] then
bchar[i] = '0'
else
bchar[i] = '1'
end if
next
for i = 1 to 8
vtemp = 6 * i - 5
row = byte(bchar[vtemp]) * 2 + byte(bchar[vtemp + 5]) + 1
col = byte(bchar[vtemp + 1]) * 8 + byte(bchar[vtemp + 2]) * 4 + byte(bchar[vtemp + 3]) * 2 + byte(bchar[vtemp + 4]) + 1
stemp += S_BOX[i].S_TABLE[row].S_LIST[col]
next
schar = stemp
for i = 1 to 32
result[i] = schar[P[i]]
next
return result
end function
on n_des.create
call super::create
TriggerEvent( this, "constructor" )
end on
on n_des.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on
event constructor;
S_BOX[1].S_TABLE[1].S_LIST = {'1110','0100','1101','0001','0010','1111','1011','1000','0011','1010','0110','1100','0101','1001','0000','0111'}
S_BOX[1].S_TABLE[2].S_LIST = {'0000','1111','0111','0100','1110','0010','1101','0001','1010','0110','1100','1011','1001','0101','0011','1000'}
S_BOX[1].S_TABLE[3].S_LIST = {'0100','0001','1110','1000','1101','0110','0010','1011','1111','1100','1001','0111','0011','1010','0101','0000'}
S_BOX[1].S_TABLE[4].S_LIST = {'1111','1100','1000','0010','0100','1001','0001','0111','0101','1011','0011','1110','1010','0000','0110','1101'}
S_BOX[2].S_TABLE[1].S_LIST = {'1111','0001','1000','1110','0110','1011','0011','0100','1001','0111','0010','1101','1100','0000','0101','1010'}
S_BOX[2].S_TABLE[2].S_LIST = {'0011','1101','0100','0111','1111','0010','1000','1110','1100','0000','0001','1010','0110','1001','1011','0101'}
S_BOX[2].S_TABLE[3].S_LIST = {'0000','1110','0111','1011','1010','0100','1101','0001','0101','1000','1100','0110','1001','0011','0010','1111'}
S_BOX[2].S_TABLE[4].S_LIST = {'1101','1000','1010','0001','0011','1111','0100','0010','1011','0110','0111','1100','0000','0101','1110','1001'}
S_BOX[3].S_TABLE[1].S_LIST = {'1010','0000','1001','1110','0110','0011','1111','0101','0001','1101','1100','0111','1011','0100','0010','1000'}
S_BOX[3].S_TABLE[2].S_LIST = {'1101','0111','0000','1001','0011','0100','0110','1010','0010','1000','0101','1110','1100','1011','1111','0001'}
S_BOX[3].S_TABLE[3].S_LIST = {'1101','0110','0100','1001','1000','1111','0011','0000','1011','0001','0010','1100','0101','1010','1110','0111'}
S_BOX[3].S_TABLE[4].S_LIST = {'0001','1010','1101','0000','0110','1001','1000','0111','0100','1111','1110','0011','1011','0101','0010','1100'}
S_BOX[4].S_TABLE[1].S_LIST = {'0111','1101','1110','0011','0000','0110','1001','1010','0001','0010','1000','0101','1011','1100','0100','1111'}
S_BOX[4].S_TABLE[2].S_LIST = {'1101','1000','1011','0101','0110','1111','0000','0011','0100','0111','0010','1100','0001','1010','1110','1001'}
S_BOX[4].S_TABLE[3].S_LIST = {'1010','0110','1001','0000','1100','1011','0111','1101','1111','0001','0011','1110','0101','0010','1000','0100'}
S_BOX[4].S_TABLE[4].S_LIST = {'0011','1111','0000','0110','1010','0001','1101','1000','1001','0100','0101','1011','1100','0111','0010','1110'}
S_BOX[5].S_TABLE[1].S_LIST = {'0010','1100','0100','0001','0111','1010','1011','0110','1000','0101','0011','1111','1101','0000','1110','1001'}
S_BOX[5].S_TABLE[2].S_LIST = {'1110','1011','0010','1100','0100','0111','1101','0001','0101','0000','1111','1010','0011','1001','1000','0110'}
S_BOX[5].S_TABLE[3].S_LIST = {'0100','0010','0001','1011','1010','1101','0111','1000','1111','1001','1100','0101','0110','0011','0000','1110'}
S_BOX[5].S_TABLE[4].S_LIST = {'1011','1000','1100','0111','0001','1110','0010','1101','0110','1111','0000','1001','1010','0100','0101','0011'}
S_BOX[6].S_TABLE[1].S_LIST = {'1100','0001','1010','1111','1001','0010','0110','1000','0000','1101','0011','0100','1110','0111','0101','1011'}
S_BOX[6].S_TABLE[2].S_LIST = {'1010','1111','0100','0010','0111','1100','1001','0101','0110','0001','1101','1110','0000','1011','0011','1000'}
S_BOX[6].S_TABLE[3].S_LIST = {'1001','1110','1111','0101','0010','1000','1100','0011','0111','0000','0100','1010','0001','1101','1011','0110'}
S_BOX[6].S_TABLE[4].S_LIST = {'0100','0011','0010','1100','1001','0101','1111','1010','1011','1110','0001','0111','0110','0000','1000','1101'}
S_BOX[7].S_TABLE[1].S_LIST = {'0100','1011','0010','1110','1111','0000','1000','1101','0011','1100','1001','0111','0101','1010','0110','0001'}
S_BOX[7].S_TABLE[2].S_LIST = {'1101','0000','1011','0111','0100','1001','0001','1010','1110','0011','0101','1100','0010','1111','1000','0110'}
S_BOX[7].S_TABLE[3].S_LIST = {'0001','0100','1011','1101','1100','0011','0111','1110','1010','1111','0110','1000','0000','0101','1001','0010'}
S_BOX[7].S_TABLE[4].S_LIST = {'0110','1011','1101','1000','0001','0100','1010','0111','1001','0101','0000','1111','1110','0010','0011','1100'}
S_BOX[8].S_TABLE[1].S_LIST = {'1101','0010','1000','0100','0110','1111','1011','0001','1010','1001','0011','1110','0101','0000','1100','0111'}
S_BOX[8].S_TABLE[2].S_LIST = {'0001','1111','1101','1000','1010','0011','0111','0100','1100','0101','0110','1011','0000','1110','1001','0010'}
S_BOX[8].S_TABLE[3].S_LIST = {'0111','1011','0100','0001','1001','1100','1110','0010','0000','0110','1010','1101','1111','0011','0101','1000'}
S_BOX[8].S_TABLE[4].S_LIST = {'0010','0001','1110','0111','0100','1010','1000','1101','1111','1100','1001','0000','0011','0101','0110','1011'}
end event