易语言支持库中的加密数据与解密数据
目录
易语言数据操作支持库一中存在这样一对算法函数
调用格式: 〈字节集〉 加密数据 (字节集 字节集数据,文本型 密码文本,[整数型 加密算法]) - 数据操作支持库一->数据加解密
英文名称:Encrypt
加密一段字节集数据,返回加密后的结果字节集。如果失败,返回空字节集。本命令为初级命令。
参数<1>的名称为“字节集数据”,类型为“字节集(bin)”。为命令提供所需的字节集数据。
参数<2>的名称为“密码文本”,类型为“文本型(text)”。
参数<3>的名称为“加密算法”,类型为“整数型(int)”,可以被省略。指定具体使用的加密算法,可以为以下常量值之一:1: #DES算法; 2: #RC4算法。加密和解密必须使用相同的算法,有关算法的具体说明请参阅有关文献。如果本参数被省略,则默认值为1,即DES算法。
调用格式: 〈字节集〉 解密数据 (字节集 字节集数据,文本型 密码文本,[整数型 加密算法]) - 数据操作支持库一->数据加解密
英文名称:Decrypt
解密一段加密后的字节集数据,返回解密后的结果字节集。注意本命令并不对密码文本进行校验,如果密码提供错误,将返回错误的结果。如果失败,返回空字节集。本命令为初级命令。
参数<1>的名称为“字节集数据”,类型为“字节集(bin)”。为命令提供所需的字节集数据。
参数<2>的名称为“密码文本”,类型为“文本型(text)”。
参数<3>的名称为“加密算法”,类型为“整数型(int)”,可以被省略。指定具体使用的加密算法,可以为以下常量值之一:1: #DES算法; 2: #RC4算法。加密和解密必须使用相同的算法,有关算法的具体说明请参阅有关文献。如果本参数被省略,则默认值为1,即DES算法。
这个函数里面的DES算法是不标准的,如果我们需要逆向算法或者移植语言,就会陷入坑中。。。。
根据别人研究的资料, 得知将密钥进行变换就可以对齐结果,实现Go语言代码如下:
package Utils
import (
"bytes"
"crypto/des"
"encoding/binary"
"math/bits"
)
func zeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext) % blockSize
padtext := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padtext...)
}
func E_加密数据_DES(加密数据 []byte,密码文本 string)([]byte,error) {
key := make([]byte,8)
//压缩密钥
sIndex := 0
for _,eKey := range 密码文本{
key[sIndex] = byte(eKey) ^ key[sIndex]
sIndex = sIndex + 1
if sIndex == 8{
sIndex = 0
}
}
//转换密钥
for n,_ := range key{
key[n] = bits.Reverse8(key[n])
}
block,err := des.NewCipher(key)
if err!=nil{
return nil,err
}
//需要在数据前面追加长度
inputData := make([]byte,4)
binary.LittleEndian.PutUint32(inputData,uint32(len(加密数据)))
inputData = append(inputData, 加密数据...)
inputData = zeroPadding(inputData,block.BlockSize())
//开始执行加密
encryptedData := make([]byte, len(inputData))
data := inputData
dst := encryptedData
bs := block.BlockSize()
for len(data) > 0 {
// Mandarin encryption is made according to blocksize
// Can use the Go key to encrypt
block.Encrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return encryptedData, nil
}
func E_解密数据_DES(解密数据 []byte,密码文本 string)([]byte,error) {
key := make([]byte,8)
//压缩密钥
sIndex := 0
for _,eKey := range 密码文本{
key[sIndex] = byte(eKey) ^ key[sIndex]
sIndex = sIndex + 1
if sIndex == 8{
sIndex = 0
}
}
//转换密钥
for n,_ := range key{
key[n] = bits.Reverse8(key[n])
}
block,err := des.NewCipher(key)
if err!=nil{
return nil,err
}
//开始执行解密
decryptedData := make([]byte, len(解密数据))
data := 解密数据
dst := decryptedData
bs := block.BlockSize()
for len(data) > 0 {
// Mandarin encryption is made according to blocksize
// Can use the Go key to encrypt
block.Decrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
//读取头部数据
recvLen := binary.LittleEndian.Uint32(decryptedData)
return decryptedData[4:recvLen+4], nil
}
另外附上一份别人写的python版本
from Crypto.Cipher import DES
import struct
def reverse_bytes(b):
assert type(b) == bytes
ba = bytearray(b)
for i in range(0, len(b)):
ba[i] = int(format(b[i], '0>8b')[::-1], 2)
return bytes(ba)
def get_new_key(key):
ba = bytearray(8)
i = 0
for b in key:
ba[i] = b ^ ba[i]
i = i + 1 if i < 8 else 0
return bytes(ba)
# zero padding
def padding(d):
ba = bytearray(d)
while len(ba) % 8 != 0:
ba.append(0)
return bytes(ba)
def append_len(d):
assert type(d) == bytes
length = struct.pack('<L', len(d))
return bytes(length + d)
def remove_len(d):
assert type(d) == bytes
return d[4:]
def e_des_encrypt(plain, key):
des = DES.new(reverse_bytes(get_new_key(key)), DES.MODE_ECB)
return des.encrypt(padding(append_len(plain)))
def e_des_decrypt(raw, key):
des = DES.new(reverse_bytes(get_new_key(key)), DES.MODE_ECB)
t = des.decrypt(raw)
return remove_len(t)
# 易语言:
# 输出调试文本(字节集_字节集到十六进制 (加密数据 (到字节集 (“123456789”), “123456789”, #DES算法)))
# 输出:
# 53DEE70DD231541839EB99553B8B056D
# --------------------------------
# python:
plain = b'123456789'
key = b'123456789'
ciph = e_des_encrypt(plain, key)
print(ciph.hex().upper())
print(e_des_decrypt(ciph, key).decode())
# 输出:
# 53DEE70DD231541839EB99553B8B056D123456789
# 123456789
参考资料
https://monvvv.github.io/2019/10/09/A-weird-way-of-DES-implementation-of-Elang.html