1、前言
随着移动商业应用程序从时髦的口号逐渐变成现实,对于移动用户和无线应用程序开发人员而言,安全性正在成为一个重要方面。在移动商业网络中,网络整体安全性的强度取决于客户端设备,无线信号的可截取本质以及大多数手持设备有限的内存和计算能力。这些使无线系统极易受到数据窃贼的攻击。对于如何有效地保护自己的无线应用程序及运行应用程序的网络而言,开发平台的选择将始终起到举足轻重的作用。
将Java 平台用于无线设备开发的最大优点是能够生产可在多种平台上运行的可移植程序代码。但即使有这个优点,各种无线设备在内存、处理能力、电池寿命、显示屏大小 和网络带宽等方面的能力差异还是相当大的。不可能将运行在成熟的机顶盒上的应用程序的全部功能都移植到行动电话上。即使对于类似的设备(如 PDA 和高级智能电话),在两者间建立可移植性也常常使一种设备超负荷而另一种设备利用不充分。只能在多组类似设备之间实现真正的可移植性。因为认识到一种规格并不能适合所有设备,所以小心地设计 J2ME 以在可移植性和可用性之间取得平衡。
在安全性API方面,J2ME中的MIDP2.0规范提供了一套核心安全性API——JSR177,里面定义了一整套JAVA平台和智能卡交互的规则和API。
本文主要介绍JSR177标准所包含的内容,以及sun提供的符合此标准的satsa1.0开发包使用方法,最后给出了一些安全应用的示例代码。
2、JSR-177
JSR-177是一种基于手机和智能卡通信通道之上的Java编程接口,可以让手机Java应用访问运行在智能卡上的数据或者应用,包括访问加密功能。JSR-177也被称为安全和信任服务API(SATSA),它使得智能卡可以充当手机Java应用的“安全组件”,令手机应用可以执行定制操作、用户身份识别以及调用定制的应用。JSR-177的广泛使用将让第三方应用开发商可以充分发挥智能卡的作用。
SATSA(JSR-177)API分为两个部分:
1、 智能卡通讯API:支持与智能卡应用程序的通讯,通讯协议包含APDU,(U)STA,JCRMI。
2、 签名服务和用户凭证API:支持格式化数字签名;支持用户凭证管理,包括用户证书申请,添加用户凭证,删除用户凭证。
JSR-177包含了四个程序可选包:
1、 SATSA-APDU通讯包:支持与使用APDU的智能卡应用程序的通信;支持与(U)SIM卡的(U)SAT应用程序的通讯。
2、 SATSA-JCRMI通讯包:定义Java Card RMI客户端API以支持Java Card对象的远程方法调用。
3、 SATSA-PKI签名服务:支持应用层的数字签名和基本的用户凭证管理。
4、 SATSA-CRYPTO密码接口:提供了一些基本的密码操作,如消息摘要,签名验证,加密,解密。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/peterwanghao/7f1e88da63a84e22925c41207ca9d311.png)
SATSA结构图
关于更多详细的内容可以参看Java Community Process(JCP)关于JSR-177的定义,
http://jcp.org/aboutJava/communityprocess/final/jsr177/index.html。
3、SATSA1.0
Sun提供了实现JSR-177标准的开发包,其下载地址为:
http://java.sun.com/products/satsa/。目前只有windows版本satsa-1_0-windows.zip。
SATSA1.0需要与Java Card2.2.1一起运行。Java Card是Java 平台中最小的子集,其设定的执行环境为智能卡上的晶片或是有严格硬体限制的环境。Java Card技术是专门为那些内存和计算能力比J2ME设备更为受限的智能卡和其它设备提供的一个平台。在这里是将Java Card作为智能卡的模拟器。其下载地址为:
http://java.sun.com/products/javacard/dev_kit.html。
安装运行过程如下:
1、设置环境变量:设置JAVA_HOME;设置JC_HOME为Java Card的目录,如C:/java_card_kit-2_2_1。
2、设置PATH : 添加 %JAVA_HOME%/bin 和 %JC_HOME%/bin.;设置CLASSPATH :添加 %JAVA_HOME%/lib 和%JC_HOME%/lib。
3、将satsa-1_0-windows.zip解压到某个目录下,如C:/satsa1.0。并设置环境变量%MIDP_HOME%为C:/satsa1.0。
4、运行MIDP模拟器
C:/>%MIDP_HOME%/bin/midp
5、 运行智能卡模拟器
在这里我们使用系统自带的数据存储器EEPROM:%MIDP_HOME%/bin/jc_eeprom_image。
C:/>%JC_HOME%/bin/cref.exe %MIDP_HOME%/bin/jc_eeprom_image
SATSA1.0
支持以下内容:
l The PKI Card Application AID is: 0xA0 0x0 0x0 0x0 0x63 0x50 0x4B 0x43 0x53 0x2D 0x31 0x35
l The PKI Security Element ID is: WIM 1.01 SATSA RI
l Security element policy selecting a key already associated with a user certificate.
l Opaque signatures.
l Using the certificate instead of the certificate URI.
l CSR generation authorization through PIN entry (required).
l Store credential authorization through PIN entry (required).
Card application (WIM) requires PIN-G for data modification.
l Remove credential authorization through PIN entry (required).
Card application (WIM) requires PIN-G for data modification.
l Non-repudiation signature authorization through PIN entry (required).
l Authentication signature authorization (no PIN required).
l PIN-related functionality in SATSA-APDU and SATSA-JCRMI optional implementations.
l Two slots to attach a security element to the device.
l Three logical channels for the Reference Implementation security element.
l The int data type in the SATSA-JCRMI security element.
l TCP/IP as the transport protocol.
l The RSA algorithm in the SATSA-CRYPTO KeyFactory implementation.
l The MD2, MD5, and SHA-1 algorithms in the SATSA-CRYPTO MessageDigest implementation.
l The MD5withRSA and SHA1withRSA algorithms in the SATSA-CRYPTO Signature implementation.
l The DES (8 byte, 64 bit), the DESede (24 bytes, 192 bit), and the AES (16 bytes, 128 bit) keys in the SATSA-CRYPTO Cipher implementation. By default ECB is the mode and there is no padding. For the DES, DESede, and AES ciphers, CBC mode and PKCS5Padding are also available.
l The security element publishing its access control requirements in an Access Control File.
在
SATSA
中所有的
key
都为
RSA
密钥,长度为
512bits
。这里还包含了三个
PIN
:
l PIN 1 - a general purpose PIN that protects WIM data from modification and authentication keys. The value is 1234.
l Non-repudiation Key 1 PIN - protects the first non-repudiation key. The value is 2345.
l Non-repudiation Key 2 PIN - protects the second non-repudiation key. The value is 3456.
4、示例代码
4.1生成证书请求
使用RSA算法,生成512位长密钥对,生成证书CSR。
public void runGenCertReq() throws Exception {
Calendar bNow = Calendar.getInstance();
long b = bNow.getTime().getTime();
System.out.println(b);
boolean pass = true;
byte[] csr = null; // Buffer for generated CSR
String distinguishedName = "c=US,st=CA,l=Santa Clara,o=dummy CA,ou=JCT,cn=thehost"; // The DN
int rsaKeyLength = 512;
String securityElementID = new String("WIM 1.01 SATSA RI");
String securityElementPrompt = new String("Please insert smart card!");
boolean forceKeyGen = true; // Generate private key
// Generate a private key and a CSR
csr = UserCredentialManager.generateCSR(distinguishedName,
UserCredentialManager.ALGORITHM_RSA, rsaKeyLength,
UserCredentialManager.KEY_USAGE_NON_REPUDIATION,
securityElementID, securityElementPrompt, forceKeyGen);
Calendar eNow = Calendar.getInstance();
long e = eNow.getTime().getTime();
System.out.println(e);
System.out.println("Cert Request..." + (pass ? "pass" : "fail"));
System.out.println("使用时间: " + String.valueOf(e - b) + " 毫秒");
}
4.2摘要
生成消息摘要
public byte[] SHA1Digest(byte[] message) throws Exception {
String digestAlgo = "SHA-1";
int shaDigestLen = 20;
byte[] newDigest = new byte[shaDigestLen];
MessageDigest md;
md = MessageDigest.getInstance(digestAlgo);
md.update(message, 0, message.length);
md.digest(newDigest, 0, shaDigestLen);
return newDigest;
}
4.3签名
对字符串签名。
public byte[] RSASign(String toSign) throws Exception {
String securityElementPrompt = null;
String caName = "c=US,st=CA,l=Santa Clara,o=dummy CA,ou=JCT,cn=thehost";
String[] caNames = new String[] { caName };
byte[] signature = CMSMessageSignatureService.sign(toSign,
CMSMessageSignatureService.SIG_INCLUDE_CERTIFICATE
| CMSMessageSignatureService.SIG_INCLUDE_CONTENT,
caNames, securityElementPrompt);
return signature;
}
4.4验证签名
验证签名值。
public boolean RSAVerify(byte[] mesg, byte[] sign) throws Exception {
String sendersPublicKeyAlgo = "RSA";
byte[] sendersEncodedPublicKey = kRSAPublicKey;
X509EncodedKeySpec pks = new X509EncodedKeySpec(sendersEncodedPublicKey);
KeyFactory kf;
kf = KeyFactory.getInstance(sendersPublicKeyAlgo);
PublicKey sendersPublicKey = kf.generatePublic(pks);
Signature signature;
signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(sendersPublicKey);
signature.update(mesg, 0, mesg.length);
boolean signatureValid;
signatureValid = signature.verify(sign);
return signatureValid;
}
4.5加密
对字符串加密,生成密文。
public byte[] RSAEncrypt(String plainText) throws Exception {
byte[] bplainText = plainText.getBytes();
String keyAlgo = "RSA";
byte[] EncodedPublicKey = kRSAPublicKey;
X509EncodedKeySpec pks;
pks = new X509EncodedKeySpec(EncodedPublicKey);
KeyFactory kf = KeyFactory.getInstance(keyAlgo);
PublicKey publicKey = kf.generatePublic(pks);
byte[] cipherText = new byte[512];
Cipher cipher;
cipher = Cipher.getInstance(keyAlgo);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipher.doFinal(bplainText, 0, bplainText.length, cipherText, 0);
return cipherText;
}
4.6解密
对密文解密,生成原文。
public String RSADecrypt(byte[] cipherText) throws Exception {
byte[] myprivatekey = CLSBase64.decode("privatekey in pkcs8format");
Key key = new SecretKeySpec(myprivatekey, 0, myprivatekey.length, "RSA");
Cipher c2 = Cipher.getInstance("RSA");
c2.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = new byte[cipherText.length];
c2.doFinal(cipherText, 0, cipherText.length, decrypted, 0);
System.out.println("Decrypted String is:"
+ new String(decrypted).trim());
return new String(decrypted).trim();
}
5、总结
SATSA(JSR-177)标准定义了一套完整的加密服务,加固了在无线应用领域的安全性。但目前各厂家对此标准的支持程度各不相同。同时SATSA要求同智能卡配合,将证书,私钥保存在智能卡里以提高安全级别。在国内好像还没有WIM卡的应用,在SIM卡上运行PKI技术也还没有看到。在这方面还有很大的发展空间。
参考资料
l JSR-177标准说明
l The Security and Trust Services API for J2ME, Part 1
l The Security and Trust Services API (SATSA) for J2ME: The Security APIs