首页 专题 - 实验 - 软件 - 管理 - 布线 - 方案 - 配置 - 问题 - 协议 - 下载 - 交换 - 路由 - 无线 - 安全 - 认证 - Cisco - 华为 - 网吧 - ADSL
您是本帖第620位浏览者 打印

[讨论] 保护您的 J2ME/MIDP 应用程序

保护您的 J2ME/MIDP 应用程序

如何在无线设备上使用 Bouncy Castle Crypto API 对 XML 文档进行数字签名和验证
级别:中级

XML 数字签名技术可以帮助您为无线 Web 服务应用程序实现轻量级且灵活的安全性解决方案。在本文中,Michael Yuan 讨论了 XML 数字签名及其应用程序的重要性。他还讨论了 Bouncy Castle 密码术包的数字签名 API,并提供了在 J2ME/MIDP 无线前端和 JSP 页后端之间的安全 XML 消息传递环境中的示例。
无线 Web 服务中的 Java 技术
基于 Java 的 Web 服务和无线 Java 开发是 JavaOne 2002 的两个最突出的主题。它们代表普及计算领域中未来的后端和前端 Java 技术。

Web 服务是基于标准 XML 通信协议的松耦合的可互操作的软件组件。Web 服务的使用使供应商能够在其核心竞争力所在的特定市场中提供服务。然后,客户可以根据其不同需要,从多个供应商选择采购服务。这种便利意味着 Web 服务完全适合于为无线前端提供服务。无线信息设备的便利和动态本质允许移动用户利用模块化的且动态可重新配置的后端服务。

Java 平台可以在无线 Web 服务应用程序开发中扮演几个重要角色。在无线端,Java 2 Micro Edition(J2ME)为所有无线设备(从蜂窝电话到复杂的家用无线信息家电)提供了跨设备的兼容性、高级语言功能和大量库。J2ME 的一个关键组件是移动信息设备框架(Mobile Information Device Profile(MIDP)),它在蜂窝电话和低端 PDA 上定义 Java API 和运行时环境。由于庞大数量的低端设备,期望在将来能够广泛部署 MIDP。

从 Web 服务端,Java 2 企业版(J2EE)已经具有所有必需的 API 和库来处理 Web 服务 XML 消息。通过 Web 服务接口或网关,可以方便地将用 EJB 技术实现的核心 J2EE 功能、JDBC API 和 RMI API 用于外部世界。为了将这些特性集合起来并启用无线 Web 服务应用程序,还提出了 J2ME Web 服务规范,目前它在 Java Community Process(JSR 172)中。

无线 Web 服务中的安全性
虽然基于 Java 的无线 Web 服务在普及移动商业世界中有一个光明的前途,但当前技术仍不成熟。安全性仍是剩下待解决的问题之一。无线通信是无线电波拦截容易获取的目标,而无线设备几乎没有任何计算能力来支持所有通信数据的强加密。此外,在后端,Web 服务运行在企业防火墙之外并使用开放消息传递协议来彼此交互。无线 Web 服务同样是易招受各种破解攻击的目标。已开发得很好的点对点安全性技术(如 SSL/TLS 和 HTTPS)不适合于多供应商、多中间 Web 服务网络拓扑图 — 重点必需集中在保护内容本身而不是传递内容的连接上。尽管面临新挑战,然而 Web 服务本身还是能用来增强移动商业安全性。新兴的 Web 服务安全性规范的出现使您能够将 Web 服务用作安全性实用程序。

在下面的段落中,我将讨论一种常用的安全性技术:数字签名。我将向您演示如何在 XML 消息中使用数字签名来保证端对端的数据完整性。我将应用一些示例来说明如何通过在无线端上使用流行的 J2ME/MIDP 平台并在后端上使用 JavaServer Pages(JSP)技术来实现 XML 数字签名。最后,我将讨论性能问题以及在当前 MIDP 设备上使用数字签名的可行性。MIDP 编程细节不在本文范围内;如果您需要复习一下,请参阅参考资料一节。

安全通信的元素
数据完整性只是保护通信的一个方面。数字签名也可以提供其它方面的解决方案。通常,安全的网络通信必须符合下列标准:
认证:通信双方必须标识其本身。公钥证书上的数字签名可以验证该公钥的可靠性以及持有它的那一方的可靠性。


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


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


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

使用数字签名保证数据完整性
让我们假设一下,您是一位股票交易者,当您不在交易大厅时,使用蜂窝电话来跟踪股票价格变化。在上下班途中,您的电话提醒您正在监视的一只股票的价格已经跌入您的心理最低价。现在,您应根据此提示买进它并利用此低价来赚一笔吗?在您采取任何行动之前,您必须绝对确保提示本身是可信的。如果竞争者可能拦截并更改消息(例如,更改股票代码),那么他就可能引诱您买进弄错的股票,并将他的高价位股票抛给您。您如何知道消息在从监视服务到您电话的途中没有被篡改呢?

数据完整性确实是通信安全性的最重要方面之一。物理上安全的网络十分昂贵,而且并不覆盖范围很广的地理区域。如果您的业务必须依靠因特网才能通信,那么您必须面对因特网本身几乎不提供安全性这一事实。因特网数据包在到达其目的地之前必须途经由非对话双方控制的多个路由器和主机。数据通信在无线因特网上特别容易受到攻击。

及时出现的援救工具是公钥基础设施(PKI)和数字签名。(和 MIDP 编程一样,数字签名不在本文范围内;感兴趣的读者可以参考参考资料一节来获取
相关主题

TOP

  清单 1. 创建已编码的摘要
static public String getDigest( String mesg ) throws Exception {

  SHA1Digest digEng = new SHA1Digest();
  byte [] mesgBytes = mesg.getBytes();
  digEng.update( mesgBytes, 0, mesgBytes.length );
  byte [] digest = new byte[digEng.getDigestSize()];
  digEng.doFinal(digest, 0);
  // Encode the digest into ASCII format for XML
  return (new String(Base64.encode(digest)));
}




在下几节中,我们将了解如何使用 Bouncy Castle 的 DSA、ECC 和 RSA 签名引擎来签署并验证数字签名。那些签名引擎使用不同的算法和不同的密钥,并且需要不同的参数。我们还将讨论如何将安全性信息(签名、摘要和公钥)嵌入 XML 文档。最后,我将比较三个签名引擎并提出今后的改进建议。

DSA 签名示例
方法 DSASigUtil.generateKeys() 生成密钥对。正如我讨论过的那样,这个步骤通常由中央认证中心在脱机状态下完成,如清单 2 所示:

清单 2. 生成密钥对
// Get a secure random source.
SecureRandom sr = new SecureRandom();

// Generate DSA parameters.
DSAParametersGenerator DSAParaGen = new DSAParametersGenerator();
DSAParaGen.init(1024, 80, sr);

DSAPara = DSAParaGen.generateParameters();

// Get DSA key generation parameters.
DSAKeyGenerationParameters DSAKeyGenPara =
          new DSAKeyGenerationParameters(sr, DSAPara);

// Generate keys.
DSAKeyPairGenerator DSAKeyPairGen = new DSAKeyPairGenerator();
DSAKeyPairGen.init( DSAKeyGenPara );
AsymmetricCipherKeyPair keyPair = DSAKeyPairGen.generateKeyPair();

privKey = (DSA**KeyParameters) keyPair.get**();
pubKey = (DSAPublicKeyParameters) keyPair.getPublic();




生成的公钥以参数 Y 来描述,并且用 pubKey.getY() 方法来检索它。参数 G、P 和 Q 描述模型。类 DSAUtil 中的下列方法检索模型和密钥参数,它们是重新构造公钥对象所必需的:

清单 3. 检索模型和密钥参数
public static String getG() throws Exception {
  return (new String(Base64.encode(DSAPara.getG().toByteArray())));
}
public static String getP() throws Exception {
  return (new String(Base64.encode(DSAPara.getP().toByteArray())));
}
public static String getQ() throws Exception {
  return (new String(Base64.encode(DSAPara.getQ().toByteArray())));
}
public static String getY() throws Exception {
  return (new String(Base64.encode(pubKey.getY().toByteArray())));
}




通过使用生成的私钥,实用程序类 DSASigUtil 可以从摘要获取两部分 DSA 签名 R 和 S:

清单 4. 检索 DSA 签名
static public String [] getSignature (String digest) throws Exception {
  // Sign
  DSASigner signer = new DSASigner();
  signer.init( true, privKey );
  BigInteger [] sigArray = signer.generateSignature( digest.getBytes());

  String [] result = new String [2];
  // Signature R
  result[0] = new String(Base64.encode(sigArray[0].toByteArray()));
  // Signature S
  result[1] = new String(Base64.encode(sigArray[1].toByteArray()));

  return result;
}




服务器将摘要、签名和密钥参数编码成 ASCII 文本格式并以 XML 数字签名格式嵌入该文本,如清单 5 所示:

清单 5. 编码并以数字签名格式嵌入
<SignedMesg>
  <mesg>Hello World</mesg>
  <Signature>
    <SignedInfo>
      <SignatureMethod
        Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
      <DigestValue>Ck1VqNd45QIvq3AZd8XYQLvEhtA=</DigestValue>
    </SignedInfo>
    <SignatureValue>
      <R>AMfVKyIUyPGdeUCtJxU N9kQJc2x</R>
      <S>RwGahqpopPx//bMYXzH8dtY0lhA=</S>
    </SignatureValue>
    <KeyInfo>
      <KeyValue>
        <DSAKeyValue>
          <G>
            FgLTXVdxKAmDQtQHkDdFF5zthKSpQhUCzRgXxz7yzxM
            OLYrRoj5D8AXdGLS 5CzT4gu55MbO62dBfyEWKbWTIO
            6E CuOfa53wvqjMl67tGxc8szgWWA6ZvRwVVVmJ6wqB
            m5hNLr7q1X2eJKQ u3XYpFflJktOjV8O3zeEPOtsTQ=
          </G>
         
            AOAu2WqVEKGTF8Zcxgde4vxc8f/Z hk8A10M0AtY2lU
            8CX54dz2MuD6hOmhqGXJxIVlV9085d9D0yHcMv2wl9V
            Vt0/ww aqFukCKZj9fHgZzq26nOBXMqibDo67J2vfQw
            EZMvCnyBXdS665whjzl5i7ubXu2Su AqsodnvG9pyYB
         
          <Q>AMjJUZy1RnQRqe/22BS83k2Hk8VR</Q>
          <Y>
            AM/9leouAW7nyON24xeqibMUpVOW8RyzcdNjp9NiPdfm
            HT42BvB4JL/cXx0tCbyHtcR5G vALoOo7Mh3JJ /gjx7

TOP