ggdlove 发表于 2013-12-4 23:18:44

自己定义的二进制表,并且用它来实现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:28:19

本帖最后由 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
)温馨提示:
这两个程序是不定义符号位的。

Gu_xl 发表于 2013-12-17 13:59:53

论坛是个宝库,什么都有!只是你没有用心去找而已!

baseToDecimal 将一个字符串按BASE的做为基数的进制转换为十进制的整数值

decimalToBase 将一个整数转换成一个按BASE基数指定的进制的字符串值

ggdlove 发表于 2013-12-17 15:33:44

Gu_xl 发表于 2013-12-17 13:59 static/image/common/back.gif
论坛是个宝库,什么都有!只是你没有用心去找而已!

baseToDecimal 将一个字符串按BASE的做为基数的进制 ...

多谢Gu版指导,还没有去函数宝库看过,惭愧。

ggdlove 发表于 2013-12-30 23:40:59

利用上面写的几个程序,就可以实现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)
)然后我们来看看执行的结果:

从结果可以看出,数据进行加密,然后再进行解密就还原了。程序是可行的!


baitang36 发表于 2021-6-23 13:24:54

留个脚印,备用

前生 发表于 2021-6-24 14:13:35


留个脚印,备用

baitang36 发表于 2022-12-24 18:19:57

前生 发表于 2021-6-24 14:13
留个脚印,备用

再留一个脚印
页: [1]
查看完整版本: 自己定义的二进制表,并且用它来实现DES加密算法