如何在 javascript 中翻译 Go des 代码

Posted

技术标签:

【中文标题】如何在 javascript 中翻译 Go des 代码【英文标题】:How to translate Go des code in javascript 【发布时间】:2021-02-23 06:22:41 【问题描述】:

我想在 javascript 中翻译 Go DES 代码

这是我的 Go 代码,使用 des zeropadding 进行加密。现在想用javascript来获取同样的功能,但是试了很多次,结果总是错。

package zeropadding

import (
    "crypto/cipher"
    "crypto/des"
    "encoding/hex"
    "fmt"
    "strings"
)

func main() 
    text := DesEncrypt([]byte("12345678"), []byte("12345678"))
    fmt.Println(strings.ToUpper(hex.EncodeToString(text)))


func DesEncrypt(origData, key []byte) []byte 
    iv := []byte0, 0, 0, 0, 0, 0, 0, 0
    block, err := des.NewCipher(key)
    if err != nil 
        return nil
    
    origData = ZeroPadding(origData)
    blockMode := cipher.NewCBCEncrypter(block, iv)
    crypted := make([]byte, len(origData))
    blockMode.CryptBlocks(crypted, origData)
    return crypted


func ZeroPadding(in []byte) []byte 
    length := len(in)

    blockCount := length / 8
    out := make([]byte, (blockCount+1)*8)
    var i int
    for i = 0; i < length; i++ 
        out[i] = in[i]
    
    return out


如何使用javascript来做到这一点

const CryptoJS = require('./crypto-js.min')

function encryptByDES(message, key, iv) 
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    var ivHex = CryptoJS.enc.Utf8.parse(iv);
    encrypted = CryptoJS.DES.encrypt(message, keyHex, 
            iv: ivHex,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.ZeroPadding
        
    );
    return encrypted.ciphertext.toString();


console.log(encryptByDES("12345678", "12345678", 0))

我使用 lib crypto-js,使用模式 CryptoJS.mode.CBC 和填充 CryptoJS.pad.ZeroPadding,但结果与 Go 代码输出不相等。

【问题讨论】:

如果明文的长度已经是块大小的整数倍,CryptoJS 代码不会附加 0x00 值的完整块(DES 为 8 字节),Golang 代码会这样做。此外,在零向量的 CryptoJS 代码中,不要将 0 作为 IV 传递,而是传递 "\0\0\0\0\0\0\0\0"。请注意,这两个代码都是不安全的:DES 是不安全的,并且已经存在了大约 20 年。使用静态 IV 也是不安全的。零填充是不可靠的。更好地应用 AES,为每个加密和 PKCS7 填充随机生成的 IV。 【参考方案1】:

您的 go 代码和 javascript 似乎都存在问题,这可能会造成混淆。 (警告 - 我远不是加密专家!)。

零填充应该将 []byte 填充为块大小的倍数(在您的情况下为 8),但如果输入长度为 8 个字节,您将填充到 16 个字节。试试:

blockCount := (length - 1) / blockSize

Playground

Javascript

您将 IV 作为数字提供,但随后将其转换为 utf8。让我们镜像你在 go 中所做的事情:

var ivHex = CryptoJS.enc.Hex.parse(iv);

并将 IV 作为十六进制传递:

console.log(encryptByDES("1234567890", "12345678", "0000000000000000"))

Js Fiddle

【讨论】:

【参考方案2】:

另一种方法是使用WebAssembly(参见webassembly.org),考虑到:

你可以将你的 Go 项目编译成 wasm

  GOOS=js GOARCH=wasm go build -o main.wasm

(有关更多最佳实践,请参阅 Cesar William Alvarenga 中的“Best Practices for WebAssembly using GoLang (1.15+)”)

你可以call said wasm from your Javascript project

【讨论】:

我之前尝试过wasm,在chrome上运行正常,但需要在微信小程序中使用,不支持wasm @ihsusta 好的。那我就不知道了。我没有在你的问题中看到微信。

以上是关于如何在 javascript 中翻译 Go des 代码的主要内容,如果未能解决你的问题,请参考以下文章

go加密算法:CBC对称加密--3DES/AES

Go语言项目中使用zap日志库(翻译)

JavaScript与C#互通的DES加解密算法

Go语言实现对称加密算法AESDES3DES和非对称加密算法RSA

Go-AES算法详解与代码

DES加密实现(翻译自书籍《Wiley.Implementing.SSL.TLS.Using.Cryptography.and.PKI》)