javax.crypto.Cipher线程安全问题

在项目中使用javax.crypto.Cipher进行AES加密时遇到线程安全问题,导致校验失败。分析发现Cipher实例在多线程环境下由于内部状态变化而不安全。解决方案包括使用ThreadLocal存储、每次操作时新建实例或在同步块中操作。
摘要由CSDN通过智能技术生成

项目场景:

某个项目中,需要对参数进行sign校验,其中用到了AES加密算法,于是使用了javax.crypto.Cipher进行加解密的运算。


问题描述

在压测中发现,偶尔会出现校验失败的情况。而生成sign的工具与被测试程序的算法是完全一致的,理论上不应该出现校验不通过,所以需要排查问题。


原因分析:

对被测试程序与测试工具分别进行了多线程测试,发现测试工具对同样的参数,每次生成的sign是一致的,而被测试程序偶尔会生成不同的sign,于是怀疑是并发导致的问题。

被测试程序与测试工具唯一的不同在于,被测试程序的Cipher是在初始时就实例化好的:

Cipher encryptCipher = Cipher.getInstance(ALGORITHM);
cipher.init(mode, keySpec, new IvParameterSpec(iv));

之后每次加密都直接使用该对象:

encryptCipher.doFinal(srcData.getBytes(StandardCharsets.UTF_8));

而测试工具是每次获得一个新对象:

Cipher encryptCipher = Cipher.getInstance(ALGORITHM);

cipher.init(mode, keySpec, new IvParameterSpec(iv));

encryptCipher.doFinal(srcData.getBytes(StandardCharsets.UTF_8));

通过查看源码与查阅资料可知, Cipher实例内部维护着自身的状态,在init或者doFinal时会改变自身状态,所以并非是线程安全的。

public final void init(int var1, Key var2, AlgorithmParameterSpec var3, SecureRandom var4) throws InvalidKeyException, InvalidAlgorithmParameterException {
        this.initialized = false;
        checkOpmode(var1);
        if (this.spi != null) {
            this.checkCryptoPerm(this.spi, var2, var3);
            this.spi.engineInit(var1, var2, var3, var4);
        } else {
            this.chooseProvider(2, var1, var2, var3, (AlgorithmParameters)null, var4);
    
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值