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 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 18

前端加密闻所未闻 :sweat_smile:

5个月前 评论
chaofu (楼主) 5个月前
Dash007 (作者) 5个月前

你这是生怕别人不知道密钥啊

5个月前 评论

这种加密不太安全,应该采用“信封”模式比较好些。

5个月前 评论
chaofu (楼主) 5个月前

发错版块了

5个月前 评论

可以用rsa加密密码,后端再解密

5个月前 评论

不是这样的流程的。首先前端从后端接口获取RSA公钥,然后使用公钥加密数据,例如密码或者提交的数据都可以,然后后端拿到数据后,中间件或者函数内使用RSA私钥解密,然后进行下一步操作。

5个月前 评论
chaofu (楼主) 5个月前

多此一举,只能防君子

5个月前 评论
chaofu (楼主) 5个月前

客户端存秘钥就不安全

5个月前 评论

这样前端是不是泄露 秘钥了

5个月前 评论

前端加密,会把加密代码暴漏在外面,你后端能解密,别人也能解密,图个啥

5个月前 评论
我们只希望世界和平 5个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
78
粉丝
8
喜欢
43
收藏
49
排名:82
访问:10.4 万
私信
所有博文
社区赞助商