AES CBC:JavaScript/CryptoJS 加密 -> Golang 解密
AES CBC: JavaScript/CryptoJS Encrypt -> Golang Decrypt
注意:这仅供个人使用和学习,我并没有尝试为 public 使用自己的加密。
我需要 AES256 加密一个字符串,但是我当前的尝试在十六进制解码时以 Salted__Vέ��|��l��ʼ8XCQlY
服务器端这样的字符串结束。十六进制解码后,它应该是一个有效的 utf8 base64 字符串,然后可以将其解码为原始字符串。这类似于 提供的解决方案,但是盐不是实际问题(尽管答案被接受)并且我无法通过在使用前对 iv 进行十六进制解码来抑制盐操作(正如它所建议的那样) ).有办法吗?
我尝试了几种不同的方法,但总是以相似的方式结束。我最近的尝试是这样的:
encrypt.js
// CryptoJS.pad.NoPadding={pad:function(){},unpad:function(){}};
const SECRET = '394812730425442A472D2F423F452848';
const iv = crypto.getRandomValues(new Uint8Array(16));
function enc(plainText) {
var b64 = CryptoJS.AES.encrypt(plainText, SECRET, {
iv,
mode: CryptoJS.mode.CBC,
// padding: CryptoJS.pad.NoPadding
}).toString();
// Don't need?
//var e64 = CryptoJS.enc.Base64.parse(b64);
//var eHex = e64.toString(CryptoJS.enc.Hex);
console.log("b64::", b64);
return b64;
}
enc("SUPA_SECRET");
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
现在我们将b64
结果粘贴到服务器端golang decrypt中的JS_GEN
变量中:
decrypt.go
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"fmt"
)
func main() {
JS_GEN := "U2FsdGVkX1+CA3LZTXePlgoGqL8VkdgiDgUenZhH4kc="
SECRET := "394812730425442A472D2F423F452848"
//msg := "SUPER_SECRET"
res, err := DecryptCBC(SECRET, JS_GEN)
if err != nil {
fmt.Println(err)
}
fmt.Println("res::", res)
}
func DecryptCBC(secret string, target string) (string, error) {
nilString := ""
key, _ := hex.DecodeString(secret)
//ciphertext, err := base64.URLEncoding.DecodeString(target)
// Decode base64 string
ciphertext, err := base64.StdEncoding.DecodeString(target)
if err != nil {
return nilString, err
}
// Create new cipher block
block, err := aes.NewCipher(key)
if err != nil {
return nilString, err
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
// CBC mode always works in whole blocks.
if len(ciphertext)%aes.BlockSize != 0 {
panic("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, ciphertext)
fmt.Println("ciphertext::", ciphertext)
// Output: exampleplaintext
return string(ciphertext), nil
}
输出将类似于:
ciphertext:: [136 227 244 124 124 92 162 254 1 147 235 213 8 136 129 150]
res:: ���||\�������
我做错了什么?
编辑: 我已经从进程中删除了十六进制 encode/decode。
您似乎在 JavaScript(默认)中使用 CBC 模式,但在 golang 中使用 CFB。请尝试使用 NewCBCDecrypter
。
我仍然不完全确定为什么之前的尝试都失败了。它可能是实现加密的多种不同方式之一 and/or 在服务器和客户端上配置。
我终于找到了我要找的东西。开箱即用的简单实现。这里我们只使用 crypto-js and go-openssl.
client.js
const msg = "SUPA_SECRET"
const key = "394812730425442A472D2F423F452848";
const encrypted = CryptoJS.AES.encrypt(msg, key);
console.log(encrypted.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
server.go
package main
import (
"fmt"
"github.com/Luzifer/go-openssl"
)
func main() {
encrypted := "ENCRYPTED_STRING_HERE"
secret := "394812730425442A472D2F423F452848"
o := openssl.New()
dec, err := o.DecryptBytes(secret, []byte(encrypted), openssl.DigestMD5Sum)
if err != nil {
fmt.Printf("An error occurred: %s\n", err)
}
fmt.Printf("Decrypted text: %s\n", string(dec))
}
// OUTPUT:
// Decrypted text: SUPA_SECRET
注意:这仅供个人使用和学习,我并没有尝试为 public 使用自己的加密。
我需要 AES256 加密一个字符串,但是我当前的尝试在十六进制解码时以 Salted__Vέ��|��l��ʼ8XCQlY
服务器端这样的字符串结束。十六进制解码后,它应该是一个有效的 utf8 base64 字符串,然后可以将其解码为原始字符串。这类似于
我尝试了几种不同的方法,但总是以相似的方式结束。我最近的尝试是这样的:
encrypt.js
// CryptoJS.pad.NoPadding={pad:function(){},unpad:function(){}};
const SECRET = '394812730425442A472D2F423F452848';
const iv = crypto.getRandomValues(new Uint8Array(16));
function enc(plainText) {
var b64 = CryptoJS.AES.encrypt(plainText, SECRET, {
iv,
mode: CryptoJS.mode.CBC,
// padding: CryptoJS.pad.NoPadding
}).toString();
// Don't need?
//var e64 = CryptoJS.enc.Base64.parse(b64);
//var eHex = e64.toString(CryptoJS.enc.Hex);
console.log("b64::", b64);
return b64;
}
enc("SUPA_SECRET");
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
现在我们将b64
结果粘贴到服务器端golang decrypt中的JS_GEN
变量中:
decrypt.go
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"fmt"
)
func main() {
JS_GEN := "U2FsdGVkX1+CA3LZTXePlgoGqL8VkdgiDgUenZhH4kc="
SECRET := "394812730425442A472D2F423F452848"
//msg := "SUPER_SECRET"
res, err := DecryptCBC(SECRET, JS_GEN)
if err != nil {
fmt.Println(err)
}
fmt.Println("res::", res)
}
func DecryptCBC(secret string, target string) (string, error) {
nilString := ""
key, _ := hex.DecodeString(secret)
//ciphertext, err := base64.URLEncoding.DecodeString(target)
// Decode base64 string
ciphertext, err := base64.StdEncoding.DecodeString(target)
if err != nil {
return nilString, err
}
// Create new cipher block
block, err := aes.NewCipher(key)
if err != nil {
return nilString, err
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
// CBC mode always works in whole blocks.
if len(ciphertext)%aes.BlockSize != 0 {
panic("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, ciphertext)
fmt.Println("ciphertext::", ciphertext)
// Output: exampleplaintext
return string(ciphertext), nil
}
输出将类似于:
ciphertext:: [136 227 244 124 124 92 162 254 1 147 235 213 8 136 129 150]
res:: ���||\�������
我做错了什么?
编辑: 我已经从进程中删除了十六进制 encode/decode。
您似乎在 JavaScript(默认)中使用 CBC 模式,但在 golang 中使用 CFB。请尝试使用 NewCBCDecrypter
。
我仍然不完全确定为什么之前的尝试都失败了。它可能是实现加密的多种不同方式之一 and/or 在服务器和客户端上配置。
我终于找到了我要找的东西。开箱即用的简单实现。这里我们只使用 crypto-js and go-openssl.
client.js
const msg = "SUPA_SECRET"
const key = "394812730425442A472D2F423F452848";
const encrypted = CryptoJS.AES.encrypt(msg, key);
console.log(encrypted.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
server.go
package main
import (
"fmt"
"github.com/Luzifer/go-openssl"
)
func main() {
encrypted := "ENCRYPTED_STRING_HERE"
secret := "394812730425442A472D2F423F452848"
o := openssl.New()
dec, err := o.DecryptBytes(secret, []byte(encrypted), openssl.DigestMD5Sum)
if err != nil {
fmt.Printf("An error occurred: %s\n", err)
}
fmt.Printf("Decrypted text: %s\n", string(dec))
}
// OUTPUT:
// Decrypted text: SUPA_SECRET