常用的加密算法

项目中用到了一些加密的算法,算法不太好,但是基于这些都是常用的加密算法,于是记录一下。不写具体原理了,在末尾加入一些链接,别人写的,写的很不错,把原理写的都特别清楚。

根据自己的使用特点来确定,由于非对称加密算法的运行速度比对称加密算法的速度慢很多,当我们需要加密大量的数据时,建议采用对称加密算法,提高加解密速度。

对称加密算法不能实现签名,因此签名只能非对称算法。

由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。

在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。

如果在选定了加密算法后,那采用多少位的密钥呢?一般来说,密钥越长,运行的速度就越慢,应该根据的我们实际需要的安全级别来选择,一般来说,RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。

基本的单向加密算法:  

  • BASE64 严格地说,属于编码格式,而非加密算法

    

/**
 * Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
 * 使用Apache的Commons-codec的base64来做加密解密
 *
 */
public class MyBase64 {
  public static void main(String[] args) throws UnsupportedEncodingException {
	String aa = "test";
	String encodeStr = Base64.encodeBase64String(new String(aa.getBytes(), "UTF-8").getBytes());
	//BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充。加密后: dGVzdA== 
	System.out.println("加密后: " + encodeStr);
	String decodeStr = new String(Base64.decodeBase64(encodeStr));
	if (aa.equals(decodeStr)) {
		System.out.println("加密解密成功");
	}
  }
}

 这里用到了apache的包,maven需要加入引用

<dependency>
		<groupId>commons-codec</groupId>
		<artifactId>commons-codec</artifactId>
		<version>1.9</version>
</dependency>

 

 

  • MD5(Message Digest algorithm 5,信息摘要算法)

 

public class MD5Test {
	public static void main(String[] args) throws UnsupportedEncodingException {
		MessageDigest md5 = null;
		
		try {
//			md5 = MessageDigest.getInstance("SHA");
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		String aa = new String("测试信息".getBytes(), "UTF-8");
		byte[] md5Bytes = null;
		try {
			md5Bytes = md5.digest(aa.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	    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));
        }
        System.out.println(hexValue.toString());
	}
}

 

 

  • SHA(Secure Hash Algorithm,安全散列算法)

写法和md5类似。

  • HMAC(Hash Message Authentication Code,散列消息鉴别码)

 

复杂的对称加密(DES、PBE)、非对称加密算法: 

  • DES(Data Encryption Standard,数据加密算法) 数据加密标准,速度较快,适用于加密大量数据的场合。

 

package com.xizheng.test.xizhneg;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DESUtil {
    //算法名称 
    public static final String KEY_ALGORITHM = "DES";
    //算法名称/加密模式/填充方式 
    //DES共有四种工作模式-->>ECB:电子密码本模式、CBC:加密分组链接模式、CFB:加密反馈模式、OFB:输出反馈模式
    public static final String CIPHER_ALGORITHM = "DES/ECB/NoPadding";

    /**
     *   
     * 生成密钥key对象
     * @param KeyStr 密钥字符串 
     * @return 密钥对象 
     * @throws InvalidKeyException   
     * @throws NoSuchAlgorithmException   
     * @throws InvalidKeySpecException   
     * @throws Exception 
     */
    private static SecretKey keyGenerator(String keyStr) throws Exception {
        byte input[] = HexString2Bytes(keyStr);
        DESKeySpec desKey = new DESKeySpec(input);
        //创建一个密匙工厂,然后用它把DESKeySpec转换成
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        return securekey;
    }

    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;
    }

    /** 
     * 加密数据
     * @param data 待加密数据
     * @param key 密钥
     * @return 加密后的数据 
     */
    public static String encrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        // 实例化Cipher对象,它用于完成实际的加密操作
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        SecureRandom random = new SecureRandom();
        // 初始化Cipher对象,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
        byte[] results = cipher.doFinal(data.getBytes());
        // 该部分是为了与加解密在线测试网站(http://tripledes.online-domain-tools.com/)的十六进制结果进行核对
        for (int i = 0; i < results.length; i++) {
            System.out.print(results[i] + " ");
        }
        System.out.println();
        // 执行加密操作。加密后的结果通常都会用Base64编码进行传输 
        return Base64.encodeBase64String(results);
    }

    /** 
     * 解密数据 
     * @param data 待解密数据 
     * @param key 密钥 
     * @return 解密后的数据 
     */
    public static String decrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //初始化Cipher对象,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        // 执行解密操作
        return new String(cipher.doFinal(Base64.decodeBase64(data)));
    }

    public static void main(String[] args) throws Exception {
        String source = "amigoxie";
        System.out.println("原文: " + source);
        String key = "A1B2C3D4E5F60708";
        String encryptData = encrypt(source, key);
        System.out.println("加密后: " + encryptData);
        String decryptData = decrypt(encryptData, key);
        System.out.println("解密后: " + decryptData);
    }
}

 TripleDES 是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。

 

 

package com.xizheng.test.xizhneg;
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;


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 = "6C4E60E55552386C759569836DC0F83869836DC0F838C0F7".getBytes();
        byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };
        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 sun.misc.BASE64Encoder().encode(str5));

        byte[] str6 = des3DecodeCBC(key, keyiv, str5);
        System.out.println(new String(str6, "UTF-8"));
    }
}

 

 

AES: 高级加密标准,是下一代的加密算法标准,速度快,安全级别高;

 

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class AesUtils {	
	// 初始向量	16byte
	private static final byte[] IV ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	public static final String AES_ECB_NOPadding = "AES/ECB/NOPadding";
	public static final String AES_ECB_PKCS5Padding = "AES/ECB/PKCS5Padding";
	public static final String AES_CBC_NOPadding = "AES/CBC/NOPadding";
	public static final String AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
	public static final String CHARSET_UTF8 = "UTF-8";
	/**
	 * AES/CBC/PKCS5Padding 
	 * @param hexData  十六进制
	 * @param hexKey 十六进制
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String encrypt(String transformation,String hexData,String hexKey) throws UnsupportedEncodingException {
		byte[] data = DataConvert.hex2byte(hexData);		
		byte[] k = DataConvert.hex2byte(hexKey);
		
		byte[] resp =  encrypt(transformation,data, k);
		return DataConvert.ByteArraytoHexString(resp);
	}
	/**
	 * AES/CBC/PKCS5Padding 
	 * @param srcData  明文字符串
	 * @param hexKey 十六进制
	 * @param charset	编码
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String encrypt(String transformation,String srcData,String hexKey,String charset) throws UnsupportedEncodingException {
		byte[] data = srcData.getBytes(charset==null?CHARSET_UTF8:charset);		
		byte[] k = DataConvert.hex2byte(hexKey);
		
		byte[] resp =  encrypt(transformation,data, k);
		return DataConvert.ByteArraytoHexString(resp);
	}
	/**
	 * AES/CBC/PKCS5Padding 
	 * @param src
	 * @param key
	 * @return
	 */
	public static byte[] encrypt(String transformation,byte[] src,byte[] key) {
		try {			
			Cipher cipher = Cipher.getInstance(transformation);
			if(AES_ECB_NOPadding.equals(transformation) || AES_ECB_PKCS5Padding.equals(transformation)){				
				cipher.init(Cipher.ENCRYPT_MODE, makeKey(key));
			}else{				
				cipher.init(Cipher.ENCRYPT_MODE, makeKey(key), makeIv());
			}
			return cipher.doFinal(src);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * AES/CBC/PKCS5Padding
	 * @param hexData 十六进制
	 * @param hexKey 十六进制
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String decrypt(String transformation,String hexData,String hexKey) throws UnsupportedEncodingException {
		byte[] data = DataConvert.hex2byte(hexData);
		byte[] k = DataConvert.hex2byte(hexKey);
		
		byte[] resp =  decrypt(transformation,data, k);
		
		return new String(resp,CHARSET_UTF8);
	}
	
	/**
	 * AES/CBC/PKCS5Padding
	 * @param eData
	 * @param key
	 * @return
	 */
	public static byte[] decrypt(String transformation,byte[] eData,byte[] key) {
		try {
			Cipher cipher = Cipher.getInstance(transformation);
			if(AES_ECB_NOPadding.equals(transformation) || AES_ECB_PKCS5Padding.equals(transformation)){	
				cipher.init(Cipher.DECRYPT_MODE, makeKey(key));
			}else{				
				cipher.init(Cipher.DECRYPT_MODE, makeKey(key), makeIv());
			}
			return cipher.doFinal(eData);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * MAC算法:采用AES-CBC算法,初始向量全0。如果最后一个数据块长度为16字节,则在此数据块后附加16字节’0x80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00’。如果最后一个数据块长度小于16字节,则该数据块的最后填补’0x80’,如果填补之后的数据块长度仍小于16字节,则在数据块后填充’0x00’,至数据块长度为16字节。MAC值为最后一块密文数据的前4字节
	 * @param hexData
	 * @param key
	 * @return
	 */
	public static byte[] encryptMac(byte[] hexData,byte[] key) {
		System.out.println("src:"+DataConvert.ByteArraytoHexString(hexData));
		byte[] mac = new byte[4];
		int maxLen = hexData.length + (16-(hexData.length%16));		
		ByteBuffer buff = ByteBuffer.allocate(maxLen);
		buff.put(hexData);
		buff.put((byte) 0x80);
		System.out.println("padding:"+DataConvert.ByteArraytoHexString(buff.array()));
		byte[] eData = encrypt(AES_CBC_NOPadding,buff.array(),key);	
		
		buff = ByteBuffer.wrap(eData);
		buff.position(buff.capacity()-16);
		buff.get(mac);	
		
		return mac;
	}
	/**
	 * 计算MAC
	 * @param hexData
	 * @param hexKey
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String encryptMac(String data,String hexKey) throws UnsupportedEncodingException {
		byte[] srcData = data.getBytes(CHARSET_UTF8);
		byte[] key = DataConvert.hex2byte(hexKey);
		
		return DataConvert.ByteArraytoHexString(encryptMac(srcData,key));
	}
	
	static AlgorithmParameterSpec makeIv() {
		IvParameterSpec ips = new IvParameterSpec(IV);
		return ips;
	}

	static Key makeKey(byte[] encodedKey) {
		SecretKey aesKey = new SecretKeySpec(encodedKey, "AES");
		return aesKey;
	}
	public static void main(String[] args) throws UnsupportedEncodingException{
		//秘钥长度为24byte
		String ENCRYPTION_KEY = "6C6F67696E41434D452D31326C6F67696E41434D452D3132";
		String src = "ED7182AECBC7D5700A34BB682E0E13EE769A692E2EA3936ED33A52E639CA0AA4F06ED47F66AC0B9FD270BBF123DBEE2B2F4E16D36C782B2C4DECECA8E08EF2DD";
		System.out.println("src: " + src);
		String encrypted = AesUtils.encrypt(AES_CBC_PKCS5Padding,src,ENCRYPTION_KEY,CHARSET_UTF8);
		System.out.println("encrypted: " + encrypted);
		String decrypted = AesUtils.decrypt(AES_CBC_PKCS5Padding,encrypted,ENCRYPTION_KEY);
		System.out.println("decrypted: " + decrypted);

	}
}

 

 

public class DataConvert {
    public DataConvert() {
    }

    /**
   * print Hex byteArray
   * @param b byte[]
   */
    public static void PrintByteArray(byte[] b) {
        char[] hex =
        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
                       'e', 'f' };

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

            if (i % 8 == 0)
                System.out.println("");
            System.out
            .print("0x" + hex[(b[i] >> 4 & 0x0f)] + hex[b[i] & 0x0f] + "; ");


        }
    
    }
    public static String getBytePrintString(byte[] b) {
        char[] hex =        
        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
                       'E', 'F' };
        StringBuffer sb=new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            
            sb.append( ""+hex[(b[i] >> 4 & 0x0f)] + hex[b[i] & 0x0f] );


        }
        return sb.toString();     
    }

    /**
   * This method convert byte array to String
   * @author sgc
   * @return String
   * @param  byte[] b,int bLen is :b' availability length
   */
    public static String ByteArraytoHexString(byte[] b, int bLen) {
        int iLen = bLen;
        //每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
        StringBuffer sb = new StringBuffer(iLen * 2);
        for (int i = 0; i < iLen; i++) {
            int intTmp = b[i];
            //把负数转换为正数
            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }
            //小于0F的数需要在前面补0
            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16));
        }
        return sb.toString().toUpperCase();
    }
    /**
     * This method convert byte array to String
     * @author sgc
     * @return String
     * @param  byte[] b,int bLen is :b' availability length
     */
      public static String ByteArraytoHexString(byte[] b) {
          int iLen = b.length;
          //每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
          StringBuffer sb = new StringBuffer(iLen * 2);
          for (int i = 0; i < iLen; i++) {
              int intTmp = b[i];
              //把负数转换为正数
              while (intTmp < 0) {
                  intTmp = intTmp + 256;
              }
              //小于0F的数需要在前面补0
              if (intTmp < 16) {
                  sb.append("0");
              }
              sb.append(Integer.toString(intTmp, 16));
          }
          return sb.toString().toUpperCase();
      }
    /**
   * Int (or) long to ByteArray
   * @param number long
   * @return byte[]
   */
    public static

    byte[] LongtoByteArray(long number) {
        long temp = number;
        StringBuffer s = new StringBuffer(Long.toString(temp, 16));
        if (s.length() % 2 == 1) {
            return StringToBytes("0" + s.toString());
        } else {
            return StringToBytes(s.toString());
        }

    }


    /**
   * ByteArray to int or long
   * @param b byte[]
   * @return int
   */
    public static int ByteArraytoInteger(byte[] b) {
        int s = 0;
        for (int i = 0; i < 3; i++) {
            if (b[i] > 0) {
                s = s + b[i];
            } else {
                s = s + 256 + b[i];
            }
            s = s * 256;
        }
        if (b[3] > 0) {
            s = s + b[3];
        } else {
            s = s + 256 + b[3];
        }
        return s;
    }

    

    public static long ByteArraytoLong(byte[] b) {
        long l = 0;
        for (int i = 0; i < b.length; i++) {
            l += (long)(b[b.length - i - 1]&0xff) << (8 * i);
        }

        return l;
    }
    public static long ByteArraytoLong(byte[] b,int start ,int len) {
        long l = 0;
        for (int i = 0; i < len; i++) {
            l += (long)(b[start+len - i - 1]&0xFF) << (8 * i);
            
        }

        return l;
    }
    /**
   * ByteArray to Double
   * @param b byte[]
   * @return double
   */
    public static double ByteArraytoDouble(byte[] b) {
        long l = 0;
        Double D = new Double(0.0);
        l = b[0];
        l = ((long)b[1] << 8);
        l = ((long)b[2] << 16);
        l = ((long)b[3] << 24);
        l = ((long)b[4] << 32);
        l = ((long)b[5] << 40);
        l = ((long)b[6] << 48);
        l = ((long)b[7] << 56);
        return Double.longBitsToDouble(l);
    }

    public static final byte[] StringToBytes(String s) {
        int temp[] = new int[s.length()];
        byte b[] = new byte[s.length() / 2];
        for (int i = 0; i < s.length(); i++) {
            temp[i] = Integer.parseInt(String.valueOf(s.charAt(i)), 16);
        }
        int k = 0;
        for (int j = 0; j < s.length(); j += 2) {
            b[k] = (byte)(temp[j] * 16 + temp[j + 1]);
            k++;
        }

        return b;
    }
    /*
   Integer和Long提供了toBinaryString, toHexString和toOctalString方 法,可以方便的将数据转换成二进制、十六进制和八进制字符串。功能更加强大的是其toString(int/long i, int radix)方法,可以将一个十进制数转换成任意进制的字符串形式。
   */

    public static String getRandom(int len, int radix) {
        StringBuffer buf = new StringBuffer("1");
        for (int i = 0; i < len; i++) {
            buf.append("0");
        }
        int div = Integer.parseInt(buf.toString());

        int value = (int)(Math.random() * div);

        if (radix == 10)
            return strPadding(value, len);
        else
            return hexStrPadding(Integer.toHexString(value), len);
    }

    /**
     * 
     * @param in
     * @param outlen
     * @return
     */
    public static final String strPadding(long in, int outlen) {
        String str = String.valueOf(in);
        int padlen = outlen - str.length();

        StringBuffer zeroBuf = new StringBuffer("");
        for (int i = 0; i < padlen; i++) {
            zeroBuf.append("0");
        }

        return zeroBuf.append(str).toString();
    }

    public static final String hexStrPadding(String in, int outlen) {
        int padlen = outlen - in.length();

        StringBuffer zeroBuf = new StringBuffer("");
        for (int i = 0; i < padlen; i++) {
            zeroBuf.append("0");
        }

        return zeroBuf.append(in).toString();
    }
    public static byte[] hex2byte(String hex) throws IllegalArgumentException {
        if (hex.length() % 2 != 0) {
            throw new IllegalArgumentException();
        }
        char[] arr = hex.toCharArray();
        byte[] b = new byte[hex.length() / 2];
        for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
            String swap = "" + arr[i++] + arr[i];
            int byteint = Integer.parseInt(swap, 16) & 0xFF;
            b[j] = new Integer(byteint).byteValue();
        }
        return b;
    }
    
    public static String decimal2Hex(String str){
        return Integer.toHexString(Integer.parseInt(str));
    }
    public static byte[] LongtoByteArray(long number, int len) {
		long temp = number;
		StringBuffer s = new StringBuffer(Long.toString(temp, 16));
		StringBuffer tmp = new StringBuffer();
		if (s.length() % 2 == 1) {
			tmp.append("0" + s.toString());
		} else {
			tmp.append(s.toString());
		}
		while (tmp.length() < len * 2) {
			tmp.insert(0, "00");
		}
		return StringToBytes(tmp.toString());
	}
}

 

AES加密的时候可能遇到以下错误

    默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误Invalid AES key length。

你需要下载一个支持更长密钥的包。这个包叫做 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6,可以从这里下载,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

   下载之后,解压后,可以看到其中包含两个包:

    local_policy.jar

    US_export_policy.jar

 

    看一下你的 JRE 环境,将 JRE 环境中 jre\lib\security 中的同名包替换掉。对于jdk来说就是以下目录:Java\jdk1.6.0_45\jre\lib\security。

 

 

  • PBE(Password-based encryption,基于密码验证)

  • RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman) RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的

package com.xizheng.test.xizhneg;  
  
import java.math.BigInteger;  
import java.security.KeyFactory;  
import java.security.KeyPair;  
import java.security.KeyPairGenerator;  
import java.security.NoSuchAlgorithmException;  
import java.security.interfaces.RSAPrivateKey;  
import java.security.interfaces.RSAPublicKey;  
import java.security.spec.RSAPrivateKeySpec;  
import java.security.spec.RSAPublicKeySpec;  
import java.util.HashMap;  
  
import javax.crypto.Cipher;  
  
public class RSAUtils {  
  
    /** 
     * 生成公钥和私钥 
     * @throws NoSuchAlgorithmException  
     * 
     */  
    public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException{  
        HashMap<String, Object> map = new HashMap<String, Object>();  
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
        keyPairGen.initialize(1024);  
        KeyPair keyPair = keyPairGen.generateKeyPair();  
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  
        map.put("public", publicKey);  
        map.put("private", privateKey);  
        return map;  
    }  
    /** 
     * 使用模和指数生成RSA公钥 
     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA/None/NoPadding】 
     *  
     * @param modulus     模 
     * @param exponent    指数 
     * @return 
     */  
    public static RSAPublicKey getPublicKey(String modulus, String exponent) {  
        try {  
            BigInteger b1 = new BigInteger(modulus);  
            BigInteger b2 = new BigInteger(exponent);  
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);  
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 使用模和指数生成RSA私钥 
     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA/None/NoPadding】 
     *  
     * @param modulus   模 
     * @param exponent  指数 
     * @return 
     */  
    public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {  
        try {  
            BigInteger b1 = new BigInteger(modulus);  
            BigInteger b2 = new BigInteger(exponent);  
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);  
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 公钥加密 
     *  
     * @param data 
     * @param publicKey 
     * @return 
     * @throws Exception 
     */  
    public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
            throws Exception {  
        Cipher cipher = Cipher.getInstance("RSA");  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
        // 模长  
        int key_len = publicKey.getModulus().bitLength() / 8;  
        // 加密数据长度 <= 模长-11  
        String[] datas = splitString(data, key_len - 11);  
        String mi = "";  
        //如果明文长度大于模长-11则要分组加密  
        for (String s : datas) {  
            mi += bcd2Str(cipher.doFinal(s.getBytes()));  
        }  
        return mi;  
    }  
  
    /** 
     * 私钥解密 
     *  
     * @param data 
     * @param privateKey 
     * @return 
     * @throws Exception 
     */  
    public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)  
            throws Exception {  
        Cipher cipher = Cipher.getInstance("RSA");  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
        //模长  
        int key_len = privateKey.getModulus().bitLength() / 8;  
        byte[] bytes = data.getBytes();  
        byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
        System.out.println(bcd.length);  
        //如果密文长度大于模长则要分组解密  
        String ming = "";  
        byte[][] arrays = splitArray(bcd, key_len);  
        for(byte[] arr : arrays){  
            ming += new String(cipher.doFinal(arr));  
        }  
        return ming;  
    }  
    /** 
     * ASCII码转BCD码 
     *  
     */  
    public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
        byte[] bcd = new byte[asc_len / 2];  
        int j = 0;  
        for (int i = 0; i < (asc_len + 1) / 2; i++) {  
            bcd[i] = asc_to_bcd(ascii[j++]);  
            bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
        }  
        return bcd;  
    }  
    public static byte asc_to_bcd(byte asc) {  
        byte bcd;  
  
        if ((asc >= '0') && (asc <= '9'))  
            bcd = (byte) (asc - '0');  
        else if ((asc >= 'A') && (asc <= 'F'))  
            bcd = (byte) (asc - 'A' + 10);  
        else if ((asc >= 'a') && (asc <= 'f'))  
            bcd = (byte) (asc - 'a' + 10);  
        else  
            bcd = (byte) (asc - 48);  
        return bcd;  
    }  
    /** 
     * BCD转字符串 
     */  
    public static String bcd2Str(byte[] bytes) {  
        char temp[] = new char[bytes.length * 2], val;  
  
        for (int i = 0; i < bytes.length; i++) {  
            val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
            temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
  
            val = (char) (bytes[i] & 0x0f);  
            temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
        }  
        return new String(temp);  
    }  
    /** 
     * 拆分字符串 
     */  
    public static String[] splitString(String string, int len) {  
        int x = string.length() / len;  
        int y = string.length() % len;  
        int z = 0;  
        if (y != 0) {  
            z = 1;  
        }  
        String[] strings = new String[x + z];  
        String str = "";  
        for (int i=0; i<x+z; i++) {  
            if (i==x+z-1 && y!=0) {  
                str = string.substring(i*len, i*len+y);  
            }else{  
                str = string.substring(i*len, i*len+len);  
            }  
            strings[i] = str;  
        }  
        return strings;  
    }  
    /** 
     *拆分数组  
     */  
    public static byte[][] splitArray(byte[] data,int len){  
        int x = data.length / len;  
        int y = data.length % len;  
        int z = 0;  
        if(y!=0){  
            z = 1;  
        }  
        byte[][] arrays = new byte[x+z][];  
        byte[] arr;  
        for(int i=0; i<x+z; i++){  
            arr = new byte[len];  
            if(i==x+z-1 && y!=0){  
                System.arraycopy(data, i*len, arr, 0, y);  
            }else{  
                System.arraycopy(data, i*len, arr, 0, len);  
            }  
            arrays[i] = arr;  
        }  
        return arrays;  
    }  
    
    public static void main(String[] args) throws Exception {  
        HashMap<String, Object> map = RSAUtils.getKeys();  
        //生成公钥和私钥  
        RSAPublicKey publicKey = (RSAPublicKey) map.get("public");  
        RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");  
          
        //模  
        String modulus = publicKey.getModulus().toString();  
        //公钥指数  
        String public_exponent = publicKey.getPublicExponent().toString();  
        //私钥指数  
        String private_exponent = privateKey.getPrivateExponent().toString();  
        //明文  
        String mingWen = "测试用例";  
        //使用模和指数生成公钥和私钥  
        RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);  
        RSAPrivateKey priKey = RSAUtils.getPrivateKey(modulus, private_exponent);  
        //加密后的密文  
        String mi = RSAUtils.encryptByPublicKey(mingWen, pubKey);  
        System.out.println(mi);  
        //解密后的明文  
        mingWen = RSAUtils.decryptByPrivateKey(mi, priKey);  
        System.out.println(mingWen);  
    } 
}  

 

  • DH(Diffie-Hellman算法,密钥一致协议)

  • DSA(Digital Signature Algorithm,数字签名)数字签名算法,是一种标准的 DSS(数字签名标准);

  • ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)

 

 

参考链接:

http://www.blogjava.net/amigoxie/archive/2014/06/01/414299.html

http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html

http://www.open-open.com/lib/view/open1397274257325.html

http://www.cnblogs.com/shoubianxingchen/p/5305617.html

 

 

猜你喜欢

转载自zhengxiangbin2008.iteye.com/blog/2335848