Archive

Archive for January, 2008

架设你的CruiseControl

January 28th, 2008 Sparkle 7 comments

说实在话,07年最大的感悟就是重新认识了TDD和持续集成的意义,这个下次有机会再说。这次要说的是部署一个持续集成服务器。

持续集成服务器的作用其实很简单,就是check out最新的代码,然后运行指定的script,然后把结果记录下来,还可以将结果(尤其是错误的结果)通过email等手段发给程序员。

事情倒是很简单,但是我们为什么要专门的软件呢,当然你也可以自己写bash script来做这些事情,做着做着你就会发现差不多实现一个CruiseControl出来了,呵呵,无谓重复发明轮子。

常用的持续集成服务器有CruiseControl、Luntbuild 和 Anthill等,相对来说CruiseControl比较老牌,支持度也比较好,不过实际使用的时候还是觉得不太好使(最近又发现了一个软件Hudson,Netbeans在使用)

下面是安装和配置过程,可能有一些细节不是很准确,因为已经是比较早之前安装的

从官方网站下载最新版的CruiseControl 2.7.1,我选用的是exe的版本,因为我的服务器是windows的,相对来说,exe版本有一些预设的参数,配置会简单些

运行安装程序,默认装在C:\Program Files\CruiseControl,可以不改动,而实际的项目文件可以放在其他盘上面的

安装成功之后运行cruisecontrol.bat,就能看到一个dos窗口运行,这个时候访问本机8080端口就可以看到一个示范项目

接下来修改配置文件

打开config.xml,可以看到示范例子的配置,把它都注释掉,不过其实我最后的配置也跟它差不多

直接贴我的配置吧,然后再来解释

<project name="xxx-xxx">
        <listeners>
            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
        </listeners>
        <bootstrappers>
            <svnbootstrapper localWorkingCopy="D:/cc/${project.name}" />
        </bootstrappers>
        <modificationset quietperiod="30">
		<svn localWorkingCopy="D:/cc/${project.name}"/>
        </modificationset>
        <schedule interval="300">
            <ant anthome="apache-ant-1.7.0" buildfile="D:/cc/${project.name}/build.xml"
target="svnup test" />
        </schedule>
        <log>
		<merge dir="D:/cc/${project.name}/target/testresult"/>
        </log>
</project>

首先是项目的名字,这个是必须的,中途可以用${project.name}来引用

listeners是监听事件,这里加了一个构建状态监听。CruiseControl默认把构建状态保存在logs/${project.name}/status.txt下,但是,这仅仅是成功or失败的状态,而没有具体的信息,加上这个配置的话,就能在首页看到是否成功的显示

bootstrappers和modificationset启动监听,其实我已经分不清他们两个的具体作用了(不好意思了,以后再翻一下补上),配置到你的项目目录中,我这里用了D:/cc/${project.name}。另外,你应该预先用svn checkout一份项目在这个位置,因为CruiseControl还要在该目录进行svn update的操作,所以这个目录的svn信息必须完整的,比如有.svn等文件,简单来说,也就是你可以在该目录成功运行“svn update”的命令

schedule里面放的是实际运行的script,很明显,我这里用了ant,调用了它的svnup和test两个target,为什么有个svnup的东西?呵呵待会说

最后是log,这个是用来合并ant输出日志的,如果你在CruiseControl的构建页面里面没有看到任何出错的详细信息,那就可能是没有合并日志,而ant脚本也必须配置成把相应的日志输出到设定的目录

基本的配置就是这样,这里还miss了一个ant的build.xml的内容,待会再介绍它,现在我先来说说CruiseControl的工作流程

CruiseControl通过内置的svn支持,定期检查localWorkingCopy目录的svn状态变化,然后触发构建script,但是,这里有一点必须主意的是,CruiseControl并没有svn update的功能,他仅仅是用内置的svn支持去检查你的目录是否有更新,但是具体的更新是由你来做,于是便有了很奇怪的ant svnup的target,待会你会看到它的内容

说实在话我觉得这种模式非常奇怪。而且如果检查的频率不够的话,svnup的时候,非常有可能update了好几个changeset下来,也就是说构建不是按照changeset分割的,仅仅是按照时间分割的

接下来就是build.xml的内容,我只列出跟CruiseControl相关的部分

<target name="test" depends="testcompile">
	<junit printsummary="true" fork="true">
		<classpath>
			...
		</classpath>
		<batchtest todir="target/testresult">
			<fileset dir="target/test">
				<include name="**/*Test.*" />
			</fileset>
		</batchtest>
	</junit>
</target>
<target name="svnup">
	<exec executable="svn">
		<arg line="up" />
	</exec>
</target>

这里需要主意的是,把测试结果输出到目录,然后在CruiseControl合并。另外一个当然是奇怪的svnup

这里有一个问题,如果你用海龟之类的svn client checkout项目,而你的机器上面没有装svn命令行的话,你可能不能使用我这个方法,需要有少少改动。其实就是用ant的svn支持来代替命令行的svn操作,具体可以研究ant的配置手册

基本就是这样了,重启你的CruiseControl,然后提交一些changge上svn,看看有没有结果输出吧

Categories: Uncategorized Tags:

优化你的Eclipse VM参数

January 26th, 2008 Sparkle No comments

最近dzone在讨论eclipse的VM参数
引用了一篇2004年的帖子

Here are the best options that I’ve found so far for my 2-processor Windows machine running JDK5.0 and Eclipse3.1:

-vmargs -XX:+UseParallelGC

2004年就用两个CPU都颇奢侈了吧

我现在的机器是双核+2G内存,于是我修改了一下eclipse的VM参数

打开eclipse.ini

修改或加入如下内容

-vmargs
-Xmx512m
-XX:+UseParallelGC

Categories: Uncategorized Tags:

我与Mercurial

January 25th, 2008 Sparkle 4 comments

最初知道 Mercurial这个工具其实是因为去年6月份看了cyfdecyf的一篇blog分布式版本管理工具:git & mercurial(作者搬迁了blog,新地址是这里).然后断断续续有在使用,一直想把一些经验写出来.最近刚好遇到云风在研究分布式版本管理,还是动手把一些经验写下来吧

一直一来都是用CVS,然后是SVN来做版本管理,最初认识分布式版本管理,是一个叫SVK的工具,是一个台湾人的作品,本身基于SVN,令到SVN可以分布式工作.当时觉得安装非常麻烦就没有研究下去了,而且本身对这样的功能需求也不大.后来Linus因为不满现有版本管理软件的问题,自己花了两个星期写了一个分布式版本管理Git,现在Linux kernel等源代码已经完全工作在Git的管理之上了.但是Git本身非常晦涩难懂,而且只能在Linux下运行,我本身也主要用Windows来工作,因此也没有深入研究.

直至看到 cyfdecyf的文章,这篇文章有坚定我研究分布式版本管理的信心.集中式版本管理的缺陷, cyfdecyf和云风都有描述了一些例子,我认为那些例子都很典型.如果所有开发人员都在一个房间里面,集中式版本管理是最好的,最明显的例子就是公司的开发,大家都能直接访问到服务器,网络不会中断.这种情况下,使用分布式版本管理反而增加了复杂性.但是,如果开发人员不是在同一个房间,甚至在不同的国家.当然你也可以在Internet上假设一个SVN服务器.但是,开发人员不一定有网络,或者网络不一定很好.而每次提交,或者同步,都要花上好几分钟或者更长时间,这非常影响开发.又或者你只是私人的项目,而你有没有能力假设公开的SVN服务器.而且我只是一个人,为什么每次都要提交到外边的服务器.当然也可以在自己的机器上面架设一个SVN,但是如果你有两台以上的机器就会觉得很麻烦了.

所有的这些场景,其实你需要一个分布式版本管理.cyfdecyf的文章最后在选择Git的代替品,定了用Mercurial.那我也从Mercurial开始吧.不过Mercurial的中文资料非常少,我始终不理解分布式版本管理的原理.最后,非常搞笑的情况是,我其实是看了Git的一份中文资料才真正明白的,也推荐大家从Git的中文资料入手.

待续…

Categories: Uncategorized Tags:

如何用Java进行3DES加密解密

January 5th, 2008 Sparkle 1 comment

最近一个合作商提出使用3DES交换数据,本来他们有现成的代码,可惜只有.net版本,我们的服务器都是Linux,而且应用都是Java。于是对照他们提供的代码改了一个Java的版本出来,主要是不熟悉3DES,折腾了一天,终于搞定。

所谓3DES,就是把DES做三次,当然不是简单地DES DES DES就行了,中途有些特定的排列。这个我可不关心,呵呵,我的目的是使用它。

在网上搜索了一下3DES,找到很少资料。经过朋友介绍,找到GNU Crypto和Bouncy Castle两个Java扩充包,里面应该有3DES的实现吧。

从GNU Crypto入手,找到一个TripleDES的实现类,发现原来3DES还有一个名字叫DESede,在网上搜索TripleDES和DESede,呵呵,终于发现更多的资料了。

Java的安全API始终那么难用,先创建一个cipher看看算法在不在吧

Cipher cipher = Cipher.getInstance("DESede");

如果没有抛异常的话,就证明这个算法是有效的

突然想看看JDK有没有内置DESede,于是撇开Crypto,直接测试,发现可以正确运行。在jce.jar里面找到相关的类,JDK内置了。

于是直接用DES的代码来改&测试,最后代码变成这样

SecureRandom sr = new SecureRandom();
DESedeKeySpec dks = new DESedeKeySpec(PASSWORD_CRYPT_KEY.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
return new String(Hex.encodeHex(cipher.doFinal(str.getBytes())));

需要留意的是,要使用DESede的Spec、Factory和Cipher才行

事情还没完结,合作商给过来的除了密钥之外,还有一个IV向量。搜索了一下,发现有一个IvParameterSpec类,于是代码变成这样

SecureRandom sr = new SecureRandom();
DESedeKeySpec dks = new DESedeKeySpec(PASSWORD_CRYPT_KEY.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
IvParameterSpec iv = new IvParameterSpec(PASSWORD_IV.getBytes());
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, securekey, iv, sr);
return new String(Hex.encodeHex(cipher.doFinal(str.getBytes())));

但是,运行报错了

java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV

ECB是什么呢?我的代码完全没有写ECB什么的

又上网搜索,结果把DES的来龙去脉都搞清楚了

http://www.tropsoft.com/strongenc/des.htm

ECB是其中一种字串分割方式,除了DES以外,其他加密方式也会使用这种分割方式的,而Java默认产生的DES算法就是用ECB方法,ECB不需要向量,当然也就不支持向量了

除了ECB,DES还支持CBC、CFB、OFB,而3DES只支持ECB和CBC两种

http://www.tropsoft.com/strongenc/des3.htm

CBC支持并且必须有向量,具体算法这里就不说了。合作商给的.net代码没有声明CBC模式,似乎是.net默认的方式就是CBC的

于是把模式改成CBC

Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");

成功运行了

后话:

搜索的过程中,找到一个不错的讨论

http://www.lslnet.com/linux/dosc1/21/linux-197579.htm

在CBC(不光是DES算法)模式下,iv通过随机数(或伪随机)机制产生是一种比较常见的方法。iv的作用主要是用于产生密文的第一个block,以使最终生成的密文产生差异(明文相同的情况下),使密码攻击变得更为困难,除此之外iv并无其它用途。因此iv通过随机方式产生是一种十分简便、有效的途径。此外,在IPsec中采用了DES-CBC作为缺省的加密方式,其使用的iv是通讯包的时间戳。从原理上来说,这与随机数机制并无二致。

看来,向量的作用其实就是salt

最大的好处是,可以令到即使相同的明文,相同的密钥,能产生不同的密文

例如,我们用DES方式在数据保存用户密码的时候,可以另外增加一列,把向量同时保存下来,并且每次用不同的向量。这样的好处是,即使两个用户的密码是一样的,数据库保存的密文,也会不一样,就能降低猜测的可能性

另外一种用法,就是类似IPsec的做法,两部主机互传数据,保证两部机的时钟同步的前提下(可以取样到分钟或更高的单位避免偏差),用时钟的变化值作为向量,就能增加被sniffer数据的解密难度

Categories: Uncategorized Tags: ,

如何用Java进行DES加密解密

January 5th, 2008 Sparkle 2 comments

这篇其实是引子,直接贴代码,不多解释了

SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(PASSWORD_CRYPT_KEY.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
return new String(Hex.encodeHex(cipher.doFinal(str.getBytes())));
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(PASSWORD_CRYPT_KEY.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
return new String(cipher.doFinal(Hex.decodeHex(str.toCharArray())));
Categories: Uncategorized Tags: ,