关于对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)”文件中。作为此过程的一部分,工具要求你提供一系列关于你本人的信息。另外,还会询问你下列项目:

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套件进行签名了。

在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属性的有用(但愿)参考资料:

你可能感兴趣的:(eclipse,项目管理,配置管理,cvs,Nokia)