You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js转Golang实现AES-256-CBC-HMAC-SHA1解密适配问题

适配Node.js AES-256-CBC-HMAC-SHA1解密逻辑到Golang

我来帮你把这段Node.js的解密逻辑完整适配到Golang里,先拆解一下Node.js代码的核心行为,再对应实现:

Node.js代码核心分析

你的Node.js代码做了这几件关键的事:

  • 使用aes-256-cbc-hmac-sha1算法(核心是AES-256-CBC解密,算法名包含HMAC-SHA1但你的代码里没显式做认证验证)
  • 关闭自动填充(setAutoPadding(false)),意味着解密数据必须是AES块大小(16字节)的整数倍,且不需要移除PKCS7填充
  • 从binary编码的输入数据解密,输出UTF-8字符串

Golang完整实现代码

下面是完全对应上述逻辑的Golang代码,包含基础解密和可选的HMAC验证:

基础解密(对应你的Node.js代码核心)

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"fmt"
)

// decryptAES256CBC 对应Node.js的解密逻辑:AES-256-CBC + 无自动填充 + 字节转UTF-8
func decryptAES256CBC(derivedKey []byte, iv []byte, encryptedData []byte) (string, error) {
	// 验证AES-256密钥长度(必须32字节)
	if len(derivedKey) != 32 {
		return "", fmt.Errorf("invalid AES-256 key: expected 32 bytes, got %d", len(derivedKey))
	}
	// 验证IV长度(必须等于AES块大小16字节)
	if len(iv) != aes.BlockSize {
		return "", fmt.Errorf("invalid IV: expected %d bytes, got %d", aes.BlockSize, len(iv))
	}
	// 验证加密数据长度(无自动填充要求必须是块大小的整数倍)
	if len(encryptedData)%aes.BlockSize != 0 {
		return "", fmt.Errorf("encrypted data length must be multiple of %d bytes", aes.BlockSize)
	}

	// 创建AES cipher实例,对应Node.js的createDecipheriv初始化
	block, err := aes.NewCipher(derivedKey)
	if err != nil {
		return "", fmt.Errorf("failed to create AES cipher: %w", err)
	}

	// 创建CBC解密器,对应Node.js的CBC模式
	mode := cipher.NewCBCDecrypter(block, iv)

	// 执行解密(无自动填充,直接解密所有数据)
	decryptedBytes := make([]byte, len(encryptedData))
	mode.CryptBlocks(decryptedBytes, encryptedData)

	// 转成UTF-8字符串,对应Node.js的utf8输出格式
	return string(decryptedBytes), nil
}

func main() {
	// 替换成你的实际数据
	derivedKey := []byte("your-32-byte-derived-key-example")
	iv := []byte("your-16-byte-iv-example")
	// encryptedData对应Node.js里的new_buf(binary编码即原始字节)
	encryptedData := []byte("your-encrypted-binary-data-here")

	result, err := decryptAES256CBC(derivedKey, iv, encryptedData)
	if err != nil {
		fmt.Printf("Decryption failed: %v\n", err)
		return
	}
	fmt.Printf("Decrypted result: %s\n", result)
}

可选:HMAC-SHA1验证(对应算法名里的HMAC部分)

如果你的Node.js代码实际需要验证HMAC(算法名包含hmac-sha1),说明derived密钥可能是AES密钥+HMAC密钥的组合(比如前32字节是AES密钥,后20字节是HMAC密钥),可以补充以下验证逻辑:

import (
	"crypto/hmac"
	"crypto/sha1"
)

// decryptAndVerify 解密+验证HMAC-SHA1
func decryptAndVerify(derivedKey []byte, iv []byte, encryptedData []byte, hmacValue []byte) (string, error) {
	// 验证组合密钥长度(32字节AES + 20字节HMAC-SHA1密钥)
	if len(derivedKey) != 32+20 {
		return "", fmt.Errorf("invalid derived key: expected 52 bytes, got %d", len(derivedKey))
	}
	aesKey := derivedKey[:32]
	hmacKey := derivedKey[32:]

	// 先执行解密
	decryptedStr, err := decryptAES256CBC(aesKey, iv, encryptedData)
	if err != nil {
		return "", err
	}

	// 验证HMAC-SHA1
	mac := hmac.New(sha1.New, hmacKey)
	mac.Write([]byte(decryptedStr))
	expectedHMAC := mac.Sum(nil)
	if !hmac.Equal(expectedHMAC, hmacValue) {
		return "", fmt.Errorf("HMAC verification failed")
	}

	return decryptedStr, nil
}

关键对应点说明

  • 无自动填充:Golang里不需要额外处理填充,直接用CryptBlocks解密即可,和Node.js的setAutoPadding(false)行为完全一致
  • 编码转换:Node.js里的binary输入对应Golang的[]byte,解密后的字节直接转字符串就是UTF-8格式,和Node.js的输出一致
  • 密钥/IV长度:严格遵循AES-256和CBC模式的要求,避免出现解密失败的情况

内容的提问来源于stack exchange,提问作者Darksorrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:09:46