自己定义的二进制表,并且用它来实现DES加密算法
本帖最后由 ggdlove 于 2013-12-30 23:44 编辑在AutoLISP中没有发现二进制数的表示,论坛里面也没有发现相关的计算函数。
二进制数在AutoLISP中怎么表示和运算呢?
这里提供了十进制数与二进制表相互转换的函数。肯定不是最好的,但是抛砖引玉,看能不能引出一些二进制的计算函数。
PS:DES加密算法及相关测试,请移步5楼。
二进制表的定义
第一位为符号位(正为0,负为1),后面的为数值位。
比如:
(0 1) --> 1
(0 1 0) --> 2
(0 1 1) --> 3
(0 1 0 0) --> 4
..............以此类推
(1 1) --> -1
(1 1 0) --> -2
(1 1 1) --> -3
(1 1 0 0) --> -4
..............以此类推
不知道这样定义怎么样?能不能完成一般的二进制运算函数。
以下是转换函数:
入门级水平,请多多指正!
十进制转二进制表函数;;将十进制数转换成二进制表,二进制第一位为符号位
(defun DecToBin(dec / bin symb)
(and
;;检验dec是否为整数,不为整数时提示错误
(itoa dec)
;;若dec为整数,求其符号,正为0,负为1
(if (= dec (setq dec (abs dec)))
(setq symb 0)
(setq symb 1)
)
;;求dec的绝对值的二进制表
(if (= dec 0)
;;当dec的绝对值为0时,直接返回'(0)
(setq bin '(0))
;;当dec的绝对值不为0时,转换为二进制表
(while (> dec 0)
(setq bin (cons (rem dec 2) bin))
(setq dec (fix (/ dec 2)))
)
)
;;将符号位加入到二进制数中
(setq bin (cons symb bin))
)
bin
)二进制表转十进制函数;;将二进制表转换成十进制数,二进制第一位为符号位
(defun BinToDec(bin / dec symb gp_error_bak *error*)
;;定义局部错误处理函数
(defun *error*(msg)
(princ "\n; 错误: 参数类型错误: bin: ")(princ bin)
(princ)
)
;;输入参数检查,若不对,则制造错误,交给局部错误处理函数
(if (or
;;若bin不为表则出错,若为表且长度大于等于2时,返回nil,否则返回T
(< (length bin) 2)
;;经检查,bin为一个表。若bin中元素有非整数则出错,全部为整数时返回nil,否则返回T
(not (mapcar 'itoa bin))
;;经检查,bin中全部为整数。若bin中全部在范围内返回nil,有不在范围内的元素返回T
(apply 'or (mapcar '(lambda(x) (or (> x 1) (< x 0))) bin))
)
;;若判别式没出错,但返回T了,则代表格式不正确,则在这里制造错误
(itoa nil)
)
;;取出bin中的符号位
(if (= (car bin) 0)
(setq symb 1)
(setq symb -1)
)
;;去掉bin中的符号位,取出数值位
(setq bin (cdr bin))
;;将bin中的数值位转化为十进制
(if (> (length bin) 1)
;;当bin的数值位长度大于1的时候,进行二进制->十进制转换
(progn
(setq dec 0)
(while bin
;;当bin的元素数量为1时,可能出现(expt 0 0)的情况,出错
(if (> (length bin) 1)
(setq dec (+ dec (expt (* (car bin) 2) (1- (length bin)))))
;;当bin的元素数量为1时,避免出现(expt 0 0)的情况
(setq dec (+ dec (car bin)))
)
;;去掉最高位
(setq bin (cdr bin))
)
)
;;当bin的数值位长度为1的时候,直接将该位赋给dec
(setq dec (car bin))
)
;;将符号位加入到dec中
(* symb dec)
) 本帖最后由 ggdlove 于 2013-12-17 00:31 编辑
利用上述的定义呢,就可以完成下面两个程序。
1)二进制表的按位异或;;按位异或************************************************************************
;;位数不够时,若mode为1,则补1,不为1则补0
(defun BIN_XOR(bin1 bin2 mode / bin *error*)
;;定义局部错误处理函数
(defun *error*(msg)
(princ "\n; 错误: 参数类型错误: bin: ")(princ bin)
(princ)
)
;;输入值检验
(or (and (= (type bin1) 'LIST);;类型为表
(>= (length bin1) 1);;元素数量大于等于1
(apply 'and (mapcar '(lambda(x) (= (type x) 'INT)) bin1));;所有元素必须为整数
(apply 'and (mapcar '(lambda(x) (and (>= x 0) (<= x 1))) bin1));;所有元素必须在区间内
)
(progn
(setq bin bin1)
(exit)
)
)
(or (and (= (type bin2) 'LIST);;类型为表
(>= (length bin2) 1);;元素数量大于等于1
(apply 'and (mapcar '(lambda(x) (= (type x) 'INT)) bin2));;所有元素必须为整数
(apply 'and (mapcar '(lambda(x) (and (>= x 0) (<= x 1))) bin2));;所有元素必须在区间内
)
(progn
(setq bin bin2)
(exit)
)
)
;;读取补位模式
(if (= mode 1)
(setq mode 1)
(setq mode 0)
)
;;位数不对的补齐
(while (/= (length bin1) (length bin2))
(if (< (length bin1) (length bin2))
(setq bin1 (cons mode bin1))
(setq bin2 (cons mode bin2))
)
)
;;按位异或运算
(mapcar '(lambda(x y)
(if (/= x y)
1
0
)
)
bin1
bin2
)
)2)二进制表的按位循环移动;;按位循环移动,当移动位数为正时表示左循环移,为负时表示右循环移*******************************
(defun BIN_RMOVE(bin dir / err *error*)
;;定义局部错误处理函数
(defun *error*(msg)
(if err
(progn
(princ "\n; 错误: 参数类型错误: fixnump: ")
(princ dir)
)
(progn
(princ "\n; 错误: 参数类型错误: bin: ")
(princ bin)
)
)
(princ)
)
;;输入值检验
(or (and (= (type bin) 'LIST);;类型为表
(>= (length bin) 1);;元素数量大于等于1
(apply 'and (mapcar '(lambda(x) (= (type x) 'INT)) bin));;所有元素必须为整数
(apply 'and (mapcar '(lambda(x) (and (>= x 0) (<= x 1))) bin));;所有元素必须在区间内
)
(exit)
)
(or (= (type dir) 'INT) (progn (setq err T) (exit)))
;;若右移,即dir<0时,则将bin倒置
(if (< dir 0) (setq bin (reverse bin)))
;;向左移动nn位
(repeat (abs dir)
(setq bin (append bin (list (car bin))))
(setq bin (cdr bin))
)
;;若右移,即dir为T,nn<0时,则再次将bin倒置
(if (< dir 0) (setq bin (reverse bin)))
;;返回值
bin
)温馨提示:
这两个程序是不定义符号位的。
论坛是个宝库,什么都有!只是你没有用心去找而已!
baseToDecimal 将一个字符串按BASE的做为基数的进制转换为十进制的整数值
decimalToBase 将一个整数转换成一个按BASE基数指定的进制的字符串值 Gu_xl 发表于 2013-12-17 13:59 static/image/common/back.gif
论坛是个宝库,什么都有!只是你没有用心去找而已!
baseToDecimal 将一个字符串按BASE的做为基数的进制 ...
多谢Gu版指导,还没有去函数宝库看过,惭愧。 利用上面写的几个程序,就可以实现DES加密运算了。
PS:待加密的数据必须是64位二进制表,密钥也必须是64位二进制表。
感谢gu版教导,这回没有在函数库里面找到这个函数了。
若是首发,请适当鼓励一下,嘿嘿。;;DES加密函数,mode为1时表示解密模式,mode为其他时表示加密模式
(defun BIN_DES(DATA KEY MODE / bin ii jj tmp *error*
;;密钥变换参数
P-KL P-KR P-KM P-KC
;;数据变换参数
P-DL P-DR P-DE P-DS P-DP P-DF
;;数据参数
KL KR DL DR SUBKEY SUBDATA TMPDR DRR
)
;;定义局部错误处理函数
(defun *error*(msg)
(princ "\n; 错误: 参数类型错误: DES: ")(princ bin)
(princ)
)
;;输入值检验,DATE和KEY必须是64位的二进制表
(or
(and (= (type DATA) 'LIST);;类型为表
(>= (length DATA) 1);;元素数量大于等于1
(apply 'and (mapcar '(lambda(x) (= (type x) 'INT)) DATA));;所有元素必须为整数
(apply 'and (mapcar '(lambda(x) (and (>= x 0) (<= x 1))) DATA));;所有元素必须在区间内
(= (length DATA) 64);;长度必须为64位
)
(progn
(setq bin DATA)
(exit)
)
)
(or
(and (= (type KEY) 'LIST);;类型为表
(>= (length KEY) 1);;元素数量大于等于1
(apply 'and (mapcar '(lambda(x) (= (type x) 'INT)) KEY));;所有元素必须为整数
(apply 'and (mapcar '(lambda(x) (and (>= x 0) (<= x 1))) KEY));;所有元素必须在区间内
(= (length KEY) 64);;长度必须为64位
)
(progn
(setq bin KEY)
(exit)
)
)
;;定义数据变换参数表
;;KEY的相关参数
(setq P-KL '(56 48 40 32 24 16 8
0 57 49 41 33 25 17
9 1 58 50 42 34 26
18 10 2 59 51 43 35
)
)
(setq P-KR '(62 54 46 38 30 22 14
6 61 53 45 37 29 21
13 5 60 52 44 36 28
20 12 4 27 19 11 3
)
)
(setq P-KM '(1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1))
(setq P-KC '(13 16 10 23 0 4 2 27
14 5 20 9 22 18 11 3
25 7 15 6 26 19 12 1
40 51 30 36 46 54 29 39
50 44 32 46 43 48 38 55
33 52 45 41 49 35 28 31
)
)
;;DATA的相关参数
(setq P-DL '(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
)
)
(setq P-DR '(56 48 40 32 24 16 8 0
58 50 42 34 26 18 10 2
60 52 44 36 28 20 12 4
62 54 46 38 30 22 14 6
)
)
(setq P-DE '(31 0 1 2 3 4
3 4 5 6 7 8
7 8 9 10 11 12
11 12 13 14 15 16
15 16 17 18 19 20
19 20 21 22 23 24
23 24 25 26 27 28
27 28 29 30 31 0
)
)
(setq P-DS (list
;;S1
(list
'(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)
)
;;S2
(list
'(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)
)
;;S3
(list
'(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)
)
;;S4
(list
'(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)
)
;;S5
(list
'(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)
)
;;S6
(list
'(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)
)
;;S7
(list
'(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)
)
;;S8
(list
'(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)
)
)
)
(setq P-DP '(15 6 19 20 28 11 27 16
0 14 22 25 4 17 30 9
1 7 23 13 31 26 2 8
18 12 29 5 21 10 3 24
)
)
(setq P-DF '(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
32 0 40 8 48 16 56 24
)
)
;;子密钥的生成
(setq KL (mapcar '(lambda(x)
(nth x KEY)
)
P-KL
)
)
(setq KR (mapcar '(lambda(x)
(nth x KEY)
)
P-KR
)
)
(setq ii 0)
(while (< ii 16)
;;向左移动
(setq KL (BIN_RMOVE KL (nth ii P-KM)))
(setq KR (BIN_RMOVE KR (nth ii P-KM)))
;;选排列
(setq tmp (mapcar '(lambda(x)
(nth x (append KL KR))
)
P-KC
)
)
;;装入SUBKEY
(setq SUBKEY (cons tmp SUBKEY))
(setq ii (1+ ii))
)
;;根据MODE确定SUBKEY的使用顺序
(and (/= MODE 1)
(setq SUBKEY (reverse SUBKEY))
)
;;数据计算
(setq DL (mapcar '(lambda(x)
(nth x DATA)
)
P-DL
)
)
(setq DR (mapcar '(lambda(x)
(nth x DATA)
)
P-DR
)
)
(setq ii 0)
(while (< ii 16)
;;将DR赋给DRR进行F运算
(setq DRR DR)
;;DRR的扩展
(setq DRR (mapcar '(lambda(x)
(nth x DRR)
)
P-DE
)
)
;;DRR与SUBKEY求异或
(setq DRR (BIN_XOR DRR (nth ii SUBKEY) 0))
;;S盒变换
;;将DRR分成8等分
(setq jj 0)
(setq TMPDR DRR)
(setq DRR nil)
(while (< jj 8)
(setq SUBDR nil)
(repeat 6
(setq SUBDR (cons (car TMPDR) SUBDR))
(setq TMPDR (cdr TMPDR))
)
(setq DRR (cons SUBDR DRR))
(setq jj (1+ jj))
)
(setq DRR (reverse DRR))
;;在S盒中选取对应的数值
(setq DRR (mapcar '(lambda(x y / tmp RR CC)
;;求S盒中的行列坐标
(setq RR (BinToDec (list 0 (nth 0 x) (nth 5 x))))
(setq CC (BinToDec (list 0 (nth 1 x) (nth 2 x) (nth 4 x) (nth 4 x))))
;;取出S盒中对应的行列坐标的值,并转换成二进制
(setq tmp (DecToBin (nth CC (nth RR y))))
;;对最高位进行补0,补足4位
(while (< (length tmp) 4)
(setq tmp (cons 0 tmp))
)
;;设置返回值
tmp
)
DRR
P-DS
)
)
;;将DRR化成32位二进制表
(setq DRR (apply 'append DRR))
;;DRR的P盒置换
(setq DRR (mapcar '(lambda(x)
(nth x DRR)
)
P-DP
)
)
;;DRR与DL异或
(setq DL (BIN_XOR DRR DL 0))
;;将DR与DL交换,第16轮除外
(and (< ii 15)
(setq DRR DL)
(setq DL DR)
(setq DR DRR)
)
(setq ii (1+ ii))
)
(setq DATA (append DL DR))
;;最后置换
(setq DATA (mapcar '(lambda(x)
(nth x DATA)
)
P-DF
)
)
;;返回值
DATA
)下面是测试函数:
这里将字符串转换成ascii码,再转换成二进制表进行加密计算,每个字符的ascii码刚好是0-255范围内即8位。;;测试函数
(defun C:TT( / DATA KEY CODE)
(setq data "abcdefgh")
(setq key "12345678")
;;提示
(princ "\n输入的数据为:")(princ data)
(princ "\n输入的密钥为:")(princ key)
;;将data和key转换成64位的二进制表
(setq data (apply 'append (mapcar '(lambda(x)
(setq x (cdr (DecToBin x)))
(while (< (length x) 8)
(setq x (cons 0 x))
x
)
)
(vl-string->list data)
)
)
)
(setq key(apply 'append (mapcar '(lambda(x)
(setq x (cdr (DecToBin x)))
(while (< (length x) 8)
(setq x (cons 0 x))
x
)
)
(vl-string->list key)
)
)
)
;;加密
(setq CODE (BIN_DES DATA KEY 0))
;;解密
(setq DATA (BIN_DES CODE KEY 1))
;;将code和data转换成字符串
(setq data (vl-list->string data))
(setq data (list (substr data 1 8) (substr data 9 8) (substr data 17 8) (substr data 25 8)
(substr data 33 8) (substr data 41 8) (substr data 49 8) (substr data 57 8)))
(setq data (mapcar 'vl-string->list data))
(setq data (vl-list->string (mapcar '(lambda(x) (BinToDec (cons 0 x))) data)))
(setq CODE (vl-list->string CODE))
(setq CODE (list (substr CODE 1 8) (substr CODE 9 8) (substr CODE 17 8) (substr CODE 25 8)
(substr CODE 33 8) (substr CODE 41 8) (substr CODE 49 8) (substr CODE 57 8)))
(setq CODE (mapcar 'vl-string->list CODE))
(setq CODE (vl-list->string (mapcar '(lambda(x) (BinToDec (cons 0 x))) CODE)))
;;提示
(princ "\n加密后的数据为:")(princ CODE)
(princ "\n解密后的数据为:")(princ DATA)
(princ)
)然后我们来看看执行的结果:
从结果可以看出,数据进行加密,然后再进行解密就还原了。程序是可行的!
留个脚印,备用
留个脚印,备用 前生 发表于 2021-6-24 14:13
留个脚印,备用
再留一个脚印
页:
[1]