openssl c++实现bouncycastle中AES加解密

0x01 为什么要用bouncycastle


先说说JCE(Java Cryptography Extension)是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现。
它提供对对称、不对称、块和流密码的加密支持,它还支持安全流和密封的对象。它不对外出口,用它开发完成封装后将无法调用。由于美国出口控制规定,JCA是可出口的,但是JCE对部分国家是限制出口的。因此,要实现一个完整的安全结构,就需要一个活多个第三方厂商提供JCE产品,称为安全供应商。bouncycastle JCE就是其中一个安全供应者。

举个例子:

在向一个国际CA发送签名请求后,CA会返回PKCS12格式的个人信息交换文件(.p12,.pfx)。此时使用sun自带的提供者(provider)进行读取产生私钥信息(keystore)时,

  KeyStore ks = KeyStore.getInstance("PKCS12", "SUN");
  ks.load(new FileInputStream("visa.p12"), "password".toCharArray());

可能(只是可能)会抛出

java.io.IOException: unsupported PKCS12 bag type 1.2.840.113549.1.12.10.1.1
        at com.sun.net.ssl.internal.ssl.PKCS12KeyStore.a(Unknown Source)
        at com.sun.net.ssl.internal.ssl.PKCS12KeyStore.engineLoad(Unknown Source)
        at java.security.KeyStore.load(Unknown Source)

这种情况就需要选用bouncycastle第三方完成读取产生私钥信息。


0x02 如何在JAVA环境中使用


第一步,首先到https://bouncycastle.org/latest_releases.html下载对应的jar包,我这里下载是bcprov-jdk14-143.jar


第二步,将bcprov-jdk14-143.jar拷贝到%JAVA_HOME%/jre1.8.0_60/lib/ext/目录下,并修改java_security文件


第三步,在eclipse中创建java工程


按向导创建





第四步,引入provider类名并注册使用

import org.bouncycastle.jce.provider.*;
 Security.insertProviderAt((Provider)new BouncyCastleProvider(), 1);
 is = new BufferedInputStream(new FileInputStream(crypt12FileEnc));
            int length = is.available();
            System.out.println("length:" + length);           
            cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");       
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(aesK, "AES"), new IvParameterSpec(aesIV));            
            isCipher = new CipherInputStream(is, cipher);
            os = new FileOutputStream(decryptedZlibFile);
            int templen = 0;
            while((read=isCipher.read(buffer))!=-1) {  
            	templen += read;
                System.out.println("read:" + read);
		        os.write(buffer, 0, read);             
		    }

            System.out.println("allread:" + templen);
            os.close();
            is.close();


这个时候,可能会报java异常

exception:Illegal key size
java.security.InvalidKeyException: Illegal key size
	at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
	at javax.crypto.Cipher.init(Cipher.java:1393)
	at javax.crypto.Cipher.init(Cipher.java:1327)
	at crypt12.main(crypt12.java:81)


这个时候美帝限制出口导致的,没关系我们去下载无限制的策略文件local_policy.jar和US_export_policy.jar替换jdk和jre下的两个j相同名字的ar包

  • jdk对应jar包的路径:D:\Java\jdk1.8.0_60\jre\lib\security
  • jre对应jar包的路径:D:\Java\jre1.8.0_60\lib\security

我这里是jdk8,所以对应的下载
地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

当然还有其他版本的:

jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR
jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html


0x03 如何用openssl实现AES加解密


在openssl中EVP_CIPHER的使用跟java里面Cipher的使用及其相似,真怀疑是不是相互有借鉴。但要注意EVP_CIPHER_CTX_ctrl的使用是不可或缺的,在加解密中若忽略此函数的使用,会直接导致加解密失败,使用方法如下:

#define BUFFERSIZE 8192

EVP_CIPHER_CTX	ctx;
	const EVP_CIPHER *cipher = EVP_aes_256_gcm();
	EVP_CIPHER_CTX_init(&ctx);
	EVP_CIPHER_CTX_set_padding(&ctx, 0);

	EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL);
	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL);
	EVP_DecryptInit_ex(&ctx, NULL, NULL, (unsigned char*)aesK, (unsigned char*)aesIV);

	int index = 0;
	std::ofstream zlibOfs(zlibFile.c_str(), std::ios::binary);
	while (needCryLen > 0)
	{
		memset(buffer, 0, BUFFERSIZE);
		memcpy_s(buffer, BUFFERSIZE, cryBuffer + BUFFERSIZE * index, needCryLen <= BUFFERSIZE ? needCryLen - 20 : BUFFERSIZE);

		int outLen = 0;
		int decryOutLen = 0;
		EVP_DecryptUpdate(&ctx, (unsigned char*)outBuffer, &outLen, (unsigned char*)buffer, needCryLen <= BUFFERSIZE ? needCryLen - 20 : BUFFERSIZE);
		decryOutLen += outLen;
		EVP_DecryptFinal_ex(&ctx, (unsigned char*)outBuffer, &outLen);
		decryOutLen += outLen;
		zlibOfs.write(outBuffer, decryOutLen);
		index++;
		needCryLen = needCryLen - BUFFERSIZE;
	}
	zlibOfs.close();
	EVP_CIPHER_CTX_cleanup(&ctx);



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值