linux上java解加密(AES/CBC)异常:java.lang.SecurityException: JCE cannot authenticate the provider BC办法

  • Post author:
  • Post category:java


我的个人博客:

等待下一个秋


用mapreduce做数据清洗的时候,需要对数据进行解密,加密方法是:

AES/CBC/PKCS7Padding

,由于java本身不支持,需要添加依赖,用的依赖是:

<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.56</version>
</dependency>

加密解密用的工具类,附上代码:

package com.js.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;
import java.util.Arrays;

public class AESCBCUtil {
    // 算法名称
    final String KEY_ALGORITHM = "AES";
    // 加解密算法/模式/填充方式
    final String algorithmStr = "AES/CBC/PKCS7Padding";
    //
    private Key key;
    private Cipher cipher;
    boolean isInited = false;

    byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    public void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr, "BC");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 加密方法
     * @param content 要加密的字符串
     * @param keyBytes 加密密钥
     * @return
     */
    public byte[] encrypt(byte[] content, byte[] keyBytes) {
        byte[] encryptedText = null;
        init(keyBytes);
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedText;
    }
    /**
     * 解密方法
     * @param encryptedData 要解密的字符串
     * @param keyBytes 解密密钥
     * @return
     */
    public byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
        byte[] encryptedText = null;
        init(keyBytes);
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedText;
    }
}


windows开发mapreduce程序的时候,测试没问题,但是上linux集群就会报错:

这里写图片描述

愁死人了,从来没有遇到过这种问题,没办法,看博客!

其实,这是由于linux版本java与windows有一些区别导致的,解决方法如下:

1、在mvn仓库中找到下载的包bcprov-jdk15on-1.56.jar,或者如果你不用maven,只要能下载到这个包,放到linux的$JAVA_HOME/jre\lib\ext下面;

2、配置我的安全属性文件:

vim /usr/java/jdk1.8.0_112/jre/lib/security/java.security

    security.provider.1=sun.security.provider.Sun
    security.provider.2=sun.security.rsa.SunRsaSign
    security.provider.3=sun.security.ec.SunEC
    security.provider.4=com.sun.net.ssl.internal.ssl.Provider
    security.provider.5=com.sun.crypto.provider.SunJCE
    security.provider.6=sun.security.jgss.SunProvider
    security.provider.7=com.sun.security.sasl.Provider
    security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    security.provider.9=sun.security.smartcardio.SunPCSC
    security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

最后一个配置是我添加的,这里取10,是由自己文件内容编号来确定的;

由于是分布式集群,每个节点都要环境一样哦!

完成这些配置后,重新执行这个任务,成功,开心!



版权声明:本文为ddxygq原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。