分享

java 的加密算法工具

 hehffyy 2015-12-19

一 、MD5算法

              散列算法之一(又译哈希算法、摘要算法等),主流编程语言普遍已有MD5的实现。将数据(如一段文字)运算变为另一固定长度值,是散列算法的基础原理。(以上是百度百科介绍)。扯那么多也是空的,反正就感觉读大学的时候觉得这种加密是最常见的,所以实现起来也比较简单,但是md5我们还是需要去了解下:

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。下面来看代码的实现:

MD5Util.java

package com.zy.suanfa;
import java.security.MessageDigest;
public class MD5Util {
    /*** 
     * MD5加密 生成32位md5码
     * @param 待加密字符串
     * @return 返回32位md5码
     */
    public static String md5Encode(String inStr) throws Exception {
        MessageDigest md5 = null;//消息摘要算法类
        try {
            md5 = MessageDigest.getInstance("MD5");//可以传入一个参数获得实例(参数可以为MD2,MD5,SHA(JDK自带的),然后也可以用bcprov里面可以带的MD4等)
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
            return "";
        }
        byte[] byteArray = inStr.getBytes("UTF-8");
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;//转化成为16进制的字节
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();//返回的hash
    }
    /**
     * 测试主函数
     * @param args
     * @throws Exception
     */
    public static void main(String args[]) throws Exception {
        String str = new String("000000");
        System.out.println("原始:" + str);
        System.out.println("MD5后:" + md5Encode(str));
    }
}

二、SHA算法

        SHA是一种数据加密算法,该算法经过加密专家多年来的发展和改进已日益完善,现在已成为公认的最安全的散列算法之一,并被广泛使用。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说是对明文的一种“指纹”或是“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。

下面直接代码:

package com.zy.suanfa;
import java.security.MessageDigest;
public class SHAUtil {
/***
* SHA加密 生成40位SHA码
* @param 待加密字符串
* @return 返回40位SHA码
*/
public static String shaEncode(String inStr) throws Exception {
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA");
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return "";
}
byte[] byteArray = inStr.getBytes("UTF-8");
byte[] md5Bytes = sha.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
/**
* 测试主函数

* @param args
* @throws Exception
*/
public static void main(String args[]) throws Exception {
String str = new String("000000");
System.out.println("原始:" + str);
System.out.println("SHA后:" + shaEncode(str));
}
}

看代码和MD5实现的比较相似,就是获得是SHA的 码这里不同,然后总结就是:
  采用SHAA加密 因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
  1)对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2)对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
 3)速度:在相同的硬件上,SHA-1的运行速度比MD5慢。
三、BASE64 算法

        Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息,例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

 或许我们对这些理论的东西不会很感兴趣,但是我们对它加密的优点还是有必要知道,不然面试的时候就无话可答了,我们做图片请求上传时不得不面对的尴尬就是后台或许不会,让你传一个字节数组作为参数,你是不是感觉蛋是微凉微凉的,(因为我就碰到过后台没有做过图片处理的,然后我不懂php我就问他有没有base64或者直接传图片文件)然后加密用BASE64确实很好。

直接代码:

package com.zy.suanfa;
import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
/**
 * BASE64加密解密
 */
public class BASE64 {
/**
* BASE64解密

* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密

* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}
public static void main(String[] args) {
String data;
try {
data = BASE64.encryptBASE64("http://www.baidu.com/img/girl.png".getBytes());
System.out.println("加密前:" + data);
byte[] byteArray = BASE64.decryptBASE64(data);
System.out.println("解密后:" + new String(byteArray));
} catch (Exception e) {
e.printStackTrace();
}
}
}

是不是使用起来非常简单呢。

四、DES(属于hmac)算法

DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,首先,DES把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,并进行前后置换(输入的第58位换到第一位,第50位换到第2位,依此类推,最后一位是原来的第7位),最终由L0输出左32位,R0输出右32位,根据这个法则经过16次迭代运算后,得到L16、R16,将此作为输入,进行与初始置换相反的逆置换,即得到密文输出。
     DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密,如果Mode为加密,则用Key去把数据Data进行加密,生成Data的密码形式作为DES的输出结果;如Mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式作为DES的输出结果。在使用DES时,双方预先约定使用的”密码”即Key,然后用Key去加密数据;接收方得到密文后使用同样的Key解密得到原数据,这样便实现了安全性较高的数据传输。

接下来代码:

package com.zy.suanfa;

import java.io.FileInputStream;
import java.io.FileOutputStream;    
import java.io.InputStream;    
import java.io.OutputStream;    
import java.security.Key;    
import java.security.SecureRandom;    
     
import javax.crypto.Cipher;    
import javax.crypto.CipherInputStream;    
import javax.crypto.CipherOutputStream;    
import javax.crypto.KeyGenerator;      

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
     
public class DESUtil {    
     
    Key key ;    
     
    public DESUtil() {    
     
    }    
     
    public DESUtil(String str) {    
       setKey(str); // 生成密匙    
    }    
    public Key getKey() {    
       return key ;    
    }    
    public void setKey(Key key) {    
       this . key = key;    
    }    
     
    /**  
      * 根据参数生成 KEY  
      */    
    public void setKey(String strKey) {    
       try {    
           KeyGenerator _generator = KeyGenerator.getInstance ( "DES" );    
           _generator.init( new SecureRandom(strKey.getBytes()));    
           this . key = _generator.generateKey();    
           _generator = null ;    
       } catch (Exception e) {    
           throw new RuntimeException(    
                  "Error initializing SqlMap class. Cause: " + e);    
       }    
    }    
     
    /**  
      * 加密 String 明文输入 ,String 密文输出  
      */    
    public String encryptStr(String strMing) {    
       byte [] byteMi = null ;    
       byte [] byteMing = null ;    
       String strMi = "" ;    
       BASE64Encoder base64en = new BASE64Encoder();    
       try {    
           byteMing = strMing.getBytes( "UTF8" );    
           byteMi = this .encryptByte(byteMing);    
           strMi = base64en.encode(byteMi);    
       } catch (Exception e) {    
           throw new RuntimeException(    
                  "Error initializing SqlMap class. Cause: " + e);    
       } finally {    
           base64en = null ;    
           byteMing = null ;    
           byteMi = null ;    
       }    
       return strMi;    
    }    
     
    /**  
      * 解密 以 String 密文输入 ,String 明文输出  
      *  
      * @param strMi  
      * @return  
      */    
    public String decryptStr(String strMi) {    
       BASE64Decoder base64De = new BASE64Decoder();    
       byte [] byteMing = null ;    
       byte [] byteMi = null ;    
       String strMing = "" ;    
       try {    
           byteMi = base64De.decodeBuffer(strMi);    
           byteMing = this .decryptByte(byteMi);    
           strMing = new String(byteMing, "UTF8" );    
       } catch (Exception e) {    
           throw new RuntimeException(    
                  "Error initializing SqlMap class. Cause: " + e);    
       } finally {    
           base64De = null ;    
           byteMing = null ;    
           byteMi = null ;    
       }    
       return strMing;    
    }    
     
    /**  
      * 加密以 byte[] 明文输入 ,byte[] 密文输出  
      *  
      * @param byteS  
      * @return  
      */    
    private byte [] encryptByte( byte [] byteS) {    
       byte [] byteFina = null ;    
       Cipher cipher;    
       try {    
           cipher = Cipher.getInstance ( "DES" );    
           cipher.init(Cipher. ENCRYPT_MODE , key );    
           byteFina = cipher.doFinal(byteS);    
       } catch (Exception e) {    
           throw new RuntimeException(    
                  "Error initializing SqlMap class. Cause: " + e);    
       } finally {    
           cipher = null ;    
       }    
       return byteFina;    
    }    
     
    /**  
      * 解密以 byte[] 密文输入 , 以 byte[] 明文输出  
      *  
      * @param byteD  
      * @return  
      */    
    private byte [] decryptByte( byte [] byteD) {    
       Cipher cipher;    
       byte [] byteFina = null ;    
       try {    
           cipher = Cipher.getInstance ( "DES" );    
           cipher.init(Cipher. DECRYPT_MODE , key );    
           byteFina = cipher.doFinal(byteD);    
       } catch (Exception e) {    
           throw new RuntimeException(    
                  "Error initializing SqlMap class. Cause: " + e);    
       } finally {    
           cipher = null ;    
       }    
       return byteFina;    
    }    
     
    /**  
      * 文件 file 进行加密并保存目标文件 destFile 中  
      *  
      * @param file  
      *             要加密的文件 如 c:/test/srcFile.txt  
      * @param destFile  
      *             加密后存放的文件名 如 c:/ 加密后文件 .txt  
      */    
    public void encryptFile(String file, String destFile) throws Exception {    
       Cipher cipher = Cipher.getInstance ( "DES" );    
       // cipher.init(Cipher.ENCRYPT_MODE, getKey());    
       cipher.init(Cipher. ENCRYPT_MODE , this . key );    
       InputStream is = new FileInputStream(file);    
       OutputStream out = new FileOutputStream(destFile);    
       CipherInputStream cis = new CipherInputStream(is, cipher);    
       byte [] buffer = new byte [1024];    
       int r;    
       while ((r = cis.read(buffer)) > 0) {    
           out.write(buffer, 0, r);    
       }    
       cis.close();    
       is.close();    
       out.close();    
    }    
     
    /**  
      * 文件采用 DES 算法解密文件  
      *  
      * @param file  
      *             已加密的文件 如 c:/ 加密后文件 .txt *  
      * @param destFile  
      *             解密后存放的文件名 如 c:/ test/ 解密后文件 .txt  
      */    
    public void decryptFile(String file, String dest) throws Exception {    
       Cipher cipher = Cipher.getInstance ( "DES" );    
       cipher.init(Cipher. DECRYPT_MODE , this . key );    
       InputStream is = new FileInputStream(file);    
       OutputStream out = new FileOutputStream(dest);    
       CipherOutputStream cos = new CipherOutputStream(out, cipher);    
       byte [] buffer = new byte [1024];    
       int r;    
       while ((r = is.read(buffer)) >= 0) {    
           cos.write(buffer, 0, r);    
       }    
       cos.close();    
       out.close();    
       is.close();    
    }    
     
    public static void main(String[] args) throws Exception {    
       DESUtil des = new DESUtil( "" );    
       // DES 加密文件    
       // des.encryptFile("G:/test.doc", "G:/ 加密 test.doc");    
       // DES 解密文件    
       // des.decryptFile("G:/ 加密 test.doc", "G:/ 解密 test.doc");    
       String str1 = " 要加密的字符串 test" ;    
       // DES 加密字符串    
       String str2 = des.encryptStr(str1);    
       // DES 解密字符串    
       String deStr = des.decryptStr(str2);    
       System. out .println( " 加密前: " + str1);    
       System. out .println( " 加密后: " + str2);    
       System. out .println( " 解密后: " + deStr);    
    }    

在这里我们使用了KeyGenerator类,所以我们用到了bcprov-jdk15-143.jar来生成key,然后也用到了BASE64Decoder需要用到sun.misc.BASE64Decoder.jar,你要用的话记得自己去下额。

五、3DES  算法


3DES又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法,并于1981年被ANSI组织规范为ANSI X.3.92。DES使用56位密钥和密码块的方法,而在密码块的方法中,文本被分成64位大小的文本块然后再进行加密。比起最初的DES,3DES更为安全。

package com.zy.suanfa;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import Decoder.BASE64Encoder;
public class ThreeDESUtil {
    // 算法名称 
    public static final String KEY_ALGORITHM = "desede";
    // 算法名称/加密模式/填充方式 
    public static final String CIPHER_ALGORITHM = "desede/CBC/NoPadding";
    /** 
     * CBC加密 
     * @param key 密钥 
     * @param keyiv IV 
     * @param data 明文 
     * @return Base64编码的密文 
     * @throws Exception 
     */
    public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {
        Security.addProvider(new BouncyCastleProvider()); 
        Key deskey = keyGenerator(new String(key));
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);
        for (int k = 0; k < bOut.length; k++) {
            System.out.print(bOut[k] + " ");
        }
        System.out.println("");
        return bOut;
    }


    /** 
     *   
     * 生成密钥key对象 
     * @param KeyStr 密钥字符串 
     * @return 密钥对象 
     * @throws InvalidKeyException   
     * @throws NoSuchAlgorithmException   
     * @throws InvalidKeySpecException   
     * @throws Exception 
     */
    private static Key keyGenerator(String keyStr) throws Exception {
        byte input[] = HexString2Bytes(keyStr);
        DESedeKeySpec KeySpec = new DESedeKeySpec(input);
        SecretKeyFactory KeyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        return ((Key) (KeyFactory.generateSecret(((java.security.spec.KeySpec) (KeySpec)))));
    }


    private static int parse(char c) {
        if (c >= 'a') return (c - 'a' + 10) & 0x0f;
        if (c >= 'A') return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }
 
    // 从十六进制字符串到字节数组转换 
    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }


    /** 
     * CBC解密 
     * @param key 密钥 
     * @param keyiv IV 
     * @param data Base64编码的密文 
     * @return 明文 
     * @throws Exception 
     */
    public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {
        Key deskey = keyGenerator(new String(key));
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);
        return bOut;
    }
    public static void main(String[] args) throws Exception {
        byte[] key = "6C4E60E5C0F838C0F7".getBytes();
        byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8,0 };
        byte[] data = "amigoxie".getBytes("UTF-8");
        System.out.println("data.length=" + data.length);
        System.out.println("CBC加密解密");
        byte[] str5 = des3EncodeCBC(key, keyiv, data);
        System.out.println(new BASE64Encoder().encode(str5));
        byte[] str6 = des3DecodeCBC(key, keyiv, str5);
        System.out.println(new String(str6, "UTF-8"));
    }
}

六、AES算法

AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据 的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。Figure 1 显示了 AES 用192位密钥对一个16位字节数据块进行加密和解密的情形。

直接代码:

package com.zy.suanfa;


import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import java.security.SecureRandom;  
  
import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.KeyGenerator;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  
import javax.crypto.spec.SecretKeySpec;  
  
public class AESUtils  
{  
    /** 
     * 加密 
     *  
     * @param content 需要加密的内容 
     * @param password  加密密码 
     * @return 
     */  
    public static byte[] encrypt(String content, String password)  
    {  
        try  
        {  
            KeyGenerator kgen = KeyGenerator.getInstance("AES");  
            kgen.init(128, new SecureRandom(password.getBytes()));  
            SecretKey secretKey = kgen.generateKey();  
            byte[] enCodeFormat = secretKey.getEncoded();  
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
            byte[] byteContent = content.getBytes("utf-8");  
            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化  
            byte[] result = cipher.doFinal(byteContent);  
            return result; // 加密  
        }  
        catch (NoSuchAlgorithmException e)  
        {  
            e.printStackTrace();  
        }  
        catch (NoSuchPaddingException e)  
        {  
            e.printStackTrace();  
        }  
        catch (InvalidKeyException e)  
        {  
            e.printStackTrace();  
        }  
        catch (UnsupportedEncodingException e)  
        {  
            e.printStackTrace();  
        }  
        catch (IllegalBlockSizeException e)  
        {  
            e.printStackTrace();  
        }  
        catch (BadPaddingException e)  
        {  
            e.printStackTrace();  
        }  
        return null;  
    }  
  
    /**解密 
     * @param content  待解密内容 
     * @param password 解密密钥 
     * @return 
     */  
    public static byte[] decrypt(byte[] content, String password)  
    {  
        try  
        {  
            KeyGenerator kgen = KeyGenerator.getInstance("AES");  
            kgen.init(128, new SecureRandom(password.getBytes()));  
            SecretKey secretKey = kgen.generateKey();  
            byte[] enCodeFormat = secretKey.getEncoded();  
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化  
            byte[] result = cipher.doFinal(content);  
            return result; // 加密  
        }  
        catch (NoSuchAlgorithmException e)  
        {  
            e.printStackTrace();  
        }  
        catch (NoSuchPaddingException e)  
        {  
            e.printStackTrace();  
        }  
        catch (InvalidKeyException e)  
        {  
            e.printStackTrace();  
        }  
        catch (IllegalBlockSizeException e)  
        {  
            e.printStackTrace();  
        }  
        catch (BadPaddingException e)  
        {  
            e.printStackTrace();  
        }  
        return null;  
    }  
  
    /**将二进制转换成16进制 
     * @param buf 
     * @return 
     */  
    public static String parseByte2HexStr(byte buf[])  
    {  
        StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < buf.length; i++)  
        {  
            String hex = Integer.toHexString(buf[i] & 0xFF);  
            if (hex.length() == 1)  
            {  
                hex = '0' + hex;  
            }  
            sb.append(hex.toUpperCase());  
        }  
        return sb.toString();  
    }  
  
    /**将16进制转换为二进制 
     * @param hexStr 
     * @return 
     */  
    public static byte[] parseHexStr2Byte(String hexStr)  
    {  
        if (hexStr.length() < 1)  
            return null;  
        byte[] result = new byte[hexStr.length() / 2];  
        for (int i = 0; i < hexStr.length() / 2; i++)  
        {  
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);  
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);  
            result[i] = (byte)(high * 16 + low);  
        }  
        return result;  
    }  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args)  
    {  
        String content = "test3444";  
        String password = "11";  
        // 加密  
        System.out.println("加密前:" + content);  
        byte[] encryptResult = encrypt(content, password);  
        String encryptResultStr = parseByte2HexStr(encryptResult);  
        System.out.println("加密后:" + encryptResultStr);  
        // 解密  
        byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);  
        byte[] decryptResult = decrypt(decryptFrom, password);  
        System.out.println("解密后:" + new String(decryptResult));  
    }  
  
}  
七 、RSA 算法
 RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。   在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。






下面直接代码:

package com.zy.suanfa;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import it.sauronsoftware.base64.Base64;
/**
 * <p>
 * BASE64编码解码工具包
 * </p>
 * <p>
 * 依赖javabase64-1.3.1.jar(自己去下)
 * </p>
 */
public class Base64Utils {
    /**
     * 文件读取缓冲区大小
     */
    private static final int CACHE_SIZE = 1024;
    
    /**
     * <p>
     * BASE64字符串解码为二进制数据
     * </p>
     * 
     * @param base64
     * @return
     * @throws Exception
     */
    public static byte[] decode(String base64) throws Exception {
        return Base64.decode(base64.getBytes());
    }
    
    /**
     * <p>
     * 二进制数据编码为BASE64字符串
     * </p>
     * 
     * @param bytes
     * @return
     * @throws Exception
     */
    public static String encode(byte[] bytes) throws Exception {
        return new String(Base64.encode(bytes));
    }
    
    /**
     * <p>
     * 将文件编码为BASE64字符串
     * </p>
     * <p>
     * 大文件慎用,可能会导致内存溢出
     * </p>
     * 
     * @param filePath 文件绝对路径
     * @return
     * @throws Exception
     */
    public static String encodeFile(String filePath) throws Exception {
        byte[] bytes = fileToByte(filePath);
        return encode(bytes);
    }
    
    /**
     * <p>
     * BASE64字符串转回文件
     * </p>
     * 
     * @param filePath 文件绝对路径
     * @param base64 编码字符串
     * @throws Exception
     */
    public static void decodeToFile(String filePath, String base64) throws Exception {
        byte[] bytes = decode(base64);
        byteArrayToFile(bytes, filePath);
    }
    
    /**
     * <p>
     * 文件转换为二进制数组
     * </p>
     * 
     * @param filePath 文件路径
     * @return
     * @throws Exception
     */
    public static byte[] fileToByte(String filePath) throws Exception {
        byte[] data = new byte[0];
        File file = new File(filePath);
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
            data = out.toByteArray();
         }
        return data;
    }
    
    /**
     * <p>
     * 二进制数据写文件
     * </p>
     * 
     * @param bytes 二进制数据
     * @param filePath 文件生成目录
     */
    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
        InputStream in = new ByteArrayInputStream(bytes);   
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        destFile.createNewFile();
        OutputStream out = new FileOutputStream(destFile);
        byte[] cache = new byte[CACHE_SIZE];
        int nRead = 0;
        while ((nRead = in.read(cache)) != -1) {   
            out.write(cache, 0, nRead);
            out.flush();
        }
        out.close();
        in.close();
    }  
}

下面是rsa加密算法代码:

 package com.zy.suanfa;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;


import javax.crypto.Cipher;


/**
 * <p>
 * RSA公钥/私钥/签名工具包
 * </p>
 * 
 * <p>
 * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
 * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
 * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
 * </p>
 */
public class RSAUtils {
/**
* 加密算法RSA
*/
private static final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
private static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 获取公钥的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
// 获取私钥的key
private static final String PRIVATE_KEY = "RSAPrivateKey";
// RSA最大加密明文大小
private static final int MAX_ENCRYPT_BLOCK = 117;
// RSA最大解密密文大小
private static final int MAX_DECRYPT_BLOCK = 128;
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator
.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* <p>
* 用私钥对信息生成数字签名
* </p>

* @param data
*            已加密数据
* @param privateKey
*            私钥(BASE64编码)

* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(data);
return Base64Utils.encode(signature.sign());
}
/**
* <p>
* 校验数字签名
* </p>

* @param data
*            已加密数据
* @param publicKey
*            公钥(BASE64编码)
* @param sign
*            数字签名

* @return
* @throws Exception

*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(data);
return signature.verify(Base64Utils.decode(sign));
}
/**
* <P>
* 私钥解密
* </p>

* @param encryptedData
*            已加密数据
* @param privateKey
*            私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData,
String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥解密
* </p>

* @param encryptedData
*            已加密数据
* @param publicKey
*            公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData,
String publicKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥加密
* </p>

* @param data
*            源数据
* @param publicKey
*            公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();

return encryptedData;
}
/**
* <p>
* 私钥加密
* </p>

* @param data
*            源数据
* @param privateKey
*            私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}


/**
* <p>
* 获取私钥
* </p>

* @param keyMap
*            密钥对
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64Utils.encode(key.getEncoded());
}
/**
* <p>
* 获取公钥
* </p>

* @param keyMap
*            密钥对
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64Utils.encode(key.getEncoded());
}
static String publicKey;  
 static String privateKey;  


 static {  
     try {  
         Map<String, Object> keyMap = RSAUtils.genKeyPair();  
         publicKey = RSAUtils.getPublicKey(keyMap);  
         privateKey = RSAUtils.getPrivateKey(keyMap);  
         System.err.println("公钥: /n/r" + publicKey);  
         System.err.println("私钥: /n/r" + privateKey);  
     } catch (Exception e) {  
         e.printStackTrace();  
     }  
 }  
 static void test() throws Exception {  
     System.err.println("公钥加密——私钥解密");  
     String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?";  
     System.out.println("/r加密前文字:/r/n" + source);  
     byte[] data = source.getBytes("UTF-8");  
     byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);  
     System.out.println("加密后文字:/r/n" + new String(encodedData));  
     byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);  
     String target = new String(decodedData);  
     System.out.println("解密后文字: /r/n" + target);  
 }  
 static void testSign() throws Exception {  
     System.err.println("私钥加密——公钥解密");  
     String source = "这是一行测试RSA数字签名的无意义文字";  
     System.out.println("原文字:/r/n" + source);  
     byte[] data = source.getBytes();  
     byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);  
     System.out.println("加密后:/r/n" + new String(encodedData));  
     byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);  
     String target = new String(decodedData);  
     System.out.println("解密后: /r/n" + target);  
     System.err.println("私钥签名——公钥验证签名");  
     String sign = RSAUtils.sign(encodedData, privateKey);  
     System.err.println("签名:/r" + sign);  
     boolean status = RSAUtils.verify(encodedData, publicKey, sign);  
     System.err.println("验证结果:/r" + status);  
 }  
 public static void main(String[] args) throws Exception {  
     test();  
     testSign();  
 }  
}  


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约