前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >加密与安全_探索口令加密算法(PBE)

加密与安全_探索口令加密算法(PBE)

作者头像
小小工匠
发布2024-05-26 13:15:43
580
发布2024-05-26 13:15:43
举报
文章被收录于专栏:小工匠聊架构

概述

加密与安全_探索对称加密算法中我们提到AES加密密钥长度是固定的128/192/256位,而不是我们用WinZip/WinRAR那样,随便输入几位都可以。

这是因为对称加密算法决定了口令必须是固定长度,然后对明文进行分块加密。又因为安全需求,口令长度往往都是128位以上,即至少16个字符。

疑问

我们平时使用的加密软件,输入6位、8位都可以,难道是加密方式不一样吗?

用户输入的口令往往不能直接作为AES的密钥进行加密,因为它们的长度通常不符合AES密钥的要求,而且可能存在规律性,容易受到字典攻击等安全威胁。

为了解决这个问题,通常会使用PBE算法,采用随机数杂凑计算出真正的密钥,再进行加密。。

PBE 算法 ( Password Based Encryption)

PBE算法(Password-Based Encryption)是一种安全的密码基础加密算法,用于将用户输入的口令转换为符合要求的密钥,以便进行加密操作。 在使用PBE算法时,用户只需输入一个口令,而不需要直接提供一个符合要求的密钥。PBE算法的作用是通过结合用户输入的口令和一个安全随机生成的盐值,采用杂凑计算的方式生成最终的密钥。

通俗的可以理解为下面的函数:

代码语言:javascript
复制
key = generate(userPassword, secureRandomPassword);

以AES密钥生成为例,用户只需输入一个口令,而不需要担心口令的长度和复杂度是否符合要求。PBE算法会在内部生成一个安全的随机数作为盐值,并将用户输入的口令与盐值一起进行杂凑计算,从而生成一个符合AES加密算法要求的真正密钥。

通过这种方式,PBE算法实现了对用户口令的保护,同时确保生成的密钥符合加密算法的要求,从而提高了整个加密系统的安全性。

Code

POM

代码语言:javascript
复制
   <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.68</version>
        </dependency>

实现

代码语言:javascript
复制
package com.artisan.securityalgjava.peb;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

 
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 * 使用PBE算法进行加密和解密示例
 */
public class PBEExample {

    public static void main(String[] args) throws Exception {
        // 将BouncyCastle作为Provider添加到java.security:
        Security.addProvider(new BouncyCastleProvider());
        // 原文:
        String message = "Hello, world!";
        // 加密口令:
        String password = "hello12345";
        // 16 bytes随机Salt:
        byte[] salt = SecureRandom.getInstanceStrong().generateSeed(16);
        System.out.printf("salt: %032x\n", new BigInteger(1, salt));
        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(password, salt, data);
        System.out.println("encrypted: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:
        byte[] decrypted = decrypt(password, salt, encrypted);
        System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
    }

    // 加密:
    public static byte[] encrypt(String password, byte[] salt, byte[] input) throws GeneralSecurityException {
        // 使用口令生成PBEKeySpec对象
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
        // 创建密钥工厂
        SecretKeyFactory skeyFactory = SecretKeyFactory.getInstance("PBEwithSHA1and128bitAES-CBC-BC");
        // 生成密钥对象
        SecretKey skey = skeyFactory.generateSecret(keySpec);
        // 创建PBE参数对象
        PBEParameterSpec pbeps = new PBEParameterSpec(salt, 1000);
        // 创建加密器
        Cipher cipher = Cipher.getInstance("PBEwithSHA1and128bitAES-CBC-BC");
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, skey, pbeps);
        // 执行加密操作
        return cipher.doFinal(input);
    }

    // 解密:
    public static byte[] decrypt(String password, byte[] salt, byte[] input) throws GeneralSecurityException {
        // 使用口令生成PBEKeySpec对象
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
        // 创建密钥工厂
        SecretKeyFactory skeyFactory = SecretKeyFactory.getInstance("PBEwithSHA1and128bitAES-CBC-BC");
        // 生成密钥对象
        SecretKey skey = skeyFactory.generateSecret(keySpec);
        // 创建PBE参数对象
        PBEParameterSpec pbeps = new PBEParameterSpec(salt, 1000);
        // 创建解密器
        Cipher cipher = Cipher.getInstance("PBEwithSHA1and128bitAES-CBC-BC");
        // 初始化解密器
        cipher.init(Cipher.DECRYPT_MODE, skey, pbeps);
        // 执行解密操作
        return cipher.doFinal(input);
    }
}

在使用PBE时,引入BouncyCastle提供了更多的加密算法支持,并且可以使用其中的PBE算法。

  • 指定算法为PBEwithSHA1and128bitAES-CBC-BC表明了我们使用SHA1和128位AES加密算法结合的PBE算法。
  • 真正的AES密钥是在调用Cipher#init()方法时同时传入SecretKeyPBEParameterSpec实现的。在创建PBEParameterSpec时,我们指定了循环次数为1000。循环次数的增加可以增加破解所需的计算量,从而提高加密的安全性。
  • 如果我们固定了salt和循环次数,就得到了一个通用的“口令”加密软件。用户只需要输入口令,程序就可以使用固定的salt和循环次数来加密和解密数据。
  • 如果我们将随机生成的salt存储在U盘中,就可以得到一个“口令”加USB Key的加密软件。这种方式的好处在于,即使用户使用了一个非常弱的口令,没有U盘也无法解密,因为U盘存储的随机数密钥具有很高的安全性。

小结

  • PBE算法(Password-Based Encryption)通过用户输入的口令和一个安全的随机salt结合,经过多次迭代的杂凑计算生成最终的密钥(Key),然后再使用这个密钥进行加密操作。这种方式的安全性得到了显著提高,因为即使用户输入的口令较弱,通过引入随机salt和多次迭代的杂凑计算,生成的密钥也具有足够的复杂性和随机性,从而增加了破解的难度。
  • PBE算法内部使用的仍然是标准的对称加密算法,例如AES。生成的密钥(Key)是由用户口令和随机salt计算得出的,然后再传递给底层的对称加密算法进行加密和解密操作。这种结构既保留了对称加密算法的高效性和快速性,又通过PBE算法增加了用户口令的安全性,使得整个加密过程更加安全可靠。

总之,PBE算法通过结合用户口令和安全的随机salt,生成一个复杂且安全的密钥,进而增强了对称加密算法的安全性,为数据加密提供了更加可靠的保障。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 疑问
  • PBE 算法 ( Password Based Encryption)
  • Code
    • POM
      • 实现
      • 小结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档