Java Web_几种加密算法

Java Web_几种加密算法

 

 

一.几种加密算法

1:消息摘要:(数字指纹):既对一个任意长度的一个数据块进行计算,产生一个唯一指纹。MD5/SHA1

发送给其他人你的信息和摘要,其他人用相同的加密方法得到摘要,最后进行比较摘要是否相同。

MD5的全称是Message-Digest Algorithm 5(信息-摘要算法)。过程不可逆, 是单向加密。SHA加密,与MD5相似的用法,只是两者的算法不同。

2:单匙密码体制:DES:比较简便高效,密钥简短,加解密速度快,破译极其困难,但其安全性依赖于密匙的安全性。

DESData Encryption Standard)是发明最早的最广泛使用的分组对称加密算法。DES算法的入口参数有三个:KeyDataMode

其中Key8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;ModeDES的工作方式,有两种:加密或解密

 

3:数字签名:就是信息发送者用其私钥对从所传报文中提取出的特征数据(或称数字指纹)进行RSA算法操作,以保证发信人无法抵赖曾发过该信息(即不可抵赖性),

同时也确保信息报文在经签名后末被篡改(即完整性)。当信息接收者收到报文后,就可以用发送者的公钥对数字签名进行验证。

代表:DSA

4:非对称密匙密码体制(公匙体系):加密密匙不同于解密密匙,加密密匙公之于众,谁都可以使用,解密密匙只有解密人自己知道。代表:RSA

 

下面是对上面几个例子进行的简单实现:

二.代码解析

1. MD5/SHA

package com.text;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

 

publicclass  MD5{

 

    /**

    * 进行MD5/SHA加密

    *

    * @param info

    *            要加密的信息

    * @return String 加密后的字符串

    */

    private String encryptToMD5(String str) {

       byte[] byteArray =null;

       try {

           //得到一个MD5的消息摘要

           MessageDigest messageDigest = MessageDigest.getInstance("MD5");

           // 得到一个SHA-1的消息摘要

           // messageDigest = MessageDigest.getInstance("SHA-1");

//         messageDigest.reset();

           //添加要进行计算摘要的信息

           messageDigest.update(str.getBytes());

//         messageDigest.update(str.getBytes("UTF-8"));

           //得到该摘要

           byteArray = messageDigest.digest();

       } catch (NoSuchAlgorithmException e) {

           e.printStackTrace();

       }

       // 将摘要转为字符串返回

       return byte2hex(byteArray);

    }

    /**

    * 将二进制转化为16进制字符串

    *

    * @param b

    *            二进制字节数组

    * @return String

    */

    public String byte2hex(byte[] b){

       String hs="";

       String stmp="";

       for (int i = 0; i < b.length; i++) {

           stmp = (java.lang.Integer.toHexString(b[i] & 0XFF));

           if (stmp.length() == 1){

              hs = hs + "0" + stmp;

           } else {

           hs = hs + stmp;

           }

       }

       return hs.toUpperCase();

    }

 

    publicstaticvoid main(String[] args) {

       String msg = "Hello";

       System.out.println("明文是:" + msg);

       // 执行MD5加密"Hello"

       System.out.println("MD5加密了是:" + new MD5().encryptToMD5(msg));

       //8B1A9953C4611296A827ABF8C47804D7

    }

}

 

2. DES

package com.text;

 

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

 

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.SecretKey;

 

publicclass DES {

 

    /**

     * 创建密匙

     *

     * @param algorithm

     *            加密算法,可用 DES,DESede,Blowfish

     * @return SecretKey 秘密(对称)密钥

     */

    public SecretKey createSecretKey(String algorithm) {

       // 声明KeyGenerator对象

       KeyGenerator keygen;

       // 声明密钥对象

       SecretKey deskey = null;

       try {

           // 返回生成指定算法的秘密密钥的 KeyGenerator 对象

           keygen = KeyGenerator.getInstance(algorithm);

           // 生成一个密钥

           deskey = keygen.generateKey();

       } catch (NoSuchAlgorithmException e) {

           e.printStackTrace();

       }

       // 返回密匙

       return deskey;

    }

 

    /**

     * 根据密匙进行DES加密

     *

     * @param key

     *            密匙

     * @param info

     *            要加密的信息

     * @return String 加密后的信息

     */

    public String encryptToDES(SecretKey key, String info) {

       // 定义加密算法,可用 DES,DESede,Blowfish

       String Algorithm = "DES";

       // 加密随机数生成器 (RNG),(可以不写)

       SecureRandom sr = new SecureRandom();

       // 定义要生成的密文

       byte[] cipherByte = null;

       try {

           // 得到加密/解密器

           Cipher c1 = Cipher.getInstance(Algorithm);

           // 用指定的密钥和模式初始化Cipher对象

           // 参数:(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)

           c1.init(Cipher.ENCRYPT_MODE, key, sr);

           // 对要加密的内容进行编码处理,

           cipherByte = c1.doFinal(info.getBytes());

       } catch (Exception e) {

           e.printStackTrace();

       }

       // 返回密文的十六进制形式

       return byte2hex(cipherByte);

    }

 

    /**

     * 根据密匙进行DES解密

     *

     * @param key

     *            密匙

     * @param sInfo

     *            要解密的密文

     * @return String 返回解密后信息

     */

    public String decryptByDES(SecretKey key, String sInfo) {

       // 定义加密算法,

       String Algorithm = "DES";

       // 加密随机数生成器 (RNG)

       SecureRandom sr = new SecureRandom();

       byte[] cipherByte = null;

       try {

           // 得到加密/解密器

           Cipher c1 = Cipher.getInstance(Algorithm);

           // 用指定的密钥和模式初始化Cipher对象

           c1.init(Cipher.DECRYPT_MODE, key, sr);

           // 对要解密的内容进行编码处理

           cipherByte = c1.doFinal(hex2byte(sInfo));

       } catch (Exception e) {

           e.printStackTrace();

       }

       // return byte2hex(cipherByte);

       returnnew String(cipherByte);

    }

 

    /**

     * 将二进制转化为16进制字符串

     *

     * @param b

     *            二进制字节数组

     * @return String

     */

    public String byte2hex(byte[] b) {

       String hs = "";

       String stmp = "";

       for (int n = 0; n < b.length; n++) {

           stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));

           if (stmp.length() == 1) {

              hs = hs + "0" + stmp;

           } else {

              hs = hs + stmp;

           }

       }

       return hs.toUpperCase();

    }

 

    /**

     * 十六进制字符串转化为2进制

     *

     * @param hex

     * @return

     */

    publicbyte[] hex2byte(String hex) {

       byte[] ret = newbyte[8];

       byte[] tmp = hex.getBytes();

       for (int i = 0; i < 8; i++) {

           ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);

       }

       return ret;

    }

 避免输入较长数据而引发的错误,将上述十六进制字符串转化为2进制方法做以下修改:

/**
* 当输入一定长度的数据时,会发现输入数据的长度和加密后数据的长度之间是有一定规律的。
* 输入0-7位数据,加密后为16位;输入8-15位加密后为32位;输入16-23位加密后为48位。。。
* 将输入数据按8的倍数的长度范围来划分。
* 加密后数据的长度会根据输入数据的长度而确定,为16的倍数。
* 得到的十六进制byte数组(byte[] ret)的大小,根据输入数据的长度/加密后数据的长度而变化,为8的倍数。
*/
/**
* 十六进制字符串转化为2进制
*
*
@param hex
*
@return
*/
public byte[] hex2byte(String hex) {
//根据输入数据的长度决定加密后数据的长度。
/**
* input:[8(x-1),8x)---output:16x---param:8x
* eg:
* input:0-7位---output:16位---param:8
* input:8-15位---output:32位---param:16
* input:16-23位---output:48位---param:24
*/
int x=hex.length()/16;
byte[] ret = new byte[8*x];
byte[] tmp = hex.getBytes();
for (int i = 0; i < 8*x; i++) {
ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
}
return ret;
}


 

    /**

     * 将两个ASCII字符合成一个字节;如:"EF"--> 0xEF

     *

     * @param src0

     *            byte

     * @param src1

     *            byte

     * @return byte

     */

    publicstaticbyte uniteBytes(byte src0, byte src1) {

       byte _b0 = Byte.decode("0x" + new String(newbyte[] { src0 }))

              .byteValue();

       _b0 = (byte) (_b0 << 4);

       byte _b1 = Byte.decode("0x" + new String(newbyte[] { src1 }))

              .byteValue();

       byte ret = (byte) (_b0 ^ _b1);

       return ret;

    }

 

    publicstaticvoid main(String[] args) {

       DES des = new DES();

       // 生成一个DES算法的密匙

       SecretKey key = des.createSecretKey("DES");

       // 用密匙加密信息"Hello"

       String str1 = des.encryptToDES(key, "Hello");

       System.out.println("使用des加密信息Hello:" + str1);

       // 02E7AADB2E1DBCF6

       // 使用这个密匙解密

       String str2 = des.decryptByDES(key, str1);

       System.out.println("解密后为:" + str2);

    }

}

 

3. DSA

package com.text;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.security.*;

 

publicclass DSA {

 

/**

* 创建密匙组,并将公匙,私匙放入到指定文件中

*

* 默认放入mykeys.bat文件中

*/

publicvoid createPairKey() {

try {

// 根据特定的算法一个密钥对生成器

KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA");

// 加密随机数生成器 (RNG)

SecureRandom random = new SecureRandom();

// 重新设置此随机对象的种子

random.setSeed(1000);

// 使用给定的随机源(和默认的参数集合)初始化确定密钥大小的密钥对生成器

keygen.initialize(512, random);// keygen.initialize(512);

// 生成密钥组

KeyPair keys = keygen.generateKeyPair();

// 得到公匙

PublicKey pubkey = keys.getPublic();

// 得到私匙

PrivateKey prikey = keys.getPrivate();

// 将公匙私匙写入到文件当中

doObjToFile("mykeys.bat", new Object[] { prikey, pubkey });

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

}

/**

* 利用私匙对信息进行签名把签名后的信息放入到指定的文件中

*

* @param info

*            要签名的信息

* @param signfile

*            存入的文件

*/

publicvoid signToInfo(String info, String signfile) {

// 从文件当中读取私匙

PrivateKey myprikey = (PrivateKey) getObjFromFile("mykeys.bat", 1);

// 从文件中读取公匙

PublicKey mypubkey = (PublicKey) getObjFromFile("mykeys.bat", 2);

try {

// Signature 对象可用来生成和验证数字签名

Signature signet = Signature.getInstance("DSA");

// 初始化签署签名的私钥

signet.initSign(myprikey);

// 更新要由字节签名或验证的数据

signet.update(info.getBytes());

// 签署或验证所有更新字节的签名,返回签名

byte[] signed = signet.sign();

// 将数字签名,公匙,信息放入文件中

doObjToFile(signfile, new Object[] { signed, mypubkey, info });

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 读取数字签名文件根据公匙,签名,信息验证信息的合法性

*

* @return true 验证成功 false 验证失败

*/

publicboolean validateSign(String signfile) {

// 读取公匙

PublicKey mypubkey = (PublicKey) getObjFromFile(signfile, 2);

// 读取签名

byte[] signed = (byte[]) getObjFromFile(signfile, 1);

// 读取信息

String info = (String) getObjFromFile(signfile, 3);

try {

// 初始一个Signature对象,并用公钥和签名进行验证

Signature signetcheck = Signature.getInstance("DSA");

// 初始化验证签名的公钥

signetcheck.initVerify(mypubkey);

// 使用指定的 byte 数组更新要签名或验证的数据

signetcheck.update(info.getBytes());

System.out.println(info);

// 验证传入的签名

return signetcheck.verify(signed);

} catch (Exception e) {

e.printStackTrace();

returnfalse;

}

}

/**

* 将指定的对象写入指定的文件

*

* @param file

*            指定写入的文件

* @param objs

*            要写入的对象

*/

publicvoid doObjToFile(String file, Object[] objs) {

ObjectOutputStream oos = null;

try {

FileOutputStream fos = new FileOutputStream(file);

oos = new ObjectOutputStream(fos);

for (int i = 0; i < objs.length; i++) {

oos.writeObject(objs[i]);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

oos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 返回在文件中指定位置的对象

*

* @param file

*            指定的文件

* @param i

*            1开始

* @return

*/

public Object getObjFromFile(String file, int i) {

ObjectInputStream ois = null;

Object obj = null;

try {

FileInputStream fis = new FileInputStream(file);

ois = new ObjectInputStream(fis);

for (int j = 0; j < i; j++) {

obj = ois.readObject();

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

ois.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return obj;

}

 

publicstaticvoid main(String[] args) {

    DSA dsa = new DSA();

// 创建公匙和私匙

    dsa.createPairKey();

// Hello使用私匙进行签名

    dsa.signToInfo("Hello", "mysign.bat");

// 利用公匙对签名进行验证。

if (dsa.validateSign("mysign.bat")) {

System.out.println("Success!");

} else {

System.out.println("Fail!");

}

}

}

 

/**

用到的重要的类

javax.crypto.KeyGenerator

public final SecretKey generateKey()生成一个密钥

public static final KeyGenerator getInstance(String algorithm) 返回生成指定算法的秘密密钥的KeyGenerator对象。

javax.crypto 接口 SecretKey

javax.crypto.Cipher 此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心

public final void init(int opmode,Key key)

public final byte[] A(byte[] input) 按单部分操作加密或解密数据,或者结束一个多部分操作

java.security.KeyPairGenerator

static KeyPairGenerator getInstance(String algorithm)

回生成指定算法的 public/private 密钥对的 KeyPairGenerator 对象。

java.security.Signature

使用 Signature 对象签名数据或验证签名包括以下三个阶段:

1:初始化,使用

初始化验证签名的公钥(请参见 initVerify),或使用

初始化签署签名的私钥(也可以选择安全随机数生成器initSign(PrivateKey)initSign(PrivateKey, SecureRandom))。

2:更新

根据初始化类型,这可更新要签名或验证的字节。请参见 update 方法。

3:签署或验证所有更新字节的签名。请参见 sign 方法和 verify 方法。

*/

 

posted @ 2011-10-17 10:55  大头鱼  阅读(1618)  评论(2编辑  收藏  举报