网络安全 频道

如何使基于JAVA技术的应用更安全(1)

注意:本文章原创并首发于安全矩阵(Security Matrix)后由原创作者友情提交到邪恶八进制信息安全团队
如何使基于JAVA
技术的应用更安全系列-(1)综述与JCE加密技术
作者:Fleshwound
Email:fleshwound@smatrix.org        
安全矩阵(Security Matrix):http://www.smatrix.org

1 引言
如果你系统被
黑客溢出了,那么你的应用程序和服务能够逃过一劫呢?如今基于J2EE的各种服务平台比比皆是,从学校的教务管理系统到大型的股票系统,从一般的个人网站到门户站点,JAVA似乎成为一种时尚(今天你JAVA了没有?),因此我觉得有必要谈谈基于JAVA应用安全的一些话题,我们的主题是:在黑客能以用户的身份访问你的系统的时候,如何使你的JAVA应用更安全。首先我们从流行的三层网络结构谈起:
2 基于Java
技术的三层网络结构
三层
网络结构,指的是将数据处理过程分为三部分:第一层是客户端(用户界面层),提供用户与系统的友好访问;第二层是应用服务层(也叫中间层),专司业务逻辑的实现;第三层是数据服务层(数据库系统),负责数据信息的存储、访问及其优化。由于业务逻辑被提取到应用服务层,大大降低了客户端负担,因此也成为瘦客户(Thin Client)结构,三层结构在传统的二层结构的基础上增加了应用服务层,将应用逻辑单独进行处理,从而使得用户界面与应用逻辑位于不同的平台上,两者之间的通信协议由系统自行定义。通过这样的结构设计,使得应用逻辑被所有用户共享,这是两层结构应用软件与三层应用软件之间最大的区别。三层结构将表示部分和业务逻辑部分按照客户层和应用服务层相分离,客户端和应用服务层、应用服务层和数据服务层之间的通讯、异构平台之间的数据交换等都可以通过中间件或者相关程序来实现。当数据库或者应用服务层的业务逻辑改变时,客户端并不需要改变,反之亦然,大大提高了系统模块的复用性,缩短开发周期,降低维护费用。以Java Applet为客户端, 以Java Servlet为中间层的三层网络结构,在目前的实时网络信息平台得到了广泛的应用,其结构和一般的三层结构如图1所示:



3 JAVA的安全盾牌-JAVA安全
技术
java几乎成为网络程序的标准语言,java给我们提供了先进的应用技术的同时,同时给我们提供了非常强大的安全技术。这些技术主要包括:
1 加密和解密
技术
2 JAVA源代码保护
技术
3
数据完整性保护技术(数字签名和消息摘要);
4 数字证书
技术
5 其它更高级的
技术(包括Kerberos技术和JAVA GSS-API技术等等);
Java加密扩展即Java Cryptography Extension,简称JCE。它是Sun的加密
服务软件,包含了加密和密匙生成功能。JCE是JCA(Java Cryptography Architecture)的一种扩展。
JCE没有规定具体的加密算法,但提供了一个框架,加密算法的具体实现可以作为
服务提供者加入。除了JCE框架之外,JCE软件包还包含了SunJCE服务提供者,其中包括许多有用的密码算法和数字签名算法,例如DES、RSA、DSA、SHA、MD5等。使用JCE进行加密解密非常方便,在后面我们将详细的讲述这一技术
4 如何最大限度的保证应用的安全性
系统被挂了我们可以重装系统,但是应用程序和
服务的敏感数据和信息被改了或者被盗窃了那我们只有祈祷上帝,希望攻击者能够良心发现。不过千万不要沮丧,我们可以利用JAVA为我们提供的一些武器来增强我们的信心,利用这些东西至少可以挡住99%以上的攻击行为,使我们的损失最小化。
(1)   使用JCE
技术来加密敏感信息和保护敏感信息的数字摘要;
(2)   使用JAVA Logging API建立日志和审核机制;
(3)   使用JAAS进行用户身份认证和授权;
(4)   利用数字签名
技术保证数据的完整性;
(5)   利用自定义的类加载器来加载加密后的JAVA类文件以抗击JAVA源代码分析和攻击;
(6)   使用JCE来构筑安全通讯协议来保证
数据传输的安全。
5使用JCE
技术来加密敏感信息和保护敏感信息的数字摘要
目前SUN公司的最新版本的JDK(JDK1.5)包含以下几种密码算法:
(1)DES:DES(
数据加密标准)是由 IBM 于上世纪 70 年代发明的,美国政府将其采纳为标准。它是一种 56 位分组密码。
(2)TripleDES:该算法被用来解决使用 DES
技术的 56 位时密钥日益减弱的强度,其方法是:使用两个密钥对明文运行 DES 算法三次,从而得到 112 位有效密钥强度。TripleDES 有时称为 DESede(表示加密、解密和加密这三个阶段)。
(3)AES:AES(高级加密标准)取代 DES 成为美国标准。它是由 Joan Daemen 和 Vincent Rijmen 发明的,也被称为 Rinjdael 算法。它是 128 位分组密码,密钥长度为 128 位、192 位或 256 位。
(4)RC2、RC4、和 RC5:这些算法来自领先的加密安全性公司 RSA Security。
(5)Blowfish:这种算法是由 Bruce Schneier 开发的,它是一种具有从 32 位到 448 位(都是 8 的整数倍)可变密钥长度的分组密码,被设计用于在软件中有效实现微处理器。
(6)其它:包括RSA、MD5、SHA、DAS等。
除此而外,由于JCE的开放性,JDK还支持第三方提供的密码算法。
在系统中,我们首先应该搞清楚的问题是:(1)该对什么
数据加密?(2)选择什么样的加密算法?(3)如何实现加密?
回答这三个问题对于不同的系统有不同的说法,通常是根据应用来定的。打个比方,银行系统有两个字段:开户人
帐号和开户人密码,那我们再权衡后会选择开户人密码。对于数据库系统而言,大规模加密会导致系统反映迟钝,严重影响效率。因此选择加密算法的时候必须考虑这点,对于数据加密我们用对称加密算法,对于对称加密算法密钥等信息我们可以使用公钥加密算法,对于流媒体我们可以采用流加密方法。下面我们来回答第三个问题,如何实现加密。
通过JCE使用对称加密算法的过程一般是这样的:
1 引入JCE加密算法库;
2 将要加密的
数据变成一个字节数组;
3 调用Cipher.getInstance建立一个Cipher实例;
4 选择加密模式,调用init方法传递密钥并初始化Cipher;
5 调用doFinal方法,传递要加密的字节数组进行加密;
6 将加密后的字节数组转变为普通的字符串类型。
需要注意的是因为加密后的密文是未知的,其中可能出现对应于ASCII行尾符或者文件尾符的密文,因此一般在应用中我们采用BASE64编码进行处理。下面我们给出示范源代码(实际使用的代码比这个要复杂得多,并要使用BASE64编解码):
/*
writer:fleshwound
*/
package myprojects.jce_smatrix;
import javax.crypto.*;
import java.security.*;
import java.io.*;
public class Jce_smatrix
{
  public static String s="welcome to smatrix!";
  public Jce_smatrix()
  {
  System.out.println("A JCE example begin:\n");
  System.out.println("plain text is:"+s+"\n");
    }
  public static void main(String args[]) throws Exception
  {
  Jce_smatrix jceexa=new Jce_smatrix();
 
  //初始化密钥
  KeyGenerator kg=KeyGenerator.getInstance("Blowfish");
  kg.init(128);
  SecretKey key=kg.generateKey();
  //加密
  Cipher c=Cipher.getInstance("Blowfish/ECB/PKCS5padding");
  c.init(Cipher.ENCRYPT_MODE,key);
  byte[] content=s.getBytes("UTF8");
  System.out.println("before ENCRYPT:");
  for(int i=0;i  System.out.print(content[i]+"\t");
  System.out.println("\n");
  byte[] encrypt=c.doFinal(content);
  System.out.println("after ENCRYPT:");
  for(int i=0;i  System.out.print(encrypt[i]+"\t");
  System.out.println("\n");
  System.out.println(" the encrypt text is:");
  System.out.println(new String(encrypt,"UTF8"));
  System.out.println("\n");
  //解密
  c.init(Cipher.DECRYPT_MODE,key);
  byte[] decrypt=c.doFinal(encrypt);
  System.out.println("the decrypt text is:");
  System.out.println(new String(decrypt,"UTF8"));
  System.out.println("A JCE example end!-fleshwound\n");
  }
}
以上是一个完整的JAVA使用BLOWFISH算法加密解密原理实例,当然这里也有些问题:就是所有的口令使用相同的密钥和相同的初始化会导致相同的密文,这样在应用之中字典攻击可能会有用武之地(这种强人到处都是,特别喜欢暴破!)。解决的方法有一个,就是加盐(Salt,此盐非彼盐也,乃干扰噪声信息之意,夫不见信号之中有椒盐噪声呼?)。下面我们给出一段加盐的代码:
import java.io.*;
import java.util.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class salt_smatrix{
  public static void main(String args[]) throws Exception{
    String s="welcome to smatrix!";
    char[] passwd=args[0].toCharArray( );
    PBEKeySpec pbks=new PBEKeySpec(passwd);
SecretKeyFactory kf=
SecretKeyFactory.getInstance("PBEWithMD5AndDES");
    SecretKey k=kf.generateSecret(pbks);
    byte[] salt=new byte[8];
    Random r=new Random( );
    r.nextBytes(salt);
    Cipher cp=Cipher.getInstance("PBEWithMD5AndDES");
PBEParameterSpec ps=new PBEParameterSpec(salt,1000);
    cp.init(Cipher.ENCRYPT_MODE, k,ps);
    byte ptext[]=s.getBytes("UTF8");
    byte ctext[]=cp.doFinal(ptext);
    // 将盐和加密结果合并在一起保存为密文
    FileOutputStream f=new FileOutputStream("saltencrypto.dat");
    f.write(salt);
    f.write(ctext);
    // 打印盐的值
    for(int i=0;i        System.out.print(salt[i] +",");
    }
    System.out.println("");
    // 打印加密结果
    for(int i=0;i        System.out.print(ctext[i] +",");
    }
  }
}
使用以上的加密方法是否已经很安全呢?一般说来,还不够,要必须保证
数据的完整性,我们采用的技术是数字签名。下面是一个使用MD5计算摘要的例子:
假设需要计算信息:message,
首先获得MD5实例:MessageDigest middleMD=MessageDigest.getInstance("MD5") ,
再添加要进行计算摘要的信息:middleMD.update(message.getBytes()),
再计算出MD5摘要:byte[] msgdigm= middleMD.digest(),所有的这一切是不是很简单?
我们来看个可以运行的完整例子(采用的是SHA-512算法):
import java.security.*;
import java.io.*;
public class digest_smatrix{
  public static void main(String args[ ]) throws Exception{
      System.out.println("one example of digest");
      String x="welcome to smatrix!";
      System.out.println("the text is:"+x);
      MessageDigest m=MessageDigest.getInstance("SHA-512");
      m.update(x.getBytes( ));
      byte s[ ]=m.digest( );
      String result="";
      for (int i=0; i        result+=Integer.toHexString((0x000000ff & s[i]) |
          0xffffff00).substring(6);
      }
      System.out.println("the digest of text(SHA-512):");
      System.out.println(result);
    }  
}
以上就是一些关于JCE加密和数字摘要的基本内容,如果想要了解更为详细的内容,可以在安全矩阵下载Java.Security.Solutions
地址为:http://www.smatrix.org/download/show.php?id=52
(下次的主题是(2)使用JAVA Logging API建立日志和审核机制-fleshwound)
0
相关文章