首页 > 其他分享 >AES 加解密(前后端)

AES 加解密(前后端)

时间:2024-03-15 20:56:16浏览次数:23  
标签:crypted decrypted AES 前后 加解密 iv key byte 123456

AES 加解密(前后端)

加密

前端加密:

aesEncrypt(plainText: string, key: string) {
    const key = CryptoJS.enc.Latin1.parse(key);
    const iv = CryptoJS.enc.Latin1.parse('1234567890123456');
    const encrypted = CryptoJS.AES.encrypt(plainText, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding // CryptoJS.pad.ZeroPadding, CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}

调用时的打印结果:

// padding = CryptoJS.pad.ZeroPadding
aesEncrypt("123456", "ABCDEFGHIJKLMNOP"); // 83MCLn7rL5/P2eXEyBzPDQ==
aesEncrypt("123456", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // ebUKt3ZWeU78On/hns7W1w==

// padding = CryptoJS.pad.Pkcs7
aesEncrypt("123456", "ABCDEFGHIJKLMNOP"); // d1R21TsRewTG3mRIeYnIWw==
aesEncrypt("123456", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // uCvloRIqYLLJauF5EpIuGA==

// 
aesEncrypt("123456"); // padding = CryptoJS.pad.NoPadding -> 83MCLn7r

后端PHP加密,OPENSSL_ZERO_PADDING 方式(0补位,不推荐这种方式,所以补位的逻辑需要自行实现):

$key = 'ABCDEFGHIJKLMNOP';
$iv = '1234567890123456';
$blockSize = 16;
$planText = "123456";
if (strlen($planText) % $blockSize) {
    $planText = str_pad($planText, strlen($planText) + $blockSize - strlen($planText) % $blockSize, "\0");
}
// key 是 16 位,对应 AES-128-CBC
$encrypted = openssl_encrypt($planText, "AES-128-CBC", $key, OPENSSL_ZERO_PADDING, $iv); // 83MCLn7rL5/P2eXEyBzPDQ==

// key 是 32 位,对应 AES-256-CBC
$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = openssl_encrypt($planText, "AES-256-CBC", $key, OPENSSL_ZERO_PADDING, $iv); // ebUKt3ZWeU78On/hns7W1w==

// 如果 key 是 24 位的,对应的是 AES-192-CBC

后端PHP加密,OPENSSL_RAW_DATA 方式(PKCS7补位):

// https://www.php.net/manual/zh/openssl.constants.other.php#constant.openssl-raw-data
// openssl_encrypt 中如果设置了 OPENSSL_RAW_DATA 将原样返回,没有设置时返回的是 base64
$encrypted = openssl_encrypt($planText, "AES-128-CBC", $key, OPENSSL_RAW_DATA, $iv);
// 需要 base64_encode 一下
$encrypted = base64_encode($encrypted); // d1R21TsRewTG3mRIeYnIWw==

$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = openssl_encrypt($planText, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
$encrypted  = base64_encode($encrypted); // uCvloRIqYLLJauF5EpIuGA==

后端 go 加密,PKCS7:

// AesEncrypt 加密
func AesEncrypt(plainText string, key string, iv string) (string, error) {
	// 创建加密实例
	keyBytes := []byte(key)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", err
	}
	data := []byte(plainText)
	ivBytes := []byte(iv) // 不使用手动指定的 iv 时,可以使用 key 的前 blockSize 位
	// 加密快的大小
	blockSize := block.BlockSize()
	// 填充
	encryptBytes := pkcs7Padding(data, blockSize)
	// 初始化加密数据接收切片
	crypted := make([]byte, len(encryptBytes))
	// CBC 加密模式
	blockMode := cipher.NewCBCEncrypter(block, ivBytes)
	// 加密
	blockMode.CryptBlocks(crypted, encryptBytes)
	// 转为 base64 格式
	return base64.StdEncoding.EncodeToString(crypted), nil
}

// pkcs7Padding 填充
func pkcs7Padding(data []byte, blockSize int) []byte {
	// 补位长度,最少1,最多 blockSize
	padding := blockSize - len(data)%blockSize
	// 补位 padding 个 padding
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}

func main() {
	key := "ABCDEFGHIJKLMNOP"
	iv := "1234567890123456"
	crypted, _ := AesEncrypt("123456", key, iv)
	fmt.Println("crypted =", crypted) // crypted = d1R21TsRewTG3mRIeYnIWw==

    key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
	crypted, _ = aes.AesEncrypt("123456", key, iv)
	fmt.Println("key = ", key, ", crypted =", crypted) // crypted = uCvloRIqYLLJauF5EpIuGA==
}

零补位时,padText := bytes.Repeat([]byte{byte(padding)}, padding)​ -> padText := bytes.Repeat([]byte{0}, padding)​:

// 方法名 zeroPadding
func zeroPadding(data []byte, blockSize int) []byte {
	// 补位长度,最少1,最多 blockSize
	padding := blockSize - len(data)%blockSize
	// 补位 padding 个 padding
	padText := bytes.Repeat([]byte{0}, padding)
	return append(data, padText...)
}

func main() {
	key := "ABCDEFGHIJKLMNOP"
	iv := "1234567890123456"
	crypted, _ := AesEncrypt("123456", key, iv)
	fmt.Println("crypted =", crypted) // crypted = 83MCLn7rL5/P2eXEyBzPDQ==

    key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
	crypted, _ = aes.AesEncrypt("123456", key, iv)
	fmt.Println("key = ", key, ", crypted =", crypted) // crypted = ebUKt3ZWeU78On/hns7W1w==
}

解密

前端解密:

aesDecrypt(encrypted: string, key: string) {
    const SECRET_KEY  = CryptoJS.enc.Latin1.parse(key);
    const SECRET_IV = CryptoJS.enc.Latin1.parse('1234567890123456');
    const decrypted = CryptoJS.AES.decrypt(encrypted, SECRET_KEY, {
        iv: SECRET_IV,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding // CryptoJS.pad.ZeroPadding, CryptoJS.pad.Pkcs7
    });

    return decrypted.toString(CryptoJS.enc.Utf8);
}

打印结果:

// padding = CryptoJS.pad.ZeroPadding
aesDecrypt("83MCLn7rL5/P2eXEyBzPDQ==", "ABCDEFGHIJKLMNOP")); // 123456
aesDecrypt("ebUKt3ZWeU78On/hns7W1w==", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // 123456


// padding = CryptoJS.pad.Pkcs7
aesDecrypt("d1R21TsRewTG3mRIeYnIWw==", "ABCDEFGHIJKLMNOP"))
aesDecrypt("uCvloRIqYLLJauF5EpIuGA==", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")

后端PHP解密,OPENSSL_ZERO_PADDING 方式:

$key = 'ABCDEFGHIJKLMNOP';
$iv = '1234567890123456';
$encrypted = '83MCLn7rL5/P2eXEyBzPDQ==';
$decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $iv); // 123456\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
// 去除补位的 0
$decrypted = rtrim($decrypted, chr(0)); // 123456

$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = 'ebUKt3ZWeU78On/hns7W1w==';
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_ZERO_PADDING, $iv); // 123456\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
$decrypted = rtrim($decrypted, chr(0)); // 123456

后端PHP解密,OPENSSL_RAW_DATA 方式:

$iv = '1234567890123456';
$key = 'ABCDEFGHIJKLMNOP';
$encrypted = 'd1R21TsRewTG3mRIeYnIWw==';
$decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); // 123456

$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = 'uCvloRIqYLLJauF5EpIuGA==';
$decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); // 123456

后端 go 解密,PKCS7:

// AesDecrypt 解密
func AesDecrypt(cryptedText string, key string, iv string) (string, error) {
	data, err := base64.StdEncoding.DecodeString(cryptedText)
	if err != nil {
		return "", err
	}

	keyBytes := []byte(key)
	// 创建实例
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", err
	}
	ivBytes := []byte(iv)
	blockMode := cipher.NewCBCDecrypter(block, ivBytes)
	// 初始化解密数据接收切片
	crypted := make([]byte, len(data))
	// 解密
	blockMode.CryptBlocks(crypted, data)
	// 去除填充
	crypted, err = pkcs7UnPadding(crypted)
	if err != nil {
		return "", err
	}
	return string(crypted), nil
}

// 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
}

func main() {
	key := "ABCDEFGHIJKLMNOP"
	iv := "1234567890123456"
	decrypted, _ := AesDecrypt("d1R21TsRewTG3mRIeYnIWw==", key, iv)
	fmt.Println("decrypted =", decrypted) // decrypted = 123456

	key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
	decrypted, _ = AesDecrypt("uCvloRIqYLLJauF5EpIuGA==", key, iv)
	fmt.Println("decrypted =", decrypted) // decrypted = 123456
}

零补位时,补位的长度需要计算

// ZeroUnpadding
func ZeroUnPadding(data []byte) ([]byte, error) {
	length := len(data)
	if length == 0 {
		return nil, errors.New("加密字符串错误!")
	}
	unPadding := 0
	for i := length - 1; i >= 0; i-- {
		if data[i] == 0 {
			unPadding++
		} else {
			break
		}
	}
	if unPadding == 0 {
		return nil, errors.New("加密字符串错误,没有补位长度!")
	}
	return data[:length-unPadding], nil
}

func main() {
	key := "ABCDEFGHIJKLMNOP"
	iv := "1234567890123456"
	decrypted, _ := AesDecrypt("83MCLn7rL5/P2eXEyBzPDQ==", key, iv)
	fmt.Println("decrypted =", decrypted) // decrypted = 123456

	key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
	decrypted, _ = AesDecrypt("ebUKt3ZWeU78On/hns7W1w==", key, iv)
	fmt.Println("decrypted =", decrypted) // decrypted = 123456
}

标签:crypted,decrypted,AES,前后,加解密,iv,key,byte,123456
From: https://www.cnblogs.com/zhpj/p/18076219/aes-decryption-front-and-back-1efs19

相关文章

  • 前后端分离Ajax入门
    前后端分离之Ajax入门一、概念Ajax(AsynchronousJavascriptAndXML),即是异步的JavaScript和XML,Ajax其实就是浏览器与服务器之间的一种异步通信方式。它可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,在这种情况下,浏览器可以做自己的事情。直到成功获取响应后,浏......
  • 【Django开发】前后端分离美多商城项目第2篇:项目准备【附代码文档】
    美多商城项目4.0文档完整教程(附代码资料)主要内容讲述:美多商城,项目准备,商业模式介绍,开发流程,需求分析,项目架构,创建工程,1.在git平台创建工程1.B2B--企业对企业,2.C2C--个人对个人,3.B2C--企业对个人,4.C2B--个人对企业,5.O2O--线上到线下,6.F2C--工厂到个人,7.B2B2C--企业--企业--......
  • 【若依前后端分离+app】app页面首页添加动态轮播图
    首页文件路径:pages/work/index.vue1. Vue组件的模板部分包括创建模板、视图容器、视图、轮播图组件以及相关的属性和事件监听器。以下部分为轮播图代码:<template><viewclass="work-container"><view><!--轮播图--><uni-swiper-dotclass="uni-s......
  • Java基于 Springboot+Vue 的招生管理系统,前后端分离
    博主介绍:✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌......
  • 一款针对加解密综合利用后渗透工具-DecryptTools
    0x01前言为什么会写这一款综合加解密工具,因为在很多比赛如果算拿下靶标不仅需要获取服务器权限还需要登录网站后台这时候很多系统要么数据库连接字符串加密,要么登陆用户加密而这款工具就是为了解决问题。加解密功能:该工具不仅有解密还提供多种加密方式。配置文件信息功......
  • 前后端分离之Ajax入门
    前后端分离之Ajax入门一、概念Ajax(AsynchronousJavascriptAndXML),即是异步的JavaScript和XML,Ajax其实就是浏览器与服务器之间的一种异步通信方式。它可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,在这种情况下,浏览器可以做自己的事情。直到成功获取响应后,浏......
  • mPaas抓包分析和数据加解密
    mPaaS是阿里研发的一个移动开发平台,其中移动网关服务(MobileGatewayService,简称MGS)作为mPaas最重要的组件之一,连接了移动客户端与服务端,简化了移动端与服务端的数据协议和通讯协议,从而能够显著提升开发效率和网络通讯效率。通过RPC组件进行网络请求,并且可以设置拦截器拦截请求......
  • 【Django开发】前后端分离美多商城项目第1篇:美多商城【附代码文档】
    美多商城项目4.0文档完整教程(附代码资料)主要内容讲述:美多商城,项目准备,商业模式介绍,开发流程,需求分析,项目架构,创建工程,1.在git平台创建工程1.B2B--企业对企业,2.C2C--个人对个人,3.B2C--企业对个人,4.C2B--个人对企业,5.O2O--线上到线下,6.F2C--工厂到个人,7.B2B2C--企业--企业--......
  • 前后端联调-前端返回包含数组导致后端无法接收~解决
    问题:.HttpMessageNotReadableException:JSONparseerror:Cannotdeserializevalueoftype`java.lang.String`fromArrayvalue(token`JsonToken.START_ARRAY`);nestedexceptioniscom.fasterxml.jackson.databind.exc.MismatchedInputException:Cannotdeseriali......
  • 03-前后端数据传输格式-下
    请求:JSON转换为Java对象响应:Java对象转换为JSONJSON想完成跨内存(浏览器/服务器、服务器/服务器)的数据传输、对象转换,必须经过网络传输,而且需要一个传递信息的载体,还需要序列化和反序列化的操作传递信息的载体JSON简单来说就是特定格式的字符串,JSON的载体就是字符串。JS对......