J2ME安全应用——Bouncy Castle Crypto API

http://blog.csdn.net/raorq/archive/2010/03/29/5427260.aspx

1 、前言

随着移动商业的不断发展,对于移动用户和 无线 应用 程序开发 人员而言, 安全 性正在成为一个重要方 面。 无线通信是无线电波拦截容易获取的目标,而无线设备几乎没有任何计算能力来支持所有通信数据的强加密。 而 目前 开发得很好的点对点安全性技术(如 SSL/TLS HTTPS 并 不 适合于多供应商、多中间 Web 服务 网 络拓扑图 。因此 重点 必须 集中在保护内容本身 而不是传递内容的连接上。

本文将讨论使用一种常见的安全性技术:数字签名。数字签名可以满足网络通讯安全的四方面标 准:

可认证性:通信双方必须标识其本身。公钥证书上的数字签名可以验证该公钥的可靠性以及持有它 的那一方的可靠性。

数据完整性:通信双方必须确保内容在传送期间不被改变。数字签名是保证数据完整性的最常用技 术。

数据机密性:有时候,通信数据是敏感的,必须保密。数字签名不提供数据机密性。我们必须使用 数据加密。

不可抵赖性:消息发送之后,发送方随后应该不能否认它。数字签名提供了部分解决方案。如果以 数字方式对消息进行签名,则发送方无法否认其责任,因为只有他能提供这种签名。

2 j2me 安全机制简介

J2ME 平台是由配置( Configuration ) 和简表( Profile )构成的。配置是提供给最大范围设备使用的最小类库集合,在配置中同时包含 Java 虚 拟机。简表是针对一系列设备提供的开发包集合。在 J2ME 中还有一个重要的概念是可选包( Optional Package ),它是针对特定设备提供的类库。

目前, J2ME 中有两个最主要的配 置,分别是 Connected Limited Devices Configuration CLDC ) 和 Connected Devices Configuration CDC )。 他们是根据设备的硬件性能进行区分的,例如处理器、内存容量等。 CLDC 主要针对那些资源非常受 限的设备比如手机、 PDA 、双工寻呼机等。而 CDC 主 要面对那些家电产品,比如机顶盒、汽车导航系统等。简表是以配置为基础的,例如 Mobile Information Devices Profile MIDP )就是 CLDC 上 层的重要简表。

CLDC 规范定义了 3 个 级别的安全机制:底层安全机制,应用级别安全机制和端对端的安全机制。在这里有一点需要强调的是字节码验证过程。 JVM 提 供了防止恶意代码进入企业系统的服务,字节码验证过程保证了应用程序不能访问内存空间或使用其域外的资源。字节码验证还防止应用程序重载 Java 语 言核心库,这是一种可以用来绕过其它应用程序级安全性措施的方法。但是,由于这种操作高昂的计算开销, MIDP VM 不 在运行时执行完整的字节码验证,而是增加了预审和机制。要求应用程序开发人员必须在把应用程序部署到移动设备中之前,在开发平台上预先验证类。预验证过程 优化执行流,创建应用程序中包含指令目录的堆栈映射( stackmap ),然后将堆栈映射添加到经 预验证的类文件。在运行时, MIDP VM 迅速地对字节码进行线性扫描,将每个有效的指令与合适 的堆栈映射项相匹配。

此外在 MIDP2.0 中规定了许可和 保护域概念。应用程序通过对敏感 API 提出许可申请来试图获得相应的权限。提供了信任域与非信任 域,不同的设备提供的保护域可能是不同的,一般我们开发的 MIDlet 都是存放到非信任域的。如果 想成为可信任的 MIDlet 需要想一个可信任的组织提出认证申请。

关于更多详细的内容可以参看 www.j2medev.com 撰 写的《 j2me 中文教程》,里面有对 j2me 安 全机制的详细介绍。

3 Bouncy Castle Crypto API

Bouncy Castle 是 一种用于 Java 平台的开放源码的轻量级密码术包。它支持大量的密码术算法,并提供 JCE1.2.1 的 实现。因为 Bouncy Castle 被设计成轻量级的,所以从 J2SE 1.4 J2ME (包括 MIDP ) 平台,它都可以运行。它是在 MIDP 上运行的唯一完整的密码术包。

不管 Bouncy Castle 包的功能有多强大,它有一个主要问题:缺少文档。 不存在在线文档,其 JavaDoc 写得并不好。与许多其它高级密码术包相似, Bouncy Castle 包广泛使用类型多态性来将常规概念与实现算法分开。对于初学者来说,辨认类之间的关系以及方法参数和返回值的 正确类型是很困难的。通常,开发人员必须浏览一下源代码和测试用例来研究做事的正确方法。

4 、示例代码

4.1 生成密钥对

使用 RSA 算法,生成 1024 位 长密钥对。

public void generateRSAKeyPair () throws Exception {

RSAPrivateCrtKeyParameters RSAprivKey = null;

RSAKeyParameters RSApubKey = null;

SecureRandom sr = new SecureRandom();

BigInteger pubExp = new BigInteger("10001", 16);

RSAKeyGenerationParameters RSAKeyGenPara =

new RSAKeyGenerationParameters(pubExp, sr, 1024, 80);

RSAKeyPairGenerator RSAKeyPairGen = new RSAKeyPairGenerator();

RSAKeyPairGen.init(RSAKeyGenPara);

AsymmetricCipherKeyPair keyPair = RSAKeyPairGen.generateKeyPair();

RSAprivKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate();

RSApubKey = (RSAKeyParameters) keyPair.getPublic();

}

4.2 签名

对字节数组签名。

public byte[] RSASign(byte[] toSign, CipherParameters RSAprivKey)

throws Exception {

if (RSAprivKey == null)

throw new Exception("Generate RSA keys first!");

SHA1Digest dig = new SHA1Digest();

RSAEngine eng = new RSAEngine();

PSSSigner signer = new PSSSigner(eng, dig, 64);

signer.init(true, RSAprivKey);

signer.update(toSign, 0, toSign.length);

return signer.generateSignature();

}

4.3 验证签名

验证签名值。

public boolean RSAVerify(byte[] mesg, byte[] sig, CipherParameters RSApubKey)

throws Exception {

if (RSApubKey == null)

throw new Exception("Generate RSA keys first!");

SHA1Digest dig = new SHA1Digest();

RSAEngine eng = new RSAEngine();

PSSSigner signer = new PSSSigner(eng, dig, 64);

signer.init(false, RSApubKey);

signer.update(mesg, 0, mesg.length);

return signer.verifySignature(sig);

}

4.4 加密

对字符串加密,生成密文。

public byte[] RSAEncrypt(String plainText ,CipherParameters RSApubKey)

throws Exception {

byte[] rv = null;

AsymmetricBlockCipher eng = new RSAEngine();

eng.init(true, RSApubKey);

byte[] ptBytes = plainText.getBytes();

rv = eng.processBlock(ptBytes, 0, ptBytes.length);

return rv;

}

4.5 解密

对密文解密,生成原文。

public String RSADecrypt(byte[] cipherText, CipherParameters RSAprivKey)

throws Exception {

byte[] rv = null;

AsymmetricBlockCipher eng = new RSAEngine();

eng.init(false, RSAprivKey);

rv = eng.processBlock(cipherText, 0, cipherText.length);

return new String(rv).trim();

}

4.6 证书解析

der 证书,获取证书信息。

public void ShowCert(byte[] cert) throws Exception {

ByteArrayInputStream bIn;

ASN1InputStream aIn;

bIn = new ByteArrayInputStream(cert);

aIn = new ASN1InputStream(bIn);

ASN1Sequence seq = null;

seq = (ASN1Sequence) aIn.readObject();

X509CertificateStructure obj = new X509CertificateStructure(seq);

TBSCertificateStructure tbsCert = obj.getTBSCertificate();

int version = tbsCert.getVersion();

String subject = tbsCert.getSubject().toString();

String issuer = tbsCert.getIssuer().toString();

long serial = tbsCert.getSerialNumber().getValue().longValue();

String sign = tbsCert.getSignature().getObjectId().getId();

// X509 Extensions

X509Extensions ext = tbsCert.getExtensions();

if (ext != null) {

Enumeration en = ext.oids();

while (en.hasMoreElements()) {

DERObjectIdentifier oid = (DERObjectIdentifier) en

.nextElement();

X509Extension extVal = ext.getExtension(oid);

}

}

}

5 、总结

Bouncy Castle 功能强大,支持大量的密码算法。特别 是提供在 MIDP 上对证书应用的处理接口,能够满足在移动设备上证书应用的需求。不足之处是其文档 太过简单,对类之间关系和参数含义理解困难,需要去阅读其原码。在性能方面,主要的瓶颈是公钥算法的速度比较慢。我在 WTK2.5 上 生成 1024 位的 RSA 密钥需要用时 2 分 钟左右。

参考资料

l TheBouncyCastleproject

http://www.bouncycastle.org/

l j2me 中 文教程

J2ME 开发网( www.j2medev.com

l Data security in mobile Java applications

http://www.javaworld.com/javaworld/jw-12-2002/jw-1220-wireless.html?page=1

你可能感兴趣的:(应用服务器,算法,网络应用,ext,企业应用)