Loading

用户密码安全存储

用户密码安全存储

关键字:AES加密,CBC,Java

浏览器或者各种客户端实现注册功能时,对用户密码的存储,该如何保证密码的安全?


关于方案

  1. 客户端使用AES(本文使用AES加密)算法对密码进行加密,然后将加密后的密码通过BASE64编码发送给服务器。
  2. 服务端收到后,BASE64解码,然后使用与客户端相同的密钥和初始向量进行ASE解密。解密后我们就得到原始密码了,然后我们可以对原始密码在进行各种操作,我说说之前我们公司的操作。他将原始密码进行md5编码,将编码后的字符串每16字节进行一次AES加密,最终将所有加密结果拼接合并,存放到数据库中再做一次SHA256.(我并不懂为什么要做这种操作,为什么不直接使用加密后的密文,而是要将编码后的每16字节进行一次加密后做拼接)

对于密钥存储

我不清楚客户端如何获取密钥,直接写在客户端代码中? 如果这样那就需要代码混淆,或者代码加密。

还是用接口访问服务器获得密钥?那么服务器也要验证接口调用者身份,况且对于每个app客户端如何判断是否有权限获得密钥。如果可以抓包,那么也可以获得请求中密钥,所以要对密钥再次进行加密,进行套娃?

好了,我们说说服务器端吧。我还是先说说之前公司的操作。他将密钥存储到配置文件,在生产环境有一个统一的配置中心,密钥就存储在那里。如果配置中心的配置泄露,那么密钥就会泄露。

如果密钥泄露,那么攻击者是否可以拦截客户端请求体,而解密出密码呢?

那么可以使用密钥管理系统来提高密钥的安全性。如KMS云服务,各个云服务厂商搜索KMS即可。或者自己部署一个开源软件密钥管理系统,如HashiCorpKeycloak 等项目。

关于Java加密解密代码

    @Test
     void encrypt() {
        String value="baeldung";
        final String key = "aesEncryptionKey";
        final String initVector = "encryptionIntVec";
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            String s = Base64.encodeBase64String(encrypted);
            System.out.println(s);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Test
    void decrypt() {
        String encrypted = "f3abc1/iSw92hEfjeZeZxA==";
        final String key = "aesEncryptionKey";
        final String initVector = "encryptionIntVec";
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            System.out.println(new String(original));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

关于AES

AES加密模式

AES padding,AES是块加密算法,因此加密的数据可能并不是16字节整数倍,因此填充数据使之成为16整数倍。

CBC需要初始向量,ECB不需要初始向量。

关于GPT

posted @ 2023-11-27 17:28  KeBoom  阅读(47)  评论(0编辑  收藏  举报