×
Namespaces

Variants
Actions

使用BouncyCastal进行RSA加解密算法处理

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

代码示例
文章
Amazing1100 在 15 Apr 2013 创建
最后由 hamishwillee 在 24 Jul 2013 编辑

Contents

需求

在Series 40中越来越多的CS应用,而且很多的在进行用户名,密码等信息验证时,都要求客户端使用服务器端给你的公钥对相关私密信息进行RSA加密后再发送到服务器端,然后服务器端再使用私钥进行解密,那么如何在Series 40中实现RSA加密就显得尤为重要了。


关于RSA

首先我们了解下什么是RSA加密算法: RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

 Rsa-process.jpg

在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然秘密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。 RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

Nokia SDK for Java 2.0 限制

在Nokia SDK for Java 2.0中是支持” SATSA-CRYPTO API”的,所以我们可以通过它来进行一系列算法的加解密工作,比如对称算饭:DES, 3DES/DESede, AES,非对称算法:RSA等。 但是我们知道在进行数据加密时,我们必须提供一个正确的密钥,然后转化为Key对象,我们才能在代码中使用它进行数据的加密,通过代码形式如下:

Key key = new SecretKeySpec(keyBits, 0, keyBits.length, "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);

但是”SecretKeySpec”这个类仅仅能被用于DES, AES等对称加密算法的密钥对象的生产,SATSA-CRYPTO并不支持使用公钥私钥对对一段消息进行加密,而且Nokia SDK for Java 2.0中是不支持SATSA-PKI的, 所以对于RSA这种非对称加密,那么我们必须另辟它径。

关于bouncy castle

Bouncy Castle 是一种用于 Java 平台的开放源码的轻量级密码术包。它支持大量的密码术算法,并提供 JCE 1.2.1 的实现。因为 Bouncy Castle 被设计成轻量级的,所以从 J2SE 1.4 到 J2ME(包括 MIDP)平台,它都可以运行。它是在 MIDP 上运行的唯一完整的密码术包。 我们可以通过它来实现我们想要的RSA加解密,那么首先我们看下如下配置它:

下载jar包

你可以到下面的链接中下载最新版本的jar包,在这里我们选择针对J2me的轻量级版本。 http://www.bouncycastle.org/latest_releases.html

配置

下载完成后,你需要把这个Jar添加到build path里面。 在Nokia IDE for JavaMe这个基于Eclipse的集成开发环境中,你可以添加,如下图:

Add-bouncycastal-lib.png

BouncyCastal RSA加解密相关API介绍

描述
org.bouncycastle.crypto.AsymmetricBlockCipher 一个非对称加密算法的接口,RSAEngine等算法都集成于它。
org.bouncycastle.crypto.CipherParameters 密钥的接口类,封装了密钥的相关成员属性等信息。
org.bouncycastle.crypto.encodings.PKCS1Encoding 一种编码方式,RSA加密所支持的Padding模式之一,还有RAW,OAEP等。
org.bouncycastle.crypto.engines.RSAEngine RSA加密的engine类,加解密工作都由它完成。
org.bouncycastle.crypto.params.RSAKeyParameters 集成于CipherParameters,用于公钥。
org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters 集成于CipherParameters,用于私钥。
org.bouncycastle.util.encoders.Hex 用来进行16进制的相关转化。

Demo演示

至此,有了上面的工作的后,我们就可以尝试使用BouncyCastal这个第三方库API来进行RSA的加解密了,下面我们来看一个Demo。

你可以从这里下载这个Demo File:BCEncreptTest.zip

创建公钥- RSAKeyParameters对象:

	private RSAKeyParameters getPubKey(String pubKey) {
RSAKeyParameters rsaPubKeyParam = null;
if (pubKey != null) {
BigInteger mypubkey_modulus = null;
BigInteger mypubkey_exponent = null;
 
try {
if(HexParam){
mypubkey_modulus = new BigInteger(module_hex, 16);
mypubkey_exponent = new BigInteger(exponent_hex, 16);
}
else{
mypubkey_modulus = new BigInteger(module_decimal, 10);
mypubkey_exponent = new BigInteger(exponent_decimal, 10);
}
 
// False stands for Encrypt
rsaPubKeyParam = new RSAKeyParameters(false, mypubkey_modulus, mypubkey_exponent);
System.out.println("Generate public key param Done !");
} catch (Exception e) {
System.out.println(e.toString());
}
 
}
return rsaPubKeyParam;
}


使用RSAEngine进行RSA加密:

		AsymmetricBlockCipher eng = new RSAEngine();  // RAW
//eng = new PKCS1Encoding(eng); //PKCS1
//eng = new OAEPEncoding(eng); //OAEP
 
eng.init(true, rsapubKey);
 
System.out.println("The String to be Encypted is: " + plainText);
 
byte[] inputdata = Hex.encode(plainText.getBytes());
 
try
{
outputdata = eng.processBlock(inputdata, 0, inputdata.length);
}
catch (Exception e)
{
System.out.println(e.toString());
}

从代码中可以看出,这里有3中padding模式,我们需要根据需要进行设置,并且保证加密和解密时,使用的是相同的模式。

创建私钥- RSAPrivateCrtKeyParameters 对象:

	private RSAKeyParameters getPriKey() {
BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
BigInteger pubExp = new BigInteger("11", 16);
BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
 
RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
 
return privParameters;
}


使用RSAEngine进行RSA解密:

	private byte[] rsaDecrypt(byte[] plainTextByte,CipherParameters privParameters) {
 
byte[] outputdata = null;
 
AsymmetricBlockCipher eng = new RSAEngine(); // RAW
//eng = new PKCS1Encoding(eng); //PKCS1
//eng = new OAEPEncoding(eng); //OAEP
 
eng.init(false, privParameters);
 
try
{
outputdata = eng.processBlock(plainTextByte, 0, plainTextByte.length);
}
catch (Exception e)
{
System.out.println("Decrypt error: " + e.toString());
}
 
return outputdata;
}


Log输出:

Rsa-demo-log.jpg

RSA算法对明文的Block的长度是有限制的,我们可以通过”RSAEngine. getInputBlockSize()”来获取允许的块的大小,比如我们这里获取出来的是127字节,我们进行加密的明文的长度不能超过此长度限制,如果超过那么我们必须进行分段处理, 然后才能进行加密,这一点很重要,请谨记。

需要注意,由于RSA非对称算法相对于DES等对称算法需要的系统性能和时间要求都高很多,所以一般我们只是用来保护最私密的数据,或者与AES等算饭混合使用。


最后我们看到,BouncyCastal这个库是较大的超过1M,对于很多Series 40手机,2M的包大小的限制,我们必须在打包时,进行混淆处理, 你可以使用Proguard,经测试,加入你仅仅使用RSA等加密API,混淆后的大小一般只有几十K,完全满足需要。

This page was last modified on 24 July 2013, at 13:26.
125 page views in the last 30 days.