具有CBC和PKCS7Padding的Java AES加密

时间:2018-11-04 09:11:41

标签: java encryption aes pkcs#7

我已经为此苦苦挣扎了几天。我需要使用采用加密参数的API。该API用C#编写。请求的加密如下:


算法:AES
密码模式:CBC
填充模式:PKCS7
块大小:128
密钥大小:256

Key:字符串->密钥是通过将提供的字符串转换为大小为32的字节数组来生成的:Encoding.ASCII.GetBytes(…)。 API声明字符串是使用字符串的MD5哈希函数由它们生成的。

IV:IV数组是通过将提供的字符串转换为大小为16的字节数组生成的:Encoding.ASCII.GetBytes(…)。

加密字符串的表示形式:Base64


在搜索并尝试了在线上建议的许多内容之后,我仍然无法生成相同的加密值(特别是默认情况下不支持PKCS7,而PKCS5应该工作相同,但事实并非如此)。这是我尝试过的一些事情:
1)使用充气城堡大罐使用PKCS7
2)添加JCE符合性,以便能够消除密钥和块大小的限制。

与他们联系后,他们向我发送了一个有效的android代码段(如果我在纯Java 8中运行,则会抱怨该提供程序(NoSuchAlgorithmException:找不到任何支持AES / CBC / PKCS7Padding的提供程序)):

public static String encrypt(String value) {
        String plainText = value;
        String escapedString;
        try {
            byte[] key = ENCRYPT_KEY.getBytes("UTF-8");
            byte[] ivs = ENCRYPT_IV.getBytes("UTF-8");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivs);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);
            escapedString = Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")), Base64.DEFAULT).trim();

            return escapedString;
        } catch (Exception e) {
            e.printStackTrace();
            return value;
        }
    }  

请提供任何帮助。

这是我尝试过的代码片段:

package com.melhem.TestJava;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class StringFunc {


    final static String key = "API_KEY_32_CHARs";
    final static String iv = "API_IV_16_CHARs";
    final static String algorithm = "AES/CBC/PKCS7Padding";
    private static Cipher cipher = null;
    private static SecretKeySpec skeySpec = null;
    private static IvParameterSpec  ivSpec = null;

    public static void main(String[] args) {
        System.out.println(encrypt("STRING_TO_ENCODE"));
    }

    private static void setUp(){
        try{
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
            skeySpec = new SecretKeySpec(key.getBytes("ASCII"), "AES");
            ivSpec = new IvParameterSpec(iv.getBytes("ASCII"));
            cipher = Cipher.getInstance(algorithm);
        }catch(NoSuchAlgorithmException | NoSuchPaddingException ex){

            ex.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static String encrypt(String str){
        try{
//            Integer strL = (int) Math.ceil(str.length() / 8.0);
//            Integer strB = strL*8;
//            str = padRight(str, ' ', strB);
            setUp();
            try {
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
                System.out.println("Block size: " + cipher.getBlockSize() * 8);
                System.out.println("Algorithm name: " + cipher.getAlgorithm());
                System.out.println("Key size: " + skeySpec.getEncoded().length * 8);
            } catch (InvalidAlgorithmParameterException ex) {
                ex.printStackTrace();
                return "";
            }
            byte[] enc = cipher.doFinal(str.getBytes("ASCII"));
            String s = new String(Base64.getEncoder().encode(enc));
            s = s.replace("+", "__plus__");
            s = s.replace("/", "__slash__");
            return s;
        }catch(InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex){
            ex.printStackTrace();
            return "";            
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
    }

    public static String padRight(String msg, char x, int l) {
        String result = "";
        if (!msg.isEmpty()) {
            for (int i=0; i<(l-msg.length()); i++) {
                result = result + x;
            }
            result = msg + result;
        }
        return result;
    }
}

1 个答案:

答案 0 :(得分:0)

Java Cipher package仅支持PKCS#7填充; AES/CBC/PKCS5Padding。使用这个;

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

对于大多数分组密码,#5和#7可以互换。请参阅Crypto.StackExchange

上的问题

,并且用于使用256位密钥大小的AES;

Java标准密码库限制为128位密钥大小。您必须去下载Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6