Java网络安全(一)

   消息摘要是数据信息的数字指纹。通过某种安全散列算法(如SHA1)对数据信息进行加密,就可以生成一个20字节(MD5算法好像是16字节)的序列,这个序列就称为消息摘要。

  从安全的角度考虑,我们总是希望任何不同的数据信息都生成不同的消息摘要,但这是不可能的,就拿SHA1算法来说,消息摘要是一个20字节的序列,也就是160位的长度,一共也只有2的160次方种可能。但这已经是一个巨大的数字了,我们可以相信两个不同的数据信息总是生成不同的消息摘要。

  所以,消息摘要具有以下两个特点:
  • 如果数据信息改变了,那么消息也将根着改变;
  • 伪造者无法创建与原数据信息具有相同消息摘要的假数据信息。

  消息摘要在网络中怎样起到安全的作用呢?假设你要发送下面一段数据信息给你的朋友:
晚上一起吃饭

  你可以先生成这段数据信息的消息摘要,上面的信息用SHA1算法加密后就复到下面的消息摘要:
fa00078d5bd477e6d397dd5f7f11166a

  之后你就可以把数据和摘要分别发送给你的朋友,然后你朋友也对数据信息进行加密,并把加密生成的摘要与你发送给他的进行对比,如果一样的,那么你朋友就可以确定数据信息在传输过程中没有被别人修改过。

  当然,仅仅是靠消息摘要,还无法解决所有的安全问题,比如数据和摘要在传输过程中同时被别人窃取了,你的朋友无法保正数据是不是真的来自于你,等等。后面的文章,我们接着介绍如果通过别的方法(比如公共密钥)来解决其它的安全问题。

  下面我们来看看在Java中如何对数据进行SHA1算法或MD5算法加密。其实Java语言已经实现了这两个算法,那就是java.security包下的MessageDigest类。具体的代码网上很容易搜到现在的代码:
public static String encodePassword(byte[] data, String algorithm)
        throws NoSuchAlgorithmException
{
    MessageDigest md = MessageDigest.getInstance(algorithm);

    md.reset();
    md.update(data);

    byte[] rlt = md.digest();

    StringBuffer buf = new StringBuffer();

    for (int i = 0; i < rlt.length; i++)
    {
        if ((rlt[i] & 0xff) < 0x10)
        {
            buf.append("0");
        }

        buf.append(Integer.toHexString(rlt[i] & 0xff));
    }

    return buf.toString();
}

  首先通过MessageDigest类的getInstance(String)方法获得该类的一个实例,具体的算法通过参数指定,比如"SHA-1"或"MD5",reset()方法用于复位摘要,update方法以字节数组的方式指定要加密的数据信息,接着调用digest()方法就生成了消息摘要。

  比较有意思的是后面for块里面的代码,我第一次看这段代码的时候也是花了点功夫才弄明白。

  后面这部分代码的作用是把byte[]格式的摘要转换成16进制的字符串。在Java中,byte占有8个位,转换成16进制的话,也就是2位,所以当这个byte小于16的话,要在前面加一个0。比如2进制数00001111,应该是转换成0f,但如果直接调用Integer.toHexString(15)的话,返回的结果是f而不是0f。这就是为什么上面if后面要做<0x10的判断了。

  另外一个比较难懂的地方就是rlt[i] & 0xff了。这里的与操作,目的很简单,就是把byte正确的转型为int,因为toHexString(int)方法只能接受int类型的参数。如果我们不做这个与操作,某些情况下转型过后的值就可能不是我们想要的值,比如-1的字节码(补码,Java以补码的形式表示数值)为
1111 1111

  转型为int后的字节码是
1111 1111 1111 1111 1111 1111 1111 1111

  而在这里我们需要的值是
0000 0000 0000 0000 0000 0000 1111 1111

  所以这里用rit[i]和0xff做了一个与运算,就能得到我们想要的值了。
  

你可能感兴趣的:(java,MD5,SHA1,消息摘要)