常用加密算法及其实现指南

用户密码加密

md5加盐(不可用因为安全性较低)

生成盐(Salt):首先生成一个随机的盐(salt),它的作用是使相同的密码生成不同的哈希值。盐通常是一个足够长且随机的字符串。
将盐与密码结合:将盐与用户的密码拼接(或交替拼接)在一起,得到新的字符串。
应用MD5哈希:对组合后的字符串进行MD5哈希运算,生成哈希值。
存储盐和哈希值:将盐和哈希值存储到数据库中,通常盐和哈希值会一起存储,以便后续验证密码时使用相同的盐。

SHA-256

    • 作用:它将输入数据(消息)映射为固定长度的256位哈希值。SHA-256被广泛应用于数字签名、数据完整性检查等领域,是许多加密协议和标准(如SSL/TLS、区块链等)的基础。
    • 缺点:
      1. 计算速度快:虽然SHA-256比MD5和SHA-1更安全,但它仍然非常快速,可能会在某些场景下被GPU/ASIC暴力破解攻击(即通过不断尝试不同的输入并计算哈希值)。
      2. 不适合用于密码存储:不加盐的情况下容易被彩虹表攻击(存储常用密码哈希值)。
    • 实现:pyhon自带库文件
      import hashlib
      data = "Hello, world!".encode('utf-8')
      hashed = hashlib.sha256(data).hexdigest()
      print(f"SHA-256 Hash: {hashed}")

bcrypt(Blowfish-based Crypt)

    • 优点:
      1. 工作因子:bcrypt 允许开发者调整计算复杂度,参数称为 cost(工作因子)。cost=10 代表 2¹⁰ = 1024 次哈希迭代,提高 cost 值会使哈希计算变慢,提高攻击难度。
      2. 内置盐
      3. slow hashing,计算慢,防止暴力攻击
    • 代码示例(gpt写的)
      import bcrypt
      # 生成盐
      salt = bcrypt.gensalt(rounds=12) # 工作因子设为 12,安全性更高
      password = "user_password".encode('utf-8')
      # 生成哈希值
      hashed_password = bcrypt.hashpw(password, salt)
      # 验证密码
      if bcrypt.checkpw(password, hashed_password):
      print("Password is correct!")
      else:
      print("Invalid password.")

Argon2(最强密码哈希算法)

    • 优点:安全性高
    • 缺点:计算慢,占用RAM多
    • 作用:Argon2 主要特性
      三种模式:
      1. Argon2i(适用于*密钥派生,抗*侧信道攻击)

        密钥派生:密钥派生是指通过某种算法从一个基本的密钥(通常是用户的密码)中生成多个密钥或更强的密钥,用于加密操作。

        侧信道攻击
        侧信道攻击是一种通过分析加密算法的非预期信息(例如执行时间、电磁波、功耗、缓存存取模式等)来破解加密算法的攻击方法。攻击者并不是直接通过破解算法本身来恢复密钥,而是利用系统中暴露的“旁路”信息。
        常见的侧信道攻击
        时间攻击:通过分析加密操作所需的时间,攻击者可以推测出某些加密密钥的值。
        功耗攻击:通过监测设备的功耗来推断算法内部的状态或密钥。
        缓存攻击:通过分析计算机缓存的行为,推测加密过程中的数据或密钥。
        Argon2i 如何抵抗侧信道攻击
        Argon2i 模式专门为抗侧信道攻击设计,主要通过以下方式增强安全性:
        内存消耗:Argon2i 强调在加密过程中消耗大量内存,使得攻击者无法利用传统的侧信道攻击手段,如时间攻击或功耗分析。
        内存和计算相结合:Argon2i 设计了一种 内存硬化(memory-hard)算法,即使使用高效的硬件(如GPU)进行攻击,攻击者依然需要大量的内存,这增加了破解的难度。
        混淆操作:Argon2i 使用复杂的哈希计算和数据重排,使得攻击者很难从旁观信息(如时间、功耗等)推断出密码。

      2. Argon2d(适用于密码哈希,抗 GPU 攻击)

      3. Argon2id(综合前两者,推荐用于密码存储)
        内存强化(Memory Hardness),可以设置内存占用量,提高破解难度。
        可调节计算强度,可以调整 时间成本(time_cost) 和 内存使用量(memory_cost)。

    • 代码示例(gpt写的)
from argon2 import PasswordHasher
# 初始化哈希器
ph = PasswordHasher()
# 生成哈希值
hashed_password = ph.hash("user_password")
# 验证密码
try:
ph.verify(hashed_password, "user_password")
print("Password is correct!")
except:
print("Invalid password.")

用户数据加密

消息较长时,可先用AES加密消息,再用RSA加密AES密钥(超过几百字节就算长,所以可以对全部数据使用此方法)

对称加密(AES)

AES 是一种块加密算法,数据被划分为固定大小的块(通常为 128 位),并通过密钥进行加密。
AES 被设计为快速、强大并且适用于各种硬件和软件环境。它是对称加密的,这意味着加密和解密使用相同的密钥。

AES 算法的主要特点

  1. 对称加密:加密和解密使用相同的密钥。
  2. 块加密:AES 将明文分成固定长度的块进行加密,每个块 128 位(16 字节)。
  3. 密钥长度:AES 支持三种密钥长度:
    AES-128:密钥长度为 128 位。
    AES-192:密钥长度为 192 位。
    AES-256:密钥长度为 256 位。
  4. 多轮加密:
    AES 的加密过程基于多轮变换,轮数取决于密钥长度:
    128 位密钥:10 轮。
    192 位密钥:12 轮。
    256 位密钥:14 轮。

AES 工作原理

AES 加密的核心是 SubBytes、ShiftRows、MixColumns 和 AddRoundKey 四个主要步骤。它通过一系列的 轮次(Rounds)对数据进行多层处理,最终得到加密结果。

以下是 AES 加密的每一轮的步骤

AddRoundKey(轮密钥加法):在每一轮的开始,使用当前轮的密钥与数据块进行异或(XOR)操作。
SubBytes(字节替换):使用一个固定的 S-Box(替代盒)对每个字节进行替代。S-Box 是一个 16x16 的矩阵,包含了 256 个值,用于替换明文块中的每个字节。
ShiftRows(行移位):将数据块中的每一行循环左移。第一行不动,第二行左移一个位置,第三行左移两个位置,第四行左移三个位置。
MixColumns(列混合):对数据块的每一列进行变换。通过与固定的矩阵相乘,对数据进行线性变换,以增加扩散性。
这一步在最后一轮中省略,以提高加密效率。
AddRoundKey(轮密钥加法):使用当前的轮密钥与数据块进行异或操作。

解密过程

解密过程与加密过程类似,但步骤相反:
SubBytes 变为 InvSubBytes,对字节进行反向替代。
ShiftRows 变为 InvShiftRows,行进行反向移位。
MixColumns 变为 InvMixColumns,对列进行反向变换。
AddRoundKey 步骤不变。

解密的轮数和加密相同,但因为顺序是反向的,所有操作会按照逆操作执行。

AES 加密的 Python 实现(gpt)

安装 PyCryptodome

pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import base64
# 填充数据到 16 字节倍数(AES 块大小)
def pad(data):
while len(data) % 16 != 0:
data += b' ' # 使用空格填充
return data
# AES 加密
def aes_encrypt(plain_text, key):
cipher = AES.new(key, AES.MODE_CBC) # 使用 CBC 模式
cipher_text = cipher.encrypt(pad(plain_text.encode())) # 加密
iv = base64.b64encode(cipher.iv).decode('utf-8') # 获取 IV(初始化向量)并 Base64 编码
cipher_text = base64.b64encode(cipher_text).decode('utf-8') # 加密结果进行 Base64 编码
return iv, cipher_text
# AES 解密
def aes_decrypt(iv, cipher_text, key):
iv = base64.b64decode(iv) # 解码 IV
cipher_text = base64.b64decode(cipher_text) # 解码密文
cipher = AES.new(key, AES.MODE_CBC, iv) # 使用 CBC 模式和解码的 IV
plain_text = cipher.decrypt(cipher_text).decode('utf-8').rstrip() # 解密并去除填充字符
return plain_text
# 示例
if __name__ == "__main__":
# 密钥必须是 16, 24 或 32 字节
key = get_random_bytes(16) # 生成一个 128 位的密钥(16 字节)
plain_text = "This is a secret message!"
# 加密
iv, cipher_text = aes_encrypt(plain_text, key)
print("Encrypted (Base64):", cipher_text)
print("IV (Base64):", iv)
# 解密
decrypted_text = aes_decrypt(iv, cipher_text, key)
print("Decrypted:", decrypted_text)

非对称加密(RSA)

算法原理

公钥所有人都有,私钥是要绝对保密的,这样确保了数据安全性。

算法用途

  1. 用于加密:用公钥加密以后,只有拥有私钥的人才可以解密
  2. 用于数字签名:用私钥“加密”,所有人都有公钥都可以解密,因此叫做签名,实际上并非加密

算法描述:

  1. 生成一对很大的素数p,q
  2. 质数相乘 N=p×q
  3. 计算欧拉函数f(n)=(p1)(q1)
  4. 选择公钥E,即 e1<e<T,gcd(e,T)=1的一个质数, E=eN (e 最好直接取65537,我也不知道为啥)
  5. 计算私钥D,d×e%T=1 , D=dN (这里就是乘法逆元就行)
  6. 明文密文转化公式:e%N=,d%N=
    也就是先把明文和密文每个字符都转化为十进制数字然后代入公式计算即可。

实现代码(依然是gpt调库写的):

先安装库

pip install pycryptodome

实现:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Random import get_random_bytes
import base64
# 生成RSA密钥对
def generate_rsa_keypair(bits=2048):
key = RSA.generate(bits) # 生成指定位数的RSA密钥
private_key = key.export_key() # 导出私钥
public_key = key.publickey().export_key() # 导出公钥
return private_key, public_key
# 加密
def encrypt_with_public_key(public_key, message):
key = RSA.import_key(public_key) # 导入公钥
cipher = PKCS1_OAEP.new(key) # 创建加密对象
encrypted_message = cipher.encrypt(message.encode()) # 加密消息
return base64.b64encode(encrypted_message).decode('utf-8') # 返回Base64编码的加密消息
# 解密
def decrypt_with_private_key(private_key, encrypted_message):
key = RSA.import_key(private_key) # 导入私钥
cipher = PKCS1_OAEP.new(key) # 创建解密对象
encrypted_message = base64.b64decode(encrypted_message) # 解码Base64加密消息
decrypted_message = cipher.decrypt(encrypted_message) # 解密消息
return decrypted_message.decode('utf-8') # 返回解密后的消息
# 示例
if __name__ == "__main__":
# 生成密钥对
private_key, public_key = generate_rsa_keypair(bits=2048)
print("Private Key:", private_key.decode())
print("Public Key:", public_key.decode())
# 加密消息
message = "This is a secret message!"
encrypted_message = encrypt_with_public_key(public_key, message)
print("Encrypted Message:", encrypted_message)
# 解密消息
decrypted_message = decrypt_with_private_key(private_key, encrypted_message)
print("Decrypted Message:", decrypted_message)

信息传输渠道加密

这模块要用 js 我不太会啊()

HTTPS(HyperText Transfer Protocol Secure)是基于SSL/TLS的HTTP协议,能够对浏览器和服务器之间的通信进行加密,防止数据在传输过程中被第三方窃取或篡改。(TLS是SSL升级版,现多用TLS)

SSL/TLS工作原理

SSL/TLS证书:服务器需要部署SSL/TLS证书,浏览器与服务器建立连接时会验证证书的有效性,确保连接是与合法的服务器进行的。

  1. 加密握手:客户端与服务器之间通过加密握手(包括证书验证、密钥交换等)来建立安全的连接。
    1. 客户端发送请求:客户端(浏览器)请求建立加密连接,并向服务器发送协议支持信息(如支持的加密算法)。
    2. 服务器响应:服务器选择加密算法,并将自己的 SSL/TLS 证书 发给客户端。
    3. 证书验证:客户端验证服务器的证书,确认服务器身份。
    4. 密钥交换:客户端和服务器通过 Diffie-Hellman 或 RSA 等算法交换密钥,确保双方拥有相同的加密密钥。
    5. 建立安全连接:客户端和服务器确认密钥交换成功后,开始使用对称加密进行通信。
  2. 数据加密:通过对称加密加密数据,并使用SSL/TLS密钥对每个数据包进行加密。
  3. 通信加密:确保用户的敏感数据(如登录凭证、银行卡信息等)在网络传输过程中不会被中途截取。

部署HTTPS

为了确保网站的安全性并且使浏览器能够使用 HTTPS 连接,网站需要做以下几步:

  1. 获取 SSL 证书:
    使用免费的 Let's Encrypt 证书。这是一个提供免费、自动化证书签发和更新服务的机构。
    购买 商业 SSL 证书,从受信任的证书颁发机构(如 Symantec、Comodo、DigiCert)获取证书。
  2. 配置服务器以支持 HTTPS:
    配置你的网站服务器(如 Apache、Nginx)以支持 HTTPS 协议。
    配置 SSL/TLS 设置,通常需要:
    安装 SSL 证书。
    配置服务器监听 443 端口(HTTPS 的默认端口)。
    开启 HTTPS 模式,并强制所有访问通过 HTTPS。
  3. 确保所有页面都使用 HTTPS:
    对于网站中的所有页面(不仅是登录页、支付页面等),都需要通过 HTTPS 进行访问。这可以通过修改网站配置,或者使用 HTTP Strict Transport Security(HSTS)来强制浏览器使用 HTTPS。
    确保所有外部资源(如图片、脚本、样式表等)都通过 HTTPS 加载,避免混合内容问题(即部分内容通过 HTTP 加载,造成潜在的安全风险)。

注意事项

  • 微信小程序:在微信小程序中,所有的网络请求(如 wx.request())默认都要求使用 HTTPS。你可以直接使用 HTTPS URL 进行接口请求。
    如果你要访问的接口使用 HTTP 协议,微信小程序会提示“请求失败”,并且不会允许请求。
    跨域问题:

  • 小程序在进行 HTTPS 请求时,可能会遇到 跨域问题,尤其是当请求来自不同域名时。你需要确保服务器配置了正确的 CORS(跨域资源共享)头部,允许从小程序的域名发起请求。
    证书有效期和更新:

  • SSL/TLS 证书有有效期,需要定期更新(通常为 1 年)。可以使用自动更新工具(如 Certbot)来定期更新证书,避免证书过期导致 HTTPS 连接中断。

两步验证/短信验证码

短信验证码

生成验证码:生成一个随机的验证码(通常是 6 位数字或字母数字组合)。
发送验证码到用户的手机号:通过短信服务将验证码发送到用户的手机上。
验证用户输入的验证码:当用户输入验证码时,后台进行验证,如果验证码匹配则认证通过。
为了实现这个功能,通常需要借助第三方短信服务提供商来发送短信。常见的服务商有 Twilio, 阿里云短信, 腾讯云短信, Sendinblue, Nexmo 等。

  1. 生成验证码
    生成验证码通常比较简单,你可以生成一个随机的数字或字母。验证码通常具有一定的时效性(如 5 分钟),

    import random
    def generate_verification_code():
    # 生成一个 6 位的数字验证码
    code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
    return code
    # 生成验证码
    verification_code = generate_verification_code()
    print("验证码是:", verification_code)
  2. 通过短信发送验证码

    要实现发送验证码到用户的手机号,首先需要选择并配置一个短信 API 服务商。常见的服务商有 Twilio, 阿里云短信, 腾讯云短信, Sendinblue, Nexmo 等。这里以 Twilio 为例。
    你需要注册 Twilio 账户,获取 Account SID 和 Auth Token,并且配置一个有效的 Twilio 电话号码。
    安装 Twilio 库:

    pip install twilio

    发送验证码:

    from twilio.rest import Client
    def send_sms(phone_number, verification_code):
    # Twilio 的账户 SID 和授权 Token
    account_sid = 'your_account_sid'
    auth_token = 'your_auth_token'
    # 创建 Twilio 客户端
    client = Client(account_sid, auth_token)
    # 发送短信
    message = client.messages.create(
    body=f"您的验证码是: {verification_code}",
    from_='+1xxxxxxxxxx', # Twilio 提供的电话号码
    to=phone_number # 用户手机号
    )
    print(f"验证码已发送到 {phone_number}")
    return message.sid
    # 发送验证码到用户手机号
    phone_number = '+8613800138000' # 例如中国的手机号
    send_sms(phone_number, verification_code)

    在此代码中,Twilio 通过 API 将验证码发送到用户手机。短信内容为 您的验证码是: 123456。

  3. 验证用户输入的验证码
    在用户请求验证码时,服务器生成并保存验证码和其生成的时间戳(例如使用 Redis 或数据库保存)。
    用户输入验证码时,系统查询保存的验证码,并检查是否与输入的验证码匹配,且是否在有效期内。
    示例:验证用户输入的验证码

    import time
    # 假设保存了验证码和生成时间戳
    saved_code = "123456"
    saved_time = time.time() # 保存验证码生成的时间
    def verify_code(user_input, saved_code, saved_time, validity_period=300):
    current_time = time.time()
    # 检查验证码是否过期(例如 5 分钟)
    if current_time - saved_time > validity_period:
    print("验证码已过期")
    return False
    # 检查验证码是否正确
    if user_input == saved_code:
    print("验证码验证成功")
    return True
    else:
    print("验证码错误")
    return False
    # 用户输入的验证码
    user_input = input("请输入验证码: ")
    # 验证验证码
    verify_code(user_input, saved_code, saved_time)
  4. 使用 Redis 缓存验证码
    通常使用 Redis 来缓存验证码,并设置过期时间,这样可以避免数据库频繁读写,提高性能。

    pip install redis
    import redis
    import random
    import time
    # 连接到 Redis 服务
    r = redis.StrictRedis(host='localhost', port=6379, db=0, decode_responses=True)
    def generate_and_send_sms(phone_number):
    # 生成验证码
    code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
    # 保存验证码到 Redis,并设置过期时间为 5 分钟(300 秒)
    r.setex(f"verification_code:{phone_number}", 300, code)
    # 发送验证码到手机号
    send_sms(phone_number, code)
    def verify_sms(phone_number, input_code):
    # 从 Redis 获取验证码
    saved_code = r.get(f"verification_code:{phone_number}")
    if not saved_code:
    print("验证码不存在或已过期")
    return False
    # 验证用户输入的验证码是否匹配
    if saved_code == input_code:
    print("验证码验证成功")
    return True
    else:
    print("验证码错误")
    return False
    # 示例:发送验证码
    phone_number = "+8613800138000"
    generate_and_send_sms(phone_number)
    # 示例:验证用户输入
    input_code = input("请输入收到的验证码:")
    verify_sms(phone_number, input_code)

私钥存储方式

硬件安全模块(HSM)

(手机小程序中不推荐,存在云端就行):用于生成和存储密钥,并在需要时提供密钥操作。HSM 是一种物理设备,它能有效地防止密钥被外部访问或盗取。

云密钥管理服务:

如 AWS KMS、Google Cloud KMS 等提供密钥管理服务,可以生成、存储和使用密钥进行加密解密操作。这些服务可以确保密钥的安全性,避免暴露在应用代码中。

实现(gpt):

要在手机小程序中使用 云服务存储密钥,并通过 API 安全地访问私钥进行加密和解密操作,您可以按照以下步骤操作。这里我们主要探讨使用 云服务提供的密钥管理服务 (KMS) 来存储和访问私钥的具体过程。

步骤 1: 选择云平台

首先,选择您需要使用的云服务提供商。以下是一些常见的云平台及其密钥管理服务:

AWS KMS(Amazon Web Services)
阿里云 KMS
华为云 KMS
Google Cloud KMS
每个云平台提供的密钥管理服务 (KMS) 都支持安全地存储密钥,并通过 API 执行加密、解密操作。

步骤 2: 创建密钥对并配置 KMS

以 AWS KMS 为例,您可以按照以下步骤创建密钥对并配置 KMS:

2.1 在 AWS KMS 中创建密钥
登录到 AWS 管理控制台。
打开 KMS 服务,点击 创建密钥。
选择密钥类型(对称或非对称密钥)。对于大多数加密操作,选择 对称密钥,如果涉及到数字签名,选择 非对称密钥。
输入密钥名称,设置权限(选择哪些 IAM 用户/角色能够访问该密钥),然后完成创建。
2.2 配置 KMS 策略
为了安全起见,需要为 KMS 配置访问权限策略,确保只有经过授权的应用或服务能够访问密钥。通常,您需要为您的手机小程序创建一个访问权限策略,通过 IAM 角色来访问 KMS。

步骤 3: 设置 API 访问

在小程序中,通过 AWS SDK 或其他相应的 SDK 访问 KMS 密钥。确保您已经在小程序的后端设置好了服务器,服务器将调用云平台的 KMS API 来进行加密和解密操作。不要直接将密钥管理操作暴露给客户端(小程序),而是通过后端服务来完成。

3.1 配置 API 访问权限
确保您的后端服务有足够的权限来访问 KMS 密钥,通常需要:

IAM 角色和策略:通过 IAM 角色 配置相应的权限。
API 访问密钥:后端服务通过 API 密钥 访问 KMS。

步骤 4: 小程序与后端通信

小程序和后端之间通过 HTTPS 安全通信,确保数据的传输是加密的。小程序将敏感信息(如需要加密的文本或密钥)发送到后端,后端再通过 KMS 调用加密/解密 API。

4.1 后端调用 KMS API 进行加密/解密
加密操作:后端使用 AWS KMS(或其他云平台提供的 API)对数据进行加密。以下是一个加密的示例代码:

import boto3
# 创建 KMS 客户端
kms_client = boto3.client('kms')
# 使用 KMS 加密数据
def encrypt_data(plaintext):
response = kms_client.encrypt(
KeyId='arn:aws:kms:region:account-id:key/key-id',
Plaintext=plaintext.encode('utf-8')
)
return response['CiphertextBlob']

解密操作:同样,后端也可以通过 KMS 解密密文。以下是解密的示例代码:

def decrypt_data(ciphertext):
response = kms_client.decrypt(
CiphertextBlob=ciphertext
)
return response['Plaintext'].decode('utf-8')

步骤 5: 使用密钥进行加密操作

通过上述后端 API,您可以在小程序中发起请求,要求后端使用 KMS 存储的密钥进行加密和解密操作。小程序与后端通过 HTTPS 通道进行安全通信。

5.1 小程序前端请求后端进行加密操作
假设小程序需要将用户输入的敏感信息(如密码)进行加密后传输给服务器,您可以通过 HTTPS 请求将敏感信息发送到后端,由后端使用 KMS 进行加密。

wx.request({
url: 'https://your-backend-api.com/encrypt', // 后端 API 地址
method: 'POST',
data: {
plaintext: 'user_password'
},
success: function(res) {
// 获取加密后的密文
console.log('Encrypted:', res.data.ciphertext);
},
fail: function(error) {
console.error('Encryption failed:', error);
}
});

步骤 6: 处理密钥管理和轮换

在生产环境中,您还需要注意 密钥管理 和 密钥轮换:

密钥轮换:定期更换密钥以提高安全性。云服务提供商通常提供 自动密钥轮换 功能,例如 AWS KMS 每年会自动轮换密钥。
权限控制:设置适当的权限来限制哪些用户/服务可以访问密钥,并定期审计密钥访问日志。

步骤 7: 安全传输和存储

使用 HTTPS:确保所有的通信(无论是客户端与后端,还是后端与 KMS 之间)都通过 HTTPS 协议进行,确保数据在传输过程中不会被窃取。
加密传输:无论是在传输过程中,还是在存储中,都应确保敏感数据(如密码、支付信息等)都经过加密。

定期更换密钥

总结

要注意的点就是并非所有数据都进行加密,公开数据可以不加密提速

posted @   lyrrr  阅读(43)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示