编码与加密(对称加密与非对称加密)

· 浏览次数 : 0

小编点评

本文主要介绍了不同类型的编码、加密方法和算法,以及它们在数据传输、存储和验证中的应用。 **主要内容概述如下**: 1. **编码与加密**: 介绍了Base64编码、十六进制编码、哈希算法、MD5、SHA-256、MAC算法和加密算法,以及它们的作用和场景。 2. **非对称加密**: 讨论了非对称加密算法,包括RSA、ECC、PEM格式存储密钥和DER格式存储密钥,以及它们的加密模式。 3. **对称加密**: 详细阐述了AES、DES、3DES和RC等对称加密算法,包括它们的密钥长度、加密和解密过程,以及它们在不同应用中的使用情况。 总的来说,本文全面涵盖了编码、加密和算法的相关知识,从基本概念到实际应用,为读者提供了一个清晰的学习框架。

正文

编码与加密

  • 只记录作用和场景使用,不探索原理(哥们数学不好.jpg
  • demo都是golang实现的

Base64编码(可逆)

它的主要作用是将二进制数据转换为文本格式,从而便于在文本传输通道中传递。
因为传输二进制数据时候比如在http中要以可见字符传输,所以需要将二进制数据编码为可见字符。

  • 标准 Base64 里的 64 个可打印字符是 A-Za-z0-9+/

    编码后长度是(n+2)/3*4
  • 如果待编码内容的字节数不是 3 的整数倍,那需要进行一些额外的处理。
    • 如果最后剩下 1 个字节,那么将补 4 个 0 位,编码成 2 个 Base64 字符,然后补两个 =:
    • 如果最后剩下 2 个字节,那么将补 2 个 0 位,编码成 3 个 Base64 字符,然后补一个 =:
  • URL Safe Base64 编码
    在 URL 的应用场景中,因为标准 Base64 索引表中的 / 和 + 会被 URLEncoder 转义成 %XX 形式,但 % 是 SQL 中的通配符,直接用于数据库操作会有问题。此时可以采用 URL Safe 的编码器
    将 + 替换为 -
    将 / 替换为 _
ans := make([]byte, base64.StdEncoding.EncodedLen(len("abcd")))
base64.StdEncoding.Encode(ans,[]byte("abcs"))//编码
fmt.Println(string(ans))
ans2 := make([]byte, base64.StdEncoding.DecodedLen(len(ans)))
base64.StdEncoding.Decode(ans2,ans)//解码
fmt.Println(string(ans2))

十六进制编码(hex.EncodeToString函数)(可逆)

将字节数组转换为十六进制字符串
将其每个字节转换为两个十六进制字符,并将结果组合成一个字符串返回。但是比base64长
对比base64是十六进制编码可以直接参与运算,且方便查看二进制数据

哈希算法(不可逆)

哈希算法(Hash Function) 是一种将任意长度的数据转换为固定长度的输出,该输出基于输入数据,且唯一对应于输入数据。哈希函数是单向函数,它将输入转换为固定长度的输出,而且不可逆。

  • 常见的哈希算法:MD5、SHA-1、SHA-256、SHA-384、SHA-512

MD5(不可逆)

返回定长16字节的128位bit哈希值
数据完整性校验:MD5算法常用于验证数据的完整性。在数据传输过程中,发送方可以计算数据的MD5哈希值并将其发送给接收方。接收方收到数据后,再次计算哈希值并与发送方提供的哈希值进行比较。如果两者匹配,则说明数据在传输过程中没有被篡改。
密码存储:MD5算法也常用于密码存储。将用户密码通过MD5哈希后存储在数据库中,即使数据库被泄露,攻击者也无法直接获取用户的明文密码。然而,由于MD5算法存在已知的安全漏洞(如彩虹表攻击和碰撞攻击),现在已不推荐使用MD5来存储密码。更安全的做法是使用加盐哈希

func Test_MD5(t *testing.T) {
    salt := "123456"//盐值
	s := "hello"//需要哈希的字符串
	h := md5.New()//创建一个md5对象
	h.Write([]byte(s)+[]byte(salt))//写入需要哈希的字符串
	fmt.Println(h.Sum(nil))//Sum把哈希值追加到参数*[]byte中,并返回
}

即使加盐,MD5 仍然可以被破解。加盐只是增加了破解的难度,但并没有解决 MD5 本身的安全缺陷。以下是详细的解释:
加盐的作用和局限性
增加破解难度:加盐主要是为了防止彩虹表攻击(即预计算哈希值的查找表)。通过加入随机盐值,每个输入的哈希结果都会有所不同,即使输入相同也会生成不同的哈希值,这使得预计算哈希表变得无效。
防止简单暴力破解:如果每个输入都带有唯一的盐值,攻击者不能一次破解多个哈希值,他们必须针对每个盐值单独进行暴力破解。
盐值和输入:盐值并不需要保密,通常与哈希值一起存储。然而,盐值的存在不会消除哈希算法的固有弱点。如果哈希算法易于碰撞(如 MD5),攻击者仍然可以利用这些弱点进行攻击。

SHA-256(不可逆)

返回定长32字节的256bit哈希值
SHA-256 是一种哈希算法,属于安全哈希算法(Secure Hash Algorithm)家族的一员,用于将任意长度的输入数据转换为固定长度(256 比特,即 32 字节)的哈希值。SHA-256 具有以下特点:

  • 不可逆性:无法通过哈希值反推出原始数据。
  • 固定输出长度:不论输入数据的长度如何,SHA-256 始终生成长度为 256 位的哈希值。
  • 碰撞抗性:极难找到两个不同的输入数据生成相同的哈希值。
  • 广泛应用:用于数据完整性验证、数字签名、密码学安全等领域。
  • 在实际应用中,SHA-256 通常用于生成数据的唯一标识或验证数据在传输过程中是否被篡改。
func Test_SHA256(t *testing.T) {
	s := "hello"//需要哈希的字符串
	h := sha256.New()//创建一个sha256对象
	h.Write([]byte(s))//写入需要哈希的字符串
	fmt.Println(hex.EncodeToString(h.Sum(nil)))//Sum把哈希值追加到参数*[]byte中,并返回
}

MAC算法(不可逆)

HMAC 是一种基于哈希函数和密钥的消息认证码。它结合了哈希算法(如 SHA-256、SHA-1、MD5 等)和密钥,用于生成一种认证码,用于验证消息的完整性和真实性。HMAC 的特点包括:

  • 结合性:使用哈希函数和密钥生成认证码。
  • 安全性:提供对消息完整性的强保证,即使哈希函数被公开,只有知道密钥的人才能验证认证码。
  • 灵活性:可以选择不同的哈希算法,但常见选择是 SHA-256。
    HMAC使用SHA-256 + 密钥生成消息认证代码MAX(Message Authentication Code)(不可逆)
    HS256(HMAC with SHA-256)生成的 token 主要用于 验证消息的完整性和真实性 ,但它更常用于生成和验证身份认证的 token,例如 JSON Web Token (JWT)。
func Test_HMAC(t *testing.T) {
	key := []byte("secret")// 密钥
	a := hmac.New(sha256.New, key)// 创建一个新的hmac对象
	a.Write([]byte("hello"))// 写入需要签名的数据
	b := a.Sum(nil)// 计算签名并返回结果
	fmt.Println(base64.StdEncoding.EncodeToString(b))// 对结果进行Base64编码
	//iKqz7ejTrflNJquQ07r9SiCDBww7zOnAFO4EpEOEfAs=
}

加密算法(可逆)

加密算法(Encryption Algorithm) 是将明文(plaintext)转换为密文(ciphertext),或者将密文转换为明文的算法。
加密都是把一个block快加密成等长的密文,由于只能一个个块加密,要配合不同的加密模式例如下面的CBC模式和ECB模式,才能达到加密的目的。
对称加密比非对称加密快

对称加密算法(可逆)

  • 是指加密和解密使用相同密钥的加密算法。
  • 加密和解密速度快,安全性高。
  • 对称加密在开发中用的很多,如 AES,DES,3DES,RC。

DES(可逆)

  • 采用的密钥长度为 56 位
  • 加密后长度和输入相同
  • 安全性较低,目前不推荐使用

DES 加密算法的密钥长度应该是 8 个字节(64 位),不过实际上只有 56 位被用于加密计算,而 8 位用于奇偶校验,所以通常是使用 8 个字节的密钥
对于 DES 加密算法而言,数据长度必须是加密块大小的整数倍,即 8 字节。
但是近些年使用越来越少,因为 DES 使用56位密钥(密钥长度越长越安全),以现代计算能力24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用 DES 加密算法。

var key = []byte("12345678") // 56位密钥
//编码一个blocksize长度的块(8位)
func encoded(s []byte) []byte {
	block, _ := des.NewCipher(key) //Cipher是密码的意思
	ans := make([]byte, len(s))
	block.Encrypt(ans, s) //encrypt加密一个block块
	return ans
}
//解码一个blocksize长度的块(8位)
func decoded(s []byte) []byte {
	block, _ := des.NewCipher(key) //Cipher是密码的意思
	ans := make([]byte, len(s))
	block.Decrypt(ans, s) //decrypt解密一个block块
	return ans
}

AES(可逆)

  • 采用的密钥长度为 128 位、192 位或 256 位
  • 加密后长度和输入相同
  • 安全性高,目前推荐使用
func Test_AES(t *testing.T) {
	key := []byte("1234567890123456") // 16字节密钥
	plaintext := []byte("helloworldaaaaaa")// 16字节明文
	ans:=encoded_aes(key,plaintext)
	fmt.Println(ans)
	fmt.Println(deccode_aes(key,ans))
}
// 编码一个blocksize长度的块(16位)
func encoded_aes(keys,s []byte) []byte {
	block, _ := aes.NewCipher(keys) //Cipher是密码的意思
	ans := make([]byte, len(s))
	block.Encrypt(ans, s) //encrypt加密一个block块
	return ans
}
func deccode_aes(keys,s []byte) []byte {
	block, _ := aes.NewCipher(keys) //Cipher是密码的意思
	ans := make([]byte, len(s))
	block.Decrypt(ans, s) //encrypt加密一个block块
	return ans
}

区别

AES(Advanced Encryption Standard)和DES(Data Encryption Standard)是两种常见的对称加密算法,它们在多个方面有显著的区别:

  • AES:支持多种密钥长度,包括 AES-128、AES-192 和 AES-256,分别对应 128 位、192 位和 256 位密钥长度。这些密钥长度提供了不同级别的安全性,其中 AES-256 提供了最高级别的安全性。
  • DES:固定为 56 位的密钥长度,但实际上只有 56 位被用作加密密钥,其余 8 位用作奇偶校验,因此实际的加密强度是 56 位。由于密钥长度短,DES 的安全性在现代计算环境下已经不足以应对安全威胁。

非对称加密算法(可逆)

  • 是指加密和解密使用不同的密钥的加密算法。
  • 加密速度慢,安全性高。
  • 私钥加密,公钥解密
  • 非对称加密在开发中用的不多,如 RSA、DSA。

RSA(可逆)

  • 加密后数据长度 <= 密钥位数 / 8 - 11
  • 公钥和私钥在本质上是大整数。它们是基于大整数数学运算的加密系统的核心组成部分。在许多公钥加密算法(如 RSA、ECC)中,公钥和私钥都可以表示
    在 RSA 加密系统中:
    • 私钥由两个主要大整数组成:
      • n(模数):这是两个大素数 p 和 q 的乘积。
      • d(私有指数):这是一个与模数 n 相关的整数,用于解密。
    • 公钥由两个主要大整数组成:
      • n(模数):与私钥中的模数相同。
      • e(公有指数):这是一个通常选定的较小的整数,用于加密。
    • 这些整数在 RSA 密钥生成过程中通过数学运算生成并满足特定的数学关系,使得 RSA 加密和解密可以进行。
func Test_RSA(t *testing.T) {
	// 生成私钥和公钥
	privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
	publicKey := &privateKey.PublicKey
	// 保存私钥和公钥
	// res1 := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
	// res2 := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(publicKey)})
	// ioutil.WriteFile("private.pem", res1, 0600)
	// ioutil.WriteFile("public.pem", res2, 0600)
	//读取私钥和公钥
	data, _ := ioutil.ReadFile("private.pem")
	block, _ := pem.Decode(data)
	privateKey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
	data, _ = ioutil.ReadFile("public.pem")
	block, _ = pem.Decode(data)
	publicKey, _ = x509.ParsePKCS1PublicKey(block.Bytes)

	// 加密
	src := []byte("hello world")
	encrypted, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, src, nil)

	fmt.Println("加密后的数据:",base64.StdEncoding.EncodeToString(encrypted))

	// 解密
	decrypted, _ := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, encrypted, nil)
	fmt.Println(string(decrypted))
}

ECC(可逆)

ECC 密钥
在椭圆曲线加密(ECC)中:

  • 私钥 是一个大整数 d,这是在某个范围内的随机数。
  • 公钥 是椭圆曲线上的一个点 Q,它是通过椭圆曲线上的基点 G 乘以私钥 d 得到的,即 Q = d * G。
  • 椭圆曲线加密依赖于椭圆曲线上的点运算,私钥和公钥在数学上有着密切的关系。

PEM格式存储密钥

pem.EncodeToMemory 是 Go 语言标准库中的一个函数,位于 encoding/pem 包内,用于将 PEM 编码的块(pem.Block)编码为字节切片并返回。
什么是 PEM 编码
PEM(Privacy-Enhanced Mail)编码是一种用于表示加密对象(如证书、私钥、公钥等)的标准。PEM 格式的文件通常以 -----BEGIN ----- 和 -----END ----- 包围数据块,并且数据块使用 Base64 编码。
例如:public.pem 文件的内容可能如下所示:

-----BEGIN PUBLIC KEY-----
MIIBCgKCAQEAvHxBCN85ydD+qwZvnIC1jt2X6PCivCgmgF0whfRfZE2CSukKJfWs
BZaPDdV8Zus/LPuH7PJs1rOazwQxyoewSy0hO2h66eAoyfCkGAwi30+lshop/oiK
BrHQW0g3S7Uywcfx+WQpFxP+YtWqXqhSGmb/Y83gYpvVtWUm5zzWleg1Iv1M2ihs
KBR+SxAoLRQmnycEmHlOorw138VR0wnH8Gmh9xNZ/+RV6wIOQVmf1VHu+dJnmf21
wAMdua9nOoibxrVz69IzjixiXi5M1El2jncAMGjRBJsMbwtfWPbABVju6f6PK13y
nYcf1rwlRcchxTeAwVnMCppMStrdhl2fTQIDAQAB
-----END PUBLIC KEY-----

pem.EncodeToMemory 的作用
pem.EncodeToMemory 的主要作用是将一个 pem.Block 对象编码为 PEM 格式的字节切片,方便存储或传输。
示例代码
下面是一个使用 pem.EncodeToMemory 的示例,它生成一个 RSA 私钥,并将其编码为 PEM 格式的字节切片,然后打印出来:

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
)

func main() {
	// 生成 RSA 私钥
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		fmt.Println("Error generating RSA key:", err)
		return
	}

	// 将私钥转换为 PKCS#1 格式的 ASN.1 DER 编码
	privateKeyDER := x509.MarshalPKCS1PrivateKey(privateKey)

	// 创建一个 PEM Block
	privateKeyBlock := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: privateKeyDER,
	}

	// 将 PEM Block 编码为字节切片
	privateKeyPEM := pem.EncodeToMemory(privateKeyBlock)

	// 打印 PEM 编码的私钥
	fmt.Println(string(privateKeyPEM))
}

DER格式存储密钥

DER(Distinguished Encoding Rules)格式是一种二进制编码格式,用于存储 ASN.1 编码的结构。
DER 格式的文件通常以 0x30 开始,以 0x00 结束。
https://blog.csdn.net/fengshenyun/article/details/124596279

加密模式

CBC模式

  • 加密过程:
    对第一个数据块(明文)进行加密时,使用 IV 与明文进行异或运算,然后将结果再与加密算法的密钥进行加密,得到第一个密文块。
    对后续的数据块,将前一个密文块与当前的明文进行异或运算,然后再与密钥进行加密,得到当前的密文块。
    这样一直进行下去,每个密文块都依赖于前一个密文块的加密结果,因此形成了一条“链”。
  • 解密过程:
    解密过程与加密过程相反。首先使用 IV 与第一个密文块进行解密运算(使用解密算法和密钥),然后再与 IV 进行异或运算,得到第一个明文块。
    对后续的密文块,使用当前密文块与前一个密文块进行解密运算,然后再与前一个密文块进行异或运算,得到当前的明文块。
    这样依次进行下去,直至得到所有的明文块。
    AES-CBC demo
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	fmt.Println("unpadding:", origData[length-1])
	return origData[:(length - unpadding)]
 }
func Test_DES_CBC(t *testing.T) {
	key := []byte("12345678")                            // 8位密钥
	plaintext := []byte("hello woqrld for study des cbc") // 8字节明文
	iv := []byte("12345678")                             // 8字节iv
	block, _ := des.NewCipher(key)
	mode := cipher.NewCBCEncrypter(block, iv) // 创建一个新的CBC加密器
	fmt.Println("补位前明文:", plaintext, len(plaintext))
	plaintext = PKCS7Padding(plaintext, block.BlockSize()) // 填充
	fmt.Println("加密前明文:", plaintext, len(plaintext))
	ciphertext := make([]byte, len(plaintext))          // 16字节密文
	for i := 0; i < len(plaintext); i += des.BlockSize {
		blocks := plaintext[i : i+des.BlockSize] // 取出一个block块
		mode.CryptBlocks(ciphertext[i:], blocks) // 加密一个block块
	}
	fmt.Println("加密后密文:", ciphertext)

	
	fmt.Println("解密前密文:", ciphertext)
	block1, _ := des.NewCipher(key)
	mode1 := cipher.NewCBCDecrypter(block1, iv) // 创建一个新的CBC解密器
	plaintext1 := make([]byte, len(ciphertext))
	for i := 0; i < len(ciphertext); i += des.BlockSize {
		block2 := ciphertext[i : i+des.BlockSize] // 取出一个block块
		mode1.CryptBlocks(plaintext1[i:], block2) // 解密一个block块
	}
	fmt.Println("解密后明文:", plaintext1)
	plaintext1 = PKCS7UnPadding(plaintext1) // 去除填充
	fmt.Println("去除填充后明文:", string(plaintext1))
}

ECB模式

  • 加密过程:
    对每个数据块(明文)进行加密时,使用加密算法的密钥进行加密,得到当前的密文块。
  • 解密过程:
    对每个数据块(密文)进行解密时,使用加密算法的密钥进行解密,得到当前的明文块。

    ECB模式 demo
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	fmt.Println("unpadding:", origData[length-1])
	return origData[:(length - unpadding)]
}
func encrypt_DES_ECB(plaintext, key []byte) ([]byte, error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	//对明文进行填充
	plaintext = PKCS7Padding(plaintext, block.BlockSize())
	ciphertext := make([]byte, len(plaintext))
	//就是逐块EDS加密后拼接
	for bs, be := 0, block.BlockSize(); bs < len(plaintext); bs, be = bs+block.BlockSize(), be+block.BlockSize() {
		block.Encrypt(ciphertext[bs:be], plaintext[bs:be])
	}
	return ciphertext, nil
}
func decrypt_DES_ECB(ciphertext, key []byte) ([]byte, error) {
	block, _ := des.NewCipher(key)

	lens := len(ciphertext)
	ans := make([]byte, lens)
	//就是逐块EDS解密后拼接
	for bs, be := 0, block.BlockSize(); bs < len(ciphertext); bs, be = bs+block.BlockSize(), be+block.BlockSize() {
		block.Decrypt(ans[bs:be], ciphertext[bs:be])
	}
	//对密文进行去填充
	ans = PKCS7UnPadding(ans)
	return ans, nil
}
func Test_DES_ECB(t *testing.T) {
	// 加密
	key := []byte("12345678")
	src := []byte("hello world")
	ans, _ := encrypt_DES_ECB(src, key)
	fmt.Println(ans)
	// 解密
	ans1, _ := decrypt_DES_ECB(ans, key)
	fmt.Println(string(ans1))
}

与编码与加密(对称加密与非对称加密)相似的内容:

编码与加密(对称加密与非对称加密)

目录编码与加密Base64编码(可逆)十六进制编码(hex.EncodeToString函数)(可逆)哈希算法(不可逆)MD5(不可逆)SHA-256(不可逆)MAC算法(不可逆)加密算法(可逆)对称加密算法(可逆)DES(可逆)AES(可逆)区别非对称加密算法(可逆)RSA(可逆)ECC(可逆)P

[转帖]使用 OpenSSL 加密和解密文件

https://linux.cn/article-13368-1.html OpenSSL 是一个实用工具,它可以确保其他人员无法打开你的敏感和机密消息。 加密是对消息进行编码的一种方法,这样可以保护消息的内容免遭他人窥视。一般有两种类型: 密钥加密或对称加密 公钥加密或非对称加密 密钥加密secr

nomp矿池源码详解

是一个由Node.js编写的高效、可扩展的加密货币挖矿池,它基于node-stratum-pool模块,包含奖励处理与支付功能以及一个响应式前端网站,提供实时统计和管理中心,本文对该项目的主体架构及相关源码进行了介绍!

【升职加薪秘籍】我在服务监控方面的实践(8)-elasticsearch 性能监控与分析手段

> 大家好,我是蓝胖子,之前讲了mysql,redis中间件的监控,今天我们再来看看另一个基础组件elasticsearch,如何对它进行监控,当你思考如何对一个组件进行监控时,四大黄金指标会告诉你答案,我们同样会从四大黄金指标给出的维度进行分析。 针对es做的性能分析,用四大黄金指标原则,我们可以

4.7 C++ Boost 多线程并发库

C++语言并没有对多线程与网络的良好支持,虽然新的C++标准加入了基本的`thread`库,但是对于并发编程的支持仍然很基础,Boost库提供了数个用于实现高并发与网络相关的开发库这让我们在开发跨平台并发网络应用时能够像Java等语言一样高效开发。thread库为C++增加了多线程处理能力,其主要提供了清晰的,互斥量,线程,条件变量等,可以很容易的实现多线程应用开发,而且该库是可跨平台的,并且支持

Java实际工作里用到的几种加密方式

1、Base64加密 最简单的加密方式,甚至可以说不是加密,只是一种用64个字符表示任意二进制数据的方法。Base64编码原理是将输入字符串按字节切分,取得每个字节对应的二进制值(若不足8比特则高位补0),然后将这些二进制数值串联起来,再按照6比特一组进行切分(因为2^6=64),最后一组若不足6比

抖音验证签名和接口含中文签名,需要在发送端加上utf8编码

抖音验证签名和接口含中文签名,需要在发送端加上utf8编码 抖音验签和抖音异步通知回调验签解决:是对整个接收的字符串做验签,而不是部分数据做验签解决中文参数问题,否则中文乱码报验签错误 签名算法https://developer.open-douyin.com/docs/resource/zh-CN

如何在低代码平台中引用 JavaScript ?

引言 在当今快速发展的数字化时代,企业对业务应用的需求日益复杂且多元。低代码开发平台作为一个创新的解决方案,以直观易用的设计理念,打破了传统的编程壁垒,让非技术人员也能轻松构建功能完备的Web应用程序,无需深入编码。这一特性极大地简化了应用开发流程,加速了业务需求转化为实际应用的速度,为企业带来了前

C#.NET与JAVA互通之AES加密解密V2024

C#.NET与JAVA互通之AES加密解密V2024 视频: 注意点: 1. KEY 和 IV 从字符串转byte数组时,双方要约定好编码,一般是UTF8。 2.明文从字符串转byte数组时,双方要约定好编码,一般是UTF8,也可以GB2312,但不能Encoding.Default。 3.加密后的

WebApi中添加Jwt鉴权

前言 JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。一个 JWT 实际上就是一个字符串,它由三部分组成,头部、载荷与签名。前两部分需要经过 Base64 编码,后一部分通过前两部分 Base64 编码后再加密而成。针对