vue cbc 加密,go 后端解密
<template>
<div>
<textarea v-model="plaintext" placeholder="Enter plaintext"></textarea>
<textarea v-model="plaintext2" placeholder="Enter plaintext"></textarea>
<button @click="encrypt">Encrypt</button>
<button @click="DecryptAES">DecryptAES</button>
<p>Encrypted: {{ encryptedText }}</p>
<p>IV: {{ iv }}</p>
</div>
</template>
<script>
import CryptoJS from 'crypto-js';
export default {
data() {
return {
plaintext: 'Hello, AES!',
plaintext2:'',
encryptedText: '',
iv: '1234567890123456',
key: '1234567890123456', // 密钥应该是 16/24/32 个字节
};
},
methods: {
encrypt() {
// 生成随机 IV
console.log("key22===",this.key)
if (this.key && this.iv) {
this.key = CryptoJS.enc.Utf8.parse(this.key);
console.log("key===", this.key)
this.iv = CryptoJS.enc.Utf8.parse(this.iv);
console.log("iv===",this.iv)
}
let srcs = CryptoJS.enc.Utf8.parse(this.plaintext);
let encrypted = CryptoJS.AES.encrypt(srcs, this.key, {
iv: this.iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
this.encryptedText = encrypted.toString()
// 转换为16进制
let encryptedHex = CryptoJS.enc.Hex.stringify(encrypted.ciphertext);
console.log("Encrypted Hex: ", encryptedHex);
// 将十六进制字符串转换为字节数组
let wordArray = CryptoJS.enc.Hex.parse(encryptedHex);
// 将字节数组转换为二进制字符串
let binaryString = '';
for (let i = 0; i < wordArray.sigBytes; i++) {
let byte = wordArray.words[wordArray.sigBytes - 1 - i] >>> 24 - (i % 4 * 8);
binaryString += ('00000000' + byte.toString(2)).slice(-8);
}
console.log("binaryString Hex: ",binaryString);
return encrypted.toString();
},
DecryptAES() {
// key 和 iv 使用同一个值
const decrypted = CryptoJS.AES.decrypt(this.encryptedText, this.key, {
iv: this.key,
mode: CryptoJS.mode.CBC, // CBC算法
padding: CryptoJS.pad.Pkcs7, //使用pkcs7 进行padding 后端需要注意
});
console.log("ddddddd",decrypted.toString(CryptoJS.enc.Utf8))
this.plaintext2 = decrypted.toString(CryptoJS.enc.Utf8);
}
}
};
</script>
后端解密
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
"fmt"
)
const sKey = "1234567890123456"
//pkcs7Padding 填充
func pkcs7Padding(data []byte, blockSize int) []byte {
//判断缺少几位长度。最少1,最多 blockSize
padding := blockSize - len(data)%blockSize
//补足位数。把切片[]byte{byte(padding)}复制padding个
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
//pkcs7UnPadding 填充的反向操作
func pkcs7UnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("加密字符串错误!")
}
//获取填充的个数
unPadding := int(data[length-1])
return data[:(length - unPadding)], nil
}
//AesEncrypt 加密
func AesEncrypt(data []byte) ([]byte, error) {
key := []byte(sKey)
//创建加密实例
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
//判断加密块的大小
blockSize := block.BlockSize()
//填充
encryptBytes := pkcs7Padding(data, blockSize)
//初始化加密数据接收切片
crypted := make([]byte, len(encryptBytes))
//使用cbc加密模式
fmt.Printf("31232131===%s\n", key[:blockSize])
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
//执行加密
blockMode.CryptBlocks(crypted, encryptBytes)
return crypted, nil
}
//AesDecrypt 解密
func AesDecrypt2(data []byte) ([]byte, error) {
key := []byte(sKey)
//创建实例
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
//获取块的大小
blockSize := block.BlockSize()
//使用cbc 这里这个 iv = key[:blockSize] 相当前端设置跟 key 一样
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
//初始化解密数据接收切片
crypted := make([]byte, len(data))
//执行解密
blockMode.CryptBlocks(crypted, data)
//去除填充
crypted, err = pkcs7UnPadding(crypted)
if err != nil {
return nil, err
}
return crypted, nil
}
func main() {
s := []byte("Hello, AES!")
ss, err := AesEncrypt(s)
if err != nil {
fmt.Printf("AesEncrypt: %v\n", err)
}
mw := base64.StdEncoding.EncodeToString(ss)
fmt.Printf("加密后: %s\n", mw)
mwb, _ := base64.StdEncoding.DecodeString("VowXT9KIzk8031LVI5rs5Q==")
s, err = AesDecrypt2(mwb)
if err != nil {
fmt.Printf("解密后: %v\n", err)
}
fmt.Printf("解密后: %s\n", s)
}
// 所以 iv 跟 key 的长度要一致
// iv: '1234567890123456', 16位
// key: '1234567890123457', 16位 两个可不同,但长度一样
func NewCBCDecrypter(b Block, iv []byte) BlockMode {
if len(iv) != b.BlockSize() {
panic("cipher.NewCBCDecrypter: IV length must equal block size")
}
if cbc, ok := b.(cbcDecAble); ok {
return cbc.NewCBCDecrypter(iv)
}
return (*cbcDecrypter)(newCBC(b, iv))
func AesDecrypt(str string) string {
// 将加密字符串转换为字节数组
encryptedData, _ := base64.StdEncoding.DecodeString(str)
// 创建一个新的AES解密器
key := []byte("1234567890123456") // 密钥与前端保持一致
iv := []byte("1234567890123457") // 偏移量与前端保持一致
block, _ := aes.NewCipher(key)
// 使用CBC模式解密
mode := cipher.NewCBCDecrypter(block, iv)
decryptedData := make([]byte, len(encryptedData))
mode.CryptBlocks(decryptedData, encryptedData)
// 移除填充
fmt.Println("decryptedData===",decryptedData)
padding := int(decryptedData[len(decryptedData)-1])
fmt.Println("padding===",padding)
fmt.Println("len(decryptedData)===",len(decryptedData))
decryptedData = decryptedData[:len(decryptedData)-padding]
// 将解密后的字节数组转换为字符串
decryptedStr := string(decryptedData)
return decryptedStr
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
:+1:
前端加密闻所未闻 :sweat_smile:
你这是生怕别人不知道密钥啊
这种加密不太安全,应该采用“信封”模式比较好些。
发错版块了
可以用rsa加密密码,后端再解密
不是这样的流程的。首先前端从后端接口获取RSA公钥,然后使用公钥加密数据,例如密码或者提交的数据都可以,然后后端拿到数据后,中间件或者函数内使用RSA私钥解密,然后进行下一步操作。
多此一举,只能防君子
客户端存秘钥就不安全
这样前端是不是泄露 秘钥了
github.com/webguosai/cryptojs-aes
前端加密,会把加密代码暴漏在外面,你后端能解密,别人也能解密,图个啥