CNJM首页 | 业界新闻 | 手机软件 | 终端应用 | 资源下载 | 开发文档 | EclipseME | CNJM论坛 加入收藏 | 设为首页  
logoTop pad
logoBottom
首页
历史
目录
先决条件
安装
创建一个新项目
创建一个新MIDlet
运行/调试
打包发布
高级话题
参考
常见问题
提交问题报告
技术支持
EclipseME开发者
许可证

Eclipse Ready Logo
SourceForge.net Logo


CNJM.net
spacer


关于对MIDlet套件进行数字签名

从Eclipse 0.7.0版本开始,开始支持使用密码对MIDlet进行签名。 本文档提供了数字签名处理的背景知识,描述了手动对MIDlet套件进行数字签名的大概流程, 接着说明了EclipseME是如何处理的。

  1. 背景知识
  2. 基本步骤
  3. 使用EclipseME进行数字签名
  4. 密码管理
  5. 模拟运行
  6. 参考资料

背景知识

在MIDP 1.0规范中,所有MIDlet都使用一个“沙盒(sandbox)”安全模式来运行。 因此实质上,MIDlet只能只能访问MIDP 1.0规范中限定的API集,以及打包在同一MIDlet套件中的库。

MIDP 2.0 (JSR-118) 把“受信任的(trusted)”和“不可信的(untrusted)”概念引入了MIDlet套件。 一个“不可信的”套件运行在与MIDP 1.0一样的限制环境中——所有可用的API集都只能是MIDP规范的一部分。 而“受信任的”套件则可以被赋予访问设备的更多API的权限。另外,作为MIDP 2.0规范的一部分, 某些“标准”API也需要授权才能访问。 比如,一个不可信MIDlet套件必须能够访问javax.microedition.io.HttpConnection API, 但是系统需要用户确认是否允许MIDlet套件使用这个API。

而另一方面,受信任的MIDlet套件则不需要用户明确授权就可被赋予该API的访问权限, 而且可以访问那些禁止不可信MIDlet访问的API。

对MIDlet套件进行数字签名的基本步骤

进行数字签名的基本步骤如下:

  1. 在JAD文件和manifest(清单)中包含你的MIDlet套件要求获得的权限列表
  2. 获取适当的密钥/证书对来进行数字签名
  3. 在MIDlet套件的部署过程中进行最后的数字签名步骤

在JAD文件和manifest(清单)中包含你的MIDlet套件要求获得的权限列表

MIDlet要在应用描述文件(JAD)和JAR清单(manifest)中声明其要求的权限, 可以使用MIDlet-PermissionsMIDlet-Permissions-Opt 这两种标签之一。 可以使用上面的标签指定多种权限,之间用逗号分隔。 在安装过程中,设备需要检查MIDlet要求的权限。 如果在MIDlet-Permissions中声明了某种权限, 那么设备要么就要把MIDlet安装在保护域中并赋予其相应权限,要么就必须中止安装。 而如果权限是声明在MIDlet-Permissions-Opt标签中的, 且MIDlet套件未被授予对适当保护域的访问权限,安装则是可以继续的,但套件无法获得其要求的访问权限。 所以,如果你的MIDlet套件依赖于某种权限,不能在没有它的情况下运行, 那么对该权限的要求应该声明在MIDlet-Permissions之中。

如果你的应用程序可以使用某种权限,但即使未获得该权限也能运行, 那么使用MIDlet-Permissions-Opt来请求访问权限。 如果你的MIDlet未被授予对某种特性的访问权限,那么尝试访问该特性会导致抛出SecurityException异常(安全性异常)。 值得注意的是对于HTTP,某些设备提供商略微的违反了规范的约定,抛出的是IOException异常(输入输出异常), 而不是SecurityException,这是为了对MIDP 1.0保持兼容的临时性措施。 对于这点请与你的无线工具包提供商的文档进行核对。

下面是一个JAD文件的例子,其中包含对权限的请求。 这个MIDlet套件要求必须拥有对HTTP和HTTPS的访问权限, 并且希望访问PushRegistry(推送注册), VideoControl.getSnapshot(拍照), 以及SMS(短信)。如果后三个被拒绝,套件能够调整且对用户仍有价值。

MIDlet-Permissions: javax.microedition.io.Connector.http, 
                    javax.microedition.io.Connector.https
MIDlet-Permissions-Opt: javax.microedition.io.PushRegistry, 
                        javax.microedition.media.control.VideoControl.getSnapshot, 
                        javax.wireless.messaging.sms.receive, 
                        javax.wireless.messaging.sms.send

在这个例子里,HTTP和HTTPS不是可选权限。因为应用程序已经申明不能在缺少它们的情况下运行, 所以如果设备不能在安装时授予这些权限,安装就会中止。是否可以进行授权决定于设备的安全策略, 以及MIDlet是否是受信任的。为了成为受信任的MIDlet,就必须对MIDlet进行数字签名。

获取适当的密钥/证书对来进行数字签名

MIDlet安全措施基于公钥加密法。基本步骤:

  1. 创建一对公钥/私钥。
  2. 使用私钥对MIDlet套件进行数字“签名”。
  3. 接着把公钥作为MIDlet套件的一部分来发布,使任何人都可以验证此数字签名。

因为使用你的私钥加密的信息只有用对应公钥才能解密,所以只要你对私钥进行保密, 这样全世界都可以确信,只要是能使用你的公钥进行解密验证的信息,都肯定来自于你。

然而,这个方案仍然回避了一个问题:别人如何知道一个公钥真的来源于你? 如何防止我自称比尔·盖茨,并以他的名义签署文档? 因此,不能仅仅把你的公钥包含在MIDlet套件中,而是要在MIDlet中加入一个包含你的公钥的数字证书。 数字证书是由一个可信任的第三方(如Verisign)颁发的,来承诺保证此公钥确实是你的。

那么设备为什么能够信任来自Verisign的数字证书呢? 因为设备在开发的时候已经预置了一个“根证书颁发机构(root certificate authorities)”的集合, 他们总是可信的。证书本身是使用手机中预置的信息进行自签名的。 这样,设备就可以使用预置的信息来验证数字证书确实是由Verisign颁发的。 另外,你的证书也可以是使用一个“中介(intermediate)”的密钥签署的, 而“中介”的公钥,是使用一个受信任的密钥签署的。这个机制叫做“证书链”。 证书链中可以有多个中介的密钥,理论上链的长度可以是任意的,不过极少有包含多于2或3个连接的证书链。

因此,设置你的密钥的典型流程如下:

  • 使用工具软件产生一对公钥/私钥。
  • 产生一个包含你的公钥的“证书申请”,并发送到证书颁发机构。
  • 证书颁发机构进行一些调查,以核实你对自己身份的声明与事实相符。 具体进行哪些调查,每个颁证机构的做法不同。
  • 当颁证机构核实你的声明和真实身份确实相符之后(并且向他们交费之后), 他们会把你的公钥用一个证书包装起来,并发还给你。
  • 你把证书导入自己的密钥库,这样你要对什么东西进行签名的时候就可以随时使用了。

作为JDK的一部分,Sun同时提供了一个工具来帮你管理密钥。 这个工具被恰如其分的命名为keytool

使用下面的命令来产生一对公钥/私钥:

keytool -genkey -keyalg RSA -keystore <keystore file name>

这条命令指示工具产生一对新的RSA 公钥/私钥对,并把它们保存在给定的“密钥库(keystore)”文件中。 作为此过程的一部分,工具要求你提供一系列关于你本人的信息。 另外,还会询问你下列项目:

Key Alias (密钥的别名) 一个密钥库可以保存多个密钥/证书对。“别名”用来在密钥库中标识特定密钥/证书对。
Keystore password (密钥库密码) 显然你的密钥库中并非人人可以访问。因此,密钥库文件是加密保存的。 这个密码用来获取对密钥库的访问权限。
Key password (密钥的密码) 使用密钥库密码,你可以访问密钥库中“公开”的那一部分——公钥和证书。 而要访问私钥,则必须使用另外的密钥密码。此密码用来对私钥进行进一步的保护。

如果你愿意,可以在keytool的命令行上直接指定上面的所有参数。 请运行

keytool -help

或者到Sun的网站上参考进一步信息。

如果你只是想“玩玩”数字签名,你可以跳过这一节直接阅读关于签署(signing)的讨论。 当生成你的密钥之后,keytool自动向密钥库中加入一个“自签署证书”。 这个证书格式正确,可用来对MIDlet套件进行签名。 但是记住这并不能使你的MIDlet套件成为受信任的成品, 因为你的手机无法使用任何一个它信任的颁证机构来验证这个“个人的”证书。 而要想达到那个效果,你仍然必须按照上面的流程来申请证书。 不过,如果你只是想体验一下EclipseME的数字签名支持,这个“自签署”的证书倒是足够用了—— 日后你可以等待获取一个“真正的”证书。

要使用keytool来产生一个证书申请,可以用下面的命令行:

keytool -certreq -keystore <keystore file name> [-storepass <storepass>]
             [-alias <alias>] [-file <request file>] [-keypass <keypass>]

在括号中的项目是可选的——keytool会自动询问你那些未在命令行中指定的项目。

产生你的证书申请之后,就可以把它寄给颁证机构。 当他们把证书发回给你之后,你需要使用下面的命令行把它倒入你的密钥库中:

keytool -import -keystore <keystore file name> [-storepass <storepass>]
             [-alias <alias>] [-file <certificate file>] [-keypass <keypass>]

此命令行会使用颁证机构颁发给你的、签过名的证书替换掉原来使用keytool生成的“自签署”证书。 到这里你就真正准备好使用密钥库中的信息对MIDlet套件进行签名了。

在MIDlet套件的部署过程中进行最后的数字签名步骤

如果你不用EclipseME,可以使用JADTool来签署你的套件。 JADTool是由Sun及许多其他厂商和他们的无线工具包一起提供的。

使用JADTool需要两步:首先使用下面的命令把JAR的签名加入到JAD文件中

java -jar JADTool.jar -addjarsig -keypass <password> -alias <key alias>
        -storepass <password> -keystore <keystore> -inputjad <filename> 
         [-jarfile <filename>] [-outputjad <filename>]

这个命令计算JAR文件的校验和,然后使用你的私钥对此校验和进行签名,然后把结果编码到JAD文件中。 第二步是把你的公钥证书添加入JAD文件,使用以下命令

java -jar JADTool.jar -addcert -keypass <password> -alias <key alias>
        -storepass <password> -keystore <keystore> -inputjad <filename>
         [-jarfile <filename>] [-outputjad <filename>]

这个命令从密钥库中提取证书,对它进行编码,然后添加入JAD文件。 到这里,你的MIDlet套件就被完全的签名了。如果你检查签名之后的JAD文件, 你会看到其中包括类似下面的两行:

MIDlet-Jar-RSA-SHA1: VPHnTUqz5+R6G29HTtEfIC4DOpXzpCa9U3zBqe0kGhOitgh1wwdcK4jcQnfj
STD9kPRfheWiIwC8xeCs08wdlE9xY/v8veYic0cj6GtSm03EgL5Mc+KRSNfitVIL7xa5LWY7yTCi7IkiI
DqC+dP8KQjoCReGsU0YoPM9iq6b6dM=

MIDlet-Certificate-1-1: MIICUjCCAbsCBEGjQ2AwDQYJKoZIhvcNAQEEBQAwcDELMAkGA1UEBhMCV
VMxCzAJBgNVBAgTAkZMMRMwEQYDVQQHEwpGb3J0IE15ZXJzMRIwEAYDVQQKEwlFY2xpcHNlTUUxFDASBg
NVBAsTC0RldmVsb3BtZW50MRUwEwYDVQQDEwxLZXZpbiBIdW50ZXIwHhcNMDQxMTIzMTQwNDE2WhcNMDU
wMjIxMTQwNDE2WjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCRkwxEzARBgNVBAcTCkZvcnQgTXllcnMx
EjAQBgNVBAoTCUVjbGlwc2VNRTEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxFTATBgNVBAMTDEtldmluIEh1b
nRlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1uL1PGDcD/u1Ki12gZntby2lJmizbzDpbLSV30
fs5BRO21dC2XY99X7igoc0+O2Ic5qSzY7x2r9rQf0c+d8hA9T3w4tjQBNizEdkvxFNcFFNrAo5MdzWvcU
PiCODqthy1O9LrCAomp/+2d5N+TGOgtUXocgDPouaT/rfKQujI5sCAwEAATANBgkqhkiG9w0BAQQFAAOB
gQBIQ4ECwjj3spYOhxsih55F7e0Prx+evi6VYBaWoZTGKjevnW3IkKTijytdoMpBX3r7oBjAIibFlSEqU
JfJRMszq/L9JOnIcEKRIvkW8yN/Ls8pWB5VEir2EUh3kiIgk2zo7uhbjs58b5bOjWhTZMhQjPI22I23Tq
a/HKXNBsTL3A==

第一行是加密后的JAR文件校验和,第二行则是包含你的公钥的证书。 如果颁证机构把一个中介证书随同你的证书一同颁发给你(一个多重证书链), 那么还会有一个MIDlet-Certificate-1-2项目。

对MIDlet套件签名之后,你的移动设备就可以使用下面步骤验证你的MIDlet套件了:

  1. 重新计算产生JAR文件的校验和。
  2. 验证JAD文件中的证书可以一直回溯到设备信任的某个颁证机构。
  3. 从证书中提取你的公钥。
  4. 从JAD文件中提取出当初加入的、加密过的JAR校验和
  5. 使用你的公钥把校验和解密。
  6. 把解密后的校验和与第一步中计算出的校验和进行比较。

如果最后一步的两项匹配,则移动设备可以确信

  • 此MIDlet套件确实是由你签署的。如果是其他人签署的,那么解密过程无法成功, 因为你的公钥不会和别人的私钥相匹配。
  • 自从你签署过之后,此MIDlet套件未被修改。否则,校验和就会不一样。

最后,很多设备会接着检查JAR文件中的MANIFEST.MF(清单文件) 要求获得的权限是否和JAD文件要求获得的权限相匹配。

使用EclipseME进行数字签名

正如你从上面看到的,把JADTool和EclipseME一起使用,你需要进行两步处理以部署你的MIDlet套件。 首先使用EclipseME来构建MIDlet套件,然后得使用JADTool手动把签名加入到JAD文件中。 你每次对MIDlet套件进行修改之后都不得不重复这个流程。 每次你改了一行代码并想启动模拟器的时候都得这么做,显然这有些单调。

从EclipseME 0.7.0版本开始,它可以帮你完成以往只能用JADTool处理的工作了。 使用此功能,请按照下面的步骤:

  1. 在JAD编辑器的可选属性面板中向JAD文件加入你想要的MIDlet-PermissionsMIDlet-Permissions-Opt项目。 作为部署过程的一部分,EclipseME会自动把这些项复制到JAR文件中的MANIFEST.MF文件。
  2. 项目属性对话框中,允许对项目进行数字签名, 并指定要用的密钥库和密钥的别名。

完成之后,EclipseME会自动处理原来需要JADTool完成的步骤。 因此,在每次部署的过程中,你的MIDlet套件就会被自动签署。

当配置数字签名的时候,最好使用检查设置(Verify Settings)按钮。 这样可以确保密钥库文件的路径,密钥的别名和它们的密码都是正确的。 另外,因为密钥库可以管理多种类型的密钥, 这个操作还会验证用指定的别名标识的密钥是否是可用来对MIDlet套件进行签名的正确类型(RSA)。

注意EclipseME目前还无法帮你获取用以对MIDlet套件进行签名的密钥/证书对。 眼下,你仍然需要按照前面说过的步骤来产生一个密钥,并设法为它申请证书。 不过,只要你把这些信息放入了你的密钥库,EclipseME就可以从中获取它们。

密码管理

我们需要指出的一点是,EclipseME需要密钥库密码和密钥密码来对MIDlet套件进行签署。 我们提供了三种方案,你可以用来管理这些密码:

  • 可以设置成让EclipseME把这些密码保存为MIDlet套件项目的一部分。如果你选择此选项, 你就要在项目属性中输入这些密码。 EclipseME会把它们保存在项目的.eclipseme文件中。 为了保护这些密码,它们以加密形式保存。 因此,这可以防止别人在不经意的查看.eclipseme文件的时候就推导出密码。 但这个方法并非万无一失,因为别人可以访问EclipseME的源码以分析密码的加密算法。 不过,在很多环境下,这个方案已经足够安全了,对于“设置并忘记”的做法也很方便, 即使项目是被多个开发者共享的。
  • 一个稍微更安全些的选择是让EclipseME把密码保存在工作空间的密码环(keyring)文件中。 默认情况下,这个文件位于
    [workspace>]\.metadata\.plugins\org.eclipse.pde.core\eASEE\org.eclipse.core.runtime\.keyring,
    不过你可以用-keyring命令行参数来让Eclipse使用指定的文件。 如果你使用CVS来共享你的项目,此文件是不会被共享的。 Eclipse自动对keyring文件的内容加密(这是Eclipse保存你的CVS密码的地方)。 你可以使用-keyring-password 命令行参数来指定Eclipse在非默认位置以非默认密码保存密码环以提高此方案的安全性。
  • 最安全的选项是根本不让EclipseME和Eclipse保存你的密码,而是在需要的时候提示你输入。 使用这个设定,EclipseME会在需要密码的时候弹出一个对话框。 为了给你少添点麻烦,EclipseME会在接下来的会话中把密码保存在内存中, 这样你不用一次一次的重新输入。当你关闭Eclipse,或是改变工作空间的时候, 这些密码就会被“忘记”。使用此选项,密码绝不会被保存在你的硬盘上。

模拟运行

不同的模拟器对签过名的MIDlet有不同的表现。 很多模拟器允许你为模拟的MIDlet指定一个特定的安全域。 对于支持此特性的模拟器,从EclipseME 0.7.0开始, 在设定启动配置中增加了一个项目允许你指定安全域。

注意:如果你使用从颁证机构获得的证书来签署MIDlet(或者你为了测试而自己创建的证书), 可能有必要把证书导入模拟器以保证你的签署过的MIDlet可以正常运行, 尤其是在无线下载(OTA)模式下进行模拟的时候。 另外也有可能你必须使用模拟器支持的证书来签署MIDlet。 请查阅模拟器的文档来获取进一步的信息。

参考资料

下面是一些关于数字签名处理过程和与数字签名有关的MIDlet属性的有用(但愿)参考资料:



Copyright © 2005, http://www.eclipseme.org. All rights reserved. 本中文版由中国Java手机网<www.cnjm.net>翻译