2008年6月1日星期日

非安全线路上的密码传输与登录

这个东西是给新版出校做准备而写的。因为校园网里,密码嗅探和会话劫持的几率比较大,所以不能将密码的明文,或者固定的哈希在网络上发送。这样就需要使用 一个动态的密码验证协议。本来是打算使用类似NTLM那样的挑战/相应式的验证的,但是后来大树说其实可以用随机值加md5就可以。虽然MS NTLM的安全性更好,但是相对比较复杂。所以后来就使用了后面一种实现方式。
大致流程如下:
1:服务器启动,初始化一个RSA密钥对
2:客户向服务器发送预登录请求,服务器生成一个随机值R,一个时间戳T,用生成的密钥对R和T签名得到签名S,吧R、T和S返回给客户
3:客户端收到R、T、S,把R和密码的unicode拼接在一起,求出哈希值H1,然后吧S、R、T、H1和用户名U发送到服务器。
4:服务器接收到S、R、T、H1、U以后,首先检查R与T的签名是否符合S,确定R与T的真实性后检查T是否超时,之后根据U取得用户的密码,与R拼接,求哈希H2,然后检查H1是否等于H2。这些步骤中间任何一步出错将导致验证失败。

这个方法的Java实现我正在写,等写完了再发上来。

某个Google控又回来啦

某人一向控Google而无视Baidu,奈何前些天Google pages 抽风,连接不能。经过骨头同志介绍,转战Blogger。等Google Pages 修复以后吧以前的资料弄回来~

2008年4月30日星期三

关于高斯模糊和不完备Java实现

前两天发图片马赛克时青姐问的,今天没事研究了一下:
1)什么是高斯模糊:
高斯模糊,是依靠正态分布函数的图像模糊算法,我们知道,正太分布函数曲线是中间高,两边低的对称图形,周边像素与某像素的距离为自变量,用这个函数的取值当作系数,分别乘以周边像素的ARGB值,然后把结果相加,可以得到一个新的ARGB,这个值就是模糊后图像的对应像素的ARGB值。
由于正太分布的曲线是中间高两边低,所以所得的像素与原来的像素相似度最大,也就基本上保持了原来图形的基本形状,并且其边缘也被模糊了
上面的话是我自己打的,可能有些表述不清,具体的可以到Wikipedia上搜索一下,那里的表述是很详细的。
2)高斯模糊的具体实现:
首先要生成高斯系数矩阵:

public static double[] gMatrix(double s, int r) {
double[] ret = new double[r];
double a = 1 / (2d * s * s);
double b = Math.sqrt(a * (1 / Math.PI));
double c = Math.exp(a);
for (int i = 0; i < r; i++) {
ret[i] = b * Math.pow(c, -i * i * 1d);
//ret[i+r-1] = Math.pow(Math.sqrt(Math.PI*2D*s*s), -1)*Math.exp((-i*i)/(2*s*s));
}
return ret;
}

然后是针对每像素操作的函数:

public static byte[] getARGB(int j) {
byte b = (byte) (j & 0x000000ff);
byte g = (byte) ((j & 0x0000ff00) >> 8);
byte r = (byte) ((j & 0x00ff0000) >> 16);
byte a = (byte) ((j & 0xff000000) >> 24);
return new byte[]{a, r, g, b};
}

public static int getInt(byte[] bytes) {
//System.out.println(Arrays.toString(d));
return ((bytes[0] << i =" 1;" i =" 1;" a =" src[i]" b =" p[i]" x =" (a" d="%d" x="%x]\n" x =" x"> 0xFF ? 0xFF : x;
src[i] = (byte) (x & 0xff);
}
}

下面是针对一个图像行(横线或纵向)的操作

public static int[] smoothLine(int[] data, double[] mtx) {
int[] ret = data.clone();
for (int i = 0; i < d =" getARGB(data[i]);" k =" 1;" nd =" getARGB(data[i">= 0) {
byte[] nd = getARGB(data[i - k]);
procByte(nd, mtx[k]);
// System.out.println("" + (i - k) + "," + Arrays.toString(nd));
addByte(d, nd);
// System.out.println("plus:" + Arrays.toString(d));
}
}

ret[i] = getInt(d);
//System.out.printf("final:%s 0x%08X\n", Arrays.toString(d), ret[i]);
}
return ret;
}

最后是针对整个图像的操作:

public static BufferedImage smooth(BufferedImage i, double s, int r) {
BufferedImage ret = new BufferedImage(i.getWidth(),

i.getHeight(),

i.getType());
double[] mtx = gMritex(s, r);
for (int j = 0; j < i.getHeight(); j++) {
int[] data = i.getRGB(0, j, i.getWidth() - 1, 1,

null, 0, i.getWidth());
//System.out.println(Arrays.toString(data));
data = smoothLine(data, mtx);
//System.out.println(Arrays.toString(data));
ret.setRGB(0, j, i.getWidth() - 1, 1,

data, 0, i.getWidth());
}
// for (int j = 0; j < i.getWidth(); j++) {
// int[] data = ret.getRGB(j, 0, 1, i.getHeight()-1, null, 0, i.getHeight());
// //System.out.println(Arrays.toString(data));
// data = smoothLine(data, mtx);
// //System.out.println(Arrays.toString(data));
// ret.setRGB(j, 0, 1, i.getHeight()-1, data, 0, i.getHeight());
// }
return ret;
}

这里需要说明几点:本来高斯模糊是矩阵运算的,但是可以化简为线性运算,也就是横竖各处理一次(至于原因参看Wikipedia)但是我发现使用 JavaAPI对竖向像素列操作十分费时,所以就把它暂时注释掉了。但是这样模糊的结果就不是完全高斯模糊的结果。我想应该吧横向处理过的图像做90度翻转,然后再横相处理一次。不过这个想法还没顾得上实施。有时间再写。
另外一个问题是:处理过的图像最右边会有一道黑线,不知道是为什么,希望有高人能够说明一下。

刚才发现好多正态分布都写成了正太分布……感觉好邪恶的样子=_=|||
最后是完整代码,里面还有Wikipedia的高斯模糊的词条页,省的伟大的GFW和谐掉我们的网络。

2008年4月5日星期六

你可能不知道的:突破Java单例模式

这个东西是以前写代码注入时发现的。这两天实在无聊,所以写出来,仅供参考。MS没什么使用价值。。。。权当娱乐
我们知道,在Java中有一种单例模式,是在一个虚拟机里,某个对象只有一个实例。但是,真的只能有一个实例么?
考虑下面代码:


import java.io.InputStream;
public interface IOnlyOne{
void printOne();
}
public class OnlyOne implements IOnlyOne{
private static final OnlyOne myOne = new OnlyOne();
public void printOne(){
System.out.println(myOne);
}
public static void main(String[] args) throws Exception{
myOne.printOne();
OnlyOneLoader loader = new OnlyOneLoader();
IOnlyOne o = loader.createNewOne();
o.printOne();
}
}
public class OnlyOneLoader extends ClassLoader{
public IOnlyOne createNewOne() throws Exception{
InputStream is = getClass().getResourceAsStream("OnlyOne.class");
byte[] b = new byte[is.available()];
is.read(b);
Class clz = defineClass(null,b, 0, b.length);
Object o = clz.newInstance();
return (IOnlyOne) o;
}
}

我们看到createNewOne()首先定义了一个类OnlyOne,然后实例化了一个对象。那么根据代码来看,这个对象的printOne方法又会访问那个myOne的静态成员。看起来两次打印的结果应该是相同的,但是事实上,结果并不相同。
那么,这是为什么呢?是不是定义类过程中又对那个myOne对象重新赋值了呢?我们可以在o.printOne();后面再加上一句myOne.printOne();
可以看到,打印的和第一次的结果是一样的。这就说明了并不是重新赋值,而是有两个myOne的变量存在。
事实上,Java中,一个类是可以存在多个定义的,这些类的类名可以相同,但是确可以有各自的成员存储区,他们的代码也可以不同。在同一个 ClassLoader中,不允许出现重名类,但是Java却允许多个不同的ClassLoader同时存在。需要注意的是:即使类名和代码都相同,但是不同ClassLoader说产生的类是不兼容的,这就是为什么上述代码中要引入一个接口的原因了。你可以把那个接口去掉,看看会发生什么有趣的现象~~
那么,这个和单例模式有什么关系呢?因为单例的对象实例是存储在静态成员变量中的,所以在不同的ClassLoader下,这个变量的值可能是不同的。

2008年4月4日星期五

没事干,PS两张证书来玩

最近看Gundam Seed,无聊之时就PS两张认证出来。猜猜原来的认证是什么证书的?

2008年2月5日星期二

凉宫春日的忧郁12话中长门友希写的程序

今天一不小心在网上看到的,代码如下:
==================================分割线==================================

#include
#include
#include

void InjectHook(PROCESSENTRY32 pe32)
{
printf("テストデバッグ プロセスID:%d プロセス名:[%s]\n",pe32.th32ProcessID,pe32.szExeFile);
}
#define _TEXT(a) (a)

BOOL CheckProcessModule(DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL,dwPID);
if (hModuleSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot(of modules)");
return ( FALSE );
}
CloseHandle(hModuleSnap);
// (ここから先は読みとれず)
return (TRUE);
}

BOOL GetProcessList()
{
HANDLE hProcessSnapshot;
HANDLE hProcess;
PROCESSENTRY32 pe32;
hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
if (hProcessSnapshot == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,_TEXT("CreateToolhelp32Snapshot"),_TEXT("ERROR"),MB_OK);
return( FALSE );
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if ( Process32First(hProcessSnapshot,&pe32) == NULL)
{
MessageBox(NULL,_TEXT("Process32First"),_TEXT("ERROR"),MB_OK);
CloseHandle(hProcessSnapshot);
return ( FALSE );
}

do
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);
if (hProcess != NULL)
{
if(CheckProcessModule(pe32.th32ProcessID))
{
InjectHook(pe32);
}
}
CloseHandle(hProcess);
}
while( Process32Next(hProcessSnapshot,&pe32));
CloseHandle(hProcessSnapshot);
return ( TRUE );
}

int main()
{
MessageBox(NULL,_TEXT("Start simurator and hit return key!!"),_TEXT("Simulator Injector"),MB_OK);
GetProcessList();
return 0;
}

==================================分割线==================================
假如懂一点英文和编程的话不难发现其实就是枚举进程而已,囧rz,这就是长门大神写的外挂么~~PS:据说这一集的脚本是——贺东招二 -_-# 好像记得在FMP的动画里也见过代码的样子,看上去像是Basic之类的东西,具体在哪里忘掉了……运行起来大概是酱紫: