您的位置:首页 > 编程语言 > Java开发

基于JavaMail的邮件客户端--JustLook(四、邮件的本地存储与安全性问题)

2009-08-13 10:28 736 查看


上图是软件登陆后的界面截图,此时还没有接收邮件所以右侧为空,下面出于个人隐私遮盖了邮件地址。左侧是一个树形结构,收件箱内容为邮箱中存在的邮件,其余包含的内容都存储在本地。



每个邮箱对应一个文件夹,可以打开文件:



因为我已经对文件内容进行了加密,所以打开文件只能看到这些。而在软件中打开邮件时看到的则是解密后的内容。

邮件的本地存储

熟悉OutLook的朋友,应该会知道OutLook是将邮件以未解析的形式存储,地址应该为C:/Documents and Settings/“userName”/Application Data/Microsoft/Outlook/,新装的系统没有用过OutLook不确定是这个,如果不是请见谅。而我存储的是解析后的邮件内容。存储文件明文的结构形式大体如下:

<Email>

<Title>

<From></From>

<TO></TO>

</Title>

<Body>

<Text></Text>

<Attach></Attach>

</Body>

</Email>

以一种类似HTML代码的形式组织解析后邮件的内容信息。

安全性处理

很显然上述类似HTML代码的内容信息不安全,所以对它进行了加解密的处理。使用Sun公司提供的JCE应用程序编程接口中的PBEWithMD5And-DES算法,对本地文件信息进行加密和解密。当用户进入本地文件夹时,系统从相应位置读取文件内容解密后存储至内存,用户选择要打开的邮件后,从内存中选取数据,显示在阅读邮件窗体中。做Java的开发就是这样的简单,自己不必非要亲自去写加解密算法,拿来用就好了,大家都学过鲁迅先生批判拿来主义那篇文章“去其糟粕取其精华”,计算机的领域太广了,对于很多方面的东西,我们也只是用的时候拿来用,无法真正的深入到知识的层面。像这里用到的PBEWithMD5And-DES,你根本不用关心是如何实现的,找个例子照搬就行了,只需要改变参数就好了,不知道这是一件幸事还是无奈之举呢。言归正传,在这里我们只需要修改两个主要参数的值,一个是种子,一个是盐值。

CipherCodeFactory类用来生成加密、解密类的对象实例,代码如下:

package edu.cie.ciphercode;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEParameterSpec;

public class CipherCodeFactory {
public static javax.crypto.Cipher createEncryptCipher(String password){
javax.crypto.spec.PBEKeySpec keySpec = new javax.crypto.spec.PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = null;
SecretKey secretKey = null;
PBEParameterSpec parameterSpec = null;
javax.crypto.Cipher cipher = null;
byte []salt = {(byte)0x24, (byte)0x63, (byte)0x11, (byte)0xa4,
(byte)0xd2, (byte)0xdc, (byte)0x4w, (byte)0xf1,};//此处为盐值,可以自己设置
int iterationCount = 100;//迭代次数
try {
keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
secretKey = keyFactory.generateSecret(keySpec);
parameterSpec = new PBEParameterSpec(salt, iterationCount);
cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}

return cipher;
}

public static javax.crypto.Cipher createDecryptCipher(String password){
javax.crypto.spec.PBEKeySpec keySpec = new javax.crypto.spec.PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = null;
SecretKey secretKey = null;
PBEParameterSpec parameterSpec = null;
javax.crypto.Cipher cipher = null;
byte []salt = {(byte)0x24, (byte)0x63, (byte)0x11, (byte)0xa4,
(byte)0xd2, (byte)0xdc, (byte)0x4w, (byte)0xf1,};//此处为盐值,可以自己设置
int iterationCount = 100;//迭代次数
try {
keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
secretKey = keyFactory.generateSecret(keySpec);
parameterSpec = new PBEParameterSpec(salt, iterationCount);
cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}

return cipher;
}
}

DecryptAndEncryptFile类代码如下:

package edu.cie.ciphercode;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Vector;

import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

public class DecryptAndEncryptFile {

public static final String PATH = "C:" + java.io.File.separator + "JustLook"
+ java.io.File.separator;
public static javax.crypto.Cipher encrypt = null;
public static javax.crypto.Cipher decrypt = null;

public DecryptAndEncryptFile(String key){
encrypt = edu.cie.ciphercode.CipherCodeFactory.createEncryptCipher("111111");//此处为种子值,由你设定但必须想同
decrypt = edu.cie.ciphercode.CipherCodeFactory.createDecryptCipher("111111");
}

public String decryptFile(String fileName, String filePath) {
String temp = "";
String path = PATH + filePath;

File file = new File(path, fileName);
System.out.println("PATH: " + file.toString());

if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}

FileInputStream inputStream = null;

try {
inputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

CipherInputStream in = new CipherInputStream(inputStream, decrypt);
Vector<Byte> fileBytes = new Vector<Byte>();

try {
byte contents = (byte) in.read();
while (contents != -1) {
fileBytes.add(new Byte(contents));
contents = (byte) in.read();
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}

byte[] text = new byte[fileBytes.size()];
for (int i = 0; i < fileBytes.size(); i++) {
text[i] = ((Byte) fileBytes.elementAt(i)).byteValue();
}
temp = new String(text);

return temp;
}

public boolean encryptFile(String fileName, String text, String filePath) {
boolean flag = false;
String path = PATH + filePath;

File save = new File(path, fileName);
FileOutputStream fileOutputStream = null;

try {
fileOutputStream = new FileOutputStream(save);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}

CipherOutputStream out = new CipherOutputStream(fileOutputStream,
encrypt);
try {
out.write(new String(text).getBytes());
out.flush();
out.close();
flag = true;
} catch (FileNotFoundException e) {
} catch (IOException e) {
}

return flag;
}

}

比较我采用的方法与OutLook存储邮件采用的方法,OutLook保存的是未解析的邮件信息,一般是安全的,如果别有用心的人得到后,要去得到邮件内容其实也是件很容易的事情,而我的方法虽然用加密来降低了这种事情发生的可能性,但加解密势必会占用更多计算机资源影响效率,而且会出现一些问题,在后面介绍,不确定我的方法是否合适,但我是这么做的,而其已经做了。

存在的问题:

1.无法保存附件:保存邮件的时候只是保存了附件的名称,文件会丢失。如果采用OutLook哪种形式保存邮件,则不会出现这种问题。我想的解决问题的思路大概是这样子的:

a.找到附件的网络地址,看是否支持独立的下载功能,估计可能性很低。但如果支持问题就很简单了。

b.保存邮件的时候同时将附件下载到本地磁盘,以对话框的形式提示用户附件所在地址或者做一个假象,出现保存文件对话框,但其实实质上只是文件的本地磁盘间的拷贝。这个方法是肯定可以实现的,但不确定是否还有更好的方案。

2.人为破坏:如果有人不是想窃取你的信息,而是破坏,直接将文件夹删除或者对文件内容进行修改,就会造成信息丢失,或者在解析的时候无法正确解析的问题。这个问题OutLook也存在,甚至大多数软件都存在,不知道是否该把它称作问题。设计此软件的部分原因就是,避免对源邮件的操作,所以本地信息的删除破坏,不会影响源邮件。如果出现破坏性的删除修改现象,损失的其实只是本地存储的草稿等邮件。也只能是降低损失,要避免的话就比较麻烦了,要让一个文件夹无法删除,文件内容外部程序不得修改,不是一件简单的事情了。

3.肯定还有一个问题存在,刚才一闪而过,现在记不起来了,想起来的时候再说。

稍后带来新邮件提示功能的介绍包括声音提示和手机短信提示。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: