Java AES算法和OpenSSL配对

近日工作上的原因,需要实现Java  AES算法和C语言下基于OpenSSL的AES 算法通信。这是个老问题了,网上搜到不少资料,但都不是很详细,没能解决问题。只能自己来了。

先说说AES算法。AES算法的实现有四种,如CBC/ECB/CFB/OFB,这四种Java和C都有实现。AES算法还有末尾的填充(padding),java支持的padding方式有三种NoPadding/PKCS5Padding/,而C却不能显式的设置padding方式,默认的padding就是在末尾加 '\0'。这是一个大坑,多少人都坑在这了。另外,网上很多JAVA AES算法,很多都用SecureRandom,如果你的代码中出现了SecureRandom这个东西,那么你再也不能用C解出来了。

先说Java端的。从良心上说,java的封装比C要强多了。先上代码:

public static String encrypt(String content, String passwd) {
        try {
            Cipher aesECB = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec key = new SecretKeySpec(passwd.getBytes(), "AES");
            aesECB.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = aesECB.doFinal(content.getBytes());
            return new BASE64Encoder().encode(result);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public String decrypt(String content, String passwd) {
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
            SecretKeySpec key = new SecretKeySpec(passwd.getBytes(), "AES");
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
            byte[] result = new BASE64Decoder().decodeBuffer(content);
            return new String(cipher.doFinal(result)); // 解密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        <span></span>} catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

以上就是两个加密解密函数,默认使用AES算法的ECB,填充方式选择了PKCS5Padding。中间用到了Base64算法将加密后的字串进行再加密,主要是为了可视化读和传递。使用Base64算法要引用sun.misc.BASE64Decoder和sun.misc.BASE64Encoder;

Java就是这么简单,当然它一开始并没有这么简单,我也是从SecureRandom里面跳出来的。

关于openssl库,先看EVP。EVP是OpenSSL自定义的一组高层算法封装函数,它是对具体算法的封装。使得可以在同一类加密算法框架下,通过相同的接口去调用不同的加密算法或者便利地改变具体的加密算法,这样大提高 了代码的可重用性。当你使用EVP的时候你就会发现,它的使用方法和Java是那么的相似,以至于会产生他们的结果肯定会相同的遐想。在使用它之前,我们先来学习学些它的用法。我们这里取出了几个重要的函数列在下面:

【EVP_CIPHER_CTX_init】

该函数初始化一个EVP_CIPHER_CTX结构体,只有初始化后该结构体才能在下面介绍的函数中使用。操作成功返回1,否则返回0。

【EVP_EncryptInit_ex】

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/1cd2ab81a0b5f90e84bcc3ddfac05b70.html