从Eclipse 0.7.0版本开始,开始支持使用密码对MIDlet进行签名。 本文档提供了数字签名处理的背景知识,描述了手动对MIDlet套件进行数字签名的大概流程, 接着说明了EclipseME是如何处理的。
在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要在应用描述文件(JAD)和JAR清单(manifest)中声明其要求的权限,可以使用MIDlet-Permissions或MIDlet-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安全措施基于公钥加密法。基本步骤:
因为使用你的私钥加密的信息只有用对应公钥才能解密,所以只要你对私钥进行保密,这样全世界都可以确信,只要是能使用你的公钥进行解密验证的信息,都肯定来自于你。
然而,这个方案仍然回避了一个问题:别人如何知道一个公钥真的来源于你?如何防止我自称比尔·盖茨,并以他的名义签署文档?因此,不能仅仅把你的公钥包含在MIDlet套件中,而是要在MIDlet中加入一个包含你的公钥的数字证书。数字证书是由一个可信任的第三方(如Verisign)颁发的,来承诺保证此公钥确实是你的。
那么设备为什么能够信任来自Verisign的数字证书呢?因为设备在开发的时候已经预置了一个“根证书颁发机构(root certificate authorities)”的集合,他们总是可信的。证书本身是使用手机中预置的信息进行自签名的。这样,设备就可以使用预置的信息来验证数字证书确实是由Verisign颁发的。另外,你的证书也可以是使用一个“中介(intermediate)”的密钥签署的,而“中介”的公钥,是使用一个受信任的密钥签署的。这个机制叫做“证书链”。证书链中可以有多个中介的密钥,理论上链的长度可以是任意的,不过极少有包含多于2或3个连接的证书链。
因此,设置你的密钥的典型流程如下:
作为JDK的一部分,Sun同时提供了一个工具来帮你管理密钥。这个工具被恰如其分的命名为keytool。
使用下面的命令来产生一对公钥/私钥:
keytool -genkey -keyalg RSA -keystore <keystore file name>
这条命令指示工具产生一对新的RSA 公钥/私钥对,并把它们保存在给定的“密钥库(keystore)”文件中。作为此过程的一部分,工具要求你提供一系列关于你本人的信息。另外,还会询问你下列项目:
KeyAlias (密钥的别名) | 一个密钥库可以保存多个密钥/证书对。“别名”用来在密钥库中标识特定密钥/证书对。 |
Keystorepassword (密钥库密码) | 显然你的密钥库中并非人人可以访问。因此,密钥库文件是加密保存的。这个密码用来获取对密钥库的访问权限。 |
Keypassword (密钥的密码) | 使用密钥库密码,你可以访问密钥库中“公开”的那一部分——公钥和证书。而要访问私钥,则必须使用另外的密钥密码。此密码用来对私钥进行进一步的保护。 |
如果你愿意,可以在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套件进行签名了。
如果你不用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套件了:
如果最后一步的两项匹配,则移动设备可以确信
最后,很多设备会接着检查JAR文件中的MANIFEST.MF(清单文件) 要求获得的权限是否和JAD文件要求获得的权限相匹配。
正如你从上面看到的,把JADTool和EclipseME一起使用,你需要进行两步处理以部署你的MIDlet套件。首先使用EclipseME来构建MIDlet套件,然后得使用JADTool手动把签名加入到JAD文件中。你每次对MIDlet套件进行修改之后都不得不重复这个流程。每次你改了一行代码并想启动模拟器的时候都得这么做,显然这有些单调。
从EclipseME 0.7.0版本开始,它可以帮你完成以往只能用JADTool处理的工作了。使用此功能,请按照下面的步骤:
完成之后,EclipseME会自动处理原来需要JADTool完成的步骤。因此,在每次部署的过程中,你的MIDlet套件就会被自动签署。
当配置数字签名的时候,最好使用检查设置(Verify Settings)按钮。这样可以确保密钥库文件的路径,密钥的别名和它们的密码都是正确的。另外,因为密钥库可以管理多种类型的密钥,这个操作还会验证用指定的别名标识的密钥是否是可用来对MIDlet套件进行签名的正确类型(RSA)。
注意EclipseME目前还无法帮你获取用以对MIDlet套件进行签名的密钥/证书对。眼下,你仍然需要按照前面说过的步骤来产生一个密钥,并设法为它申请证书。不过,只要你把这些信息放入了你的密钥库,EclipseME就可以从中获取它们。
我们需要指出的一点是,EclipseME需要密钥库密码和密钥密码来对MIDlet套件进行签署。我们提供了三种方案,你可以用来管理这些密码:
不同的模拟器对签过名的MIDlet有不同的表现。很多模拟器允许你为模拟的MIDlet指定一个特定的安全域。对于支持此特性的模拟器,从EclipseME 0.7.0开始,在设定启动配置中增加了一个项目允许你指定安全域。
注意:如果你使用从颁证机构获得的证书来签署MIDlet(或者你为了测试而自己创建的证书),可能有必要把证书导入模拟器以保证你的签署过的MIDlet可以正常运行,尤其是在无线下载(OTA)模式下进行模拟的时候。另外也有可能你必须使用模拟器支持的证书来签署MIDlet。请查阅模拟器的文档来获取进一步的信息。
下面是一些关于数字签名处理过程和与数字签名有关的MIDlet属性的有用(但愿)参考资料: