zoukankan      html  css  js  c++  java
  • java加密-解密小结

    加密算法可以分为

    双向加密(对称加密、不对称加密)

    单向加密(不可逆加密)—— MD5、sha、hmac...

    对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密

    有: DES AES。。

    不对称加密算法使用两把完全不同但又是完全匹配的一对钥匙—公钥和私钥。在使用不对称加密算法加密文件时,只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程

    RSA、DSA。。

     ================ 上面的全是废话 =============


     主要参照http://zhangyiqian.iteye.com/blog/1470713

     Md5 消息摘要5 —— MessageDigest

     好像还有一个版本是MessageDigest4、3 ,不过当然没有5好,现在已经被弃用。

    关键点:

    1 借助java.security.MessageDigest,这是jdk自带的。加密要点只有两个:MessageDigest的update、digest方法MessageDigest比较‘单纯’,只提供几个简单方法

    2 无论要加密的数据的长短,结果长度都是固定的(32或者16)。—— 加密过程是十分快速的。据我测试,无论加密的数据的长短,加密时间几乎一样。

    3 将byte[]组装string有2个方法: 1 借助 Hex ;2  自己组装

    4 md5是单向加密,原理上是可以极难破解的,不过听说只要解密的'md5数据库'足够大,我们也很快可以反查出原始加密信息。。。

    5 密码是可能出现重复的? 就是不同字符串的加密结果可能一样?

    MessageDigest.getInstance("MD5"); —— 除了md5还有其他的 SHA-1 or SHA-256 —— 不知道什么区别。。

    7 sha的加密结果长度固定,同md5.

    8 一般用来加密用户的密码,通常我们可能还需要对密码加盐或者随机盐,然后加密。。

    不知道其底层原理,—— 某些很大的几十几百M下载包、文件等都是通过md5加密的(其中还有sha加密选项。。),可能是其加密速度快的原因吧!

    package basic.security;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import org.apache.commons.codec.binary.Hex;
    
    public class EncrypMD5 {
    	
    	public byte[] eccrypt(String info) throws NoSuchAlgorithmException{
    		//���MD5�㷨���MessageDigest����
    		MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    		byte[] srcBytes = info.getBytes();
    		//ʹ��srcBytes����ժҪ
    		md5.update(srcBytes);
    		//��ɹ�ϣ���㣬�õ�result
    		byte[] resultBytes = md5.digest();
    		return resultBytes;
    	}
    	
    	public static void main(String args[]) throws NoSuchAlgorithmException{
    		String msg = "aaa";
    		EncrypMD5 md5 = new EncrypMD5();
    		byte[] b = md5.eccrypt(msg);
    		//System.out.println(((b)));
    		//System.out.println(new String((b)));
    		//System.out.println((new Hex().encode(b))); //[B@58ea58e3: byte[]没法直接显示成string
    		
    		// 将byte[]组装string ?
    		// 1 借助 Hex
    		System.out.println(new String(new Hex().encode(b)));
    		
    		
    		// 2 自己组装
    		int i;
    		StringBuffer buf = new StringBuffer(); 
    	    for (int offset = 0; offset < b.length; offset++) {
    	    	i = b[offset];
    	    	if (i < 0) {
    	    		i += 256;
    	    	}
    	    	if (i < 16) {
    	    		buf.append("0");
    	    	}
    	    	// 将整型 十进制 i 转换为16位,用十六进制参数表示的无符号整数值的字符串表示形式。
    	    	buf.append(Integer.toHexString(i)); 
    	    }
    	    
    	    // 32位的加密
    	    String md5Str = buf.toString();
    	     System.out.println(""+ md5Str);
    	    // 16位的加密
    	     md5Str = buf.toString().substring(8,24); 
    		System.out.println(""+ md5Str);
    		
    	}
    
    }
    

      

     Base64/32     我也不知道这个什么用。。。

    1 实现借助sun.misc.BASE64Decoder/ sun.misc.BASE32Decoder 是jdk自带的

    2 调用非常简单:加密encode,解密是静态方法decodeBuffer

    3 不同于md5,加密结果随着要加密的字符串长短不同而不同。

    package basic.security;
    
    import java.io.IOException;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    
    public class Base64Test {
    
    	public String encode(String toEncodeContent){
    		if(toEncodeContent == null){
    			return null;
    		}
    		BASE64Encoder encoder = new BASE64Encoder();
    //		BASE32Encoder encoder32 = new BASE32Encoder();
    		return encoder.encode(toEncodeContent.getBytes());
    	}
    	
    	public String decode(String toDecodeContent){
    		if(toDecodeContent == null) {
    			return null;
    		}
    		byte[] buf = null;
    		try {
    			buf = new BASE64Decoder().decodeBuffer(toDecodeContent);
    		} catch(IOException e){
    			e.printStackTrace();
    		} finally {
    		}
    		return new String(buf);
    	}
    	
    	public static void main(String[] args) throws Exception {
    		Base64Test test = new Base64Test();
    		String toEncodeContent = "I12313";
    		String encodeRet = test.encode(toEncodeContent);
    		System.out.println(encodeRet);
    		System.out.println(test.decode(encodeRet));
    	}
    }
    

      

    参考http://www.iteye.com/topic/1122076 写得非常好!

    http://723242038.iteye.com/blog/1813853 good,有清晰的图解

    对称加密算法 DES/3DES/AES (es结尾。。)

    1 主要借助javax.crypto.包的 KeyGenerator 对称密钥生成器,其generateKey方法以获取密钥,——SecretKey 保存对称密钥。javax.crypto包的Cipher 负责完成加密或解密工作

    2 加密 c.init(Cipher.ENCRYPT_MODE, deskey); cipherByte = c.doFinal(src);     --- ENCRYPT_MODE 即表示加密! doFinal完成加密

    3 解密 c.init(Cipher.DECRYPT_MODE, deskey); cipherByte = c.doFinal(buff);    ----DECRYPT_MODE 表示解密

    4 加密解密使用的是同一个deskey,——- 表明是对称加密算法。!!!

    5 比起最初的DES,3DES更为安全.跟早期常用于wifi密码加密的wes貌似。不过现在似乎被认为不安全,被wpa2加密了。。。

    6 各个加密算法本质上有很大的实现不同,但是sun给我们封装了, 使用上区别仅仅在于keygen = KeyGenerator.getInstance("算法名字"); 其中名字的不同。

    7 加密结果不是长度固定的,大概是加密字符越长,结果就越长。。

    package basic.security;
    
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    
    public class EncrypDES {
    	
    	//KeyGenerator 提供对称密钥生成器的功能,支持各种算法
    	private KeyGenerator keygen;
    	//SecretKey 负责保存对称密钥
    	private SecretKey deskey;
    	//Cipher负责完成加密或解密工作
    	private Cipher c;
    	//该字节数组负责保存加密的结果
    	private byte[] cipherByte;
    	
    	public EncrypDES() throws NoSuchAlgorithmException, NoSuchPaddingException{
    		Security.addProvider(new com.sun.crypto.provider.SunJCE());
    		//实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)
    		keygen = KeyGenerator.getInstance("DES");
    		//生成密钥
    		deskey = keygen.generateKey();
    		//生成Cipher对象,指定其支持的DES算法
    		c = Cipher.getInstance("DES");
    	}
    	
    	/**
    	 * 对字符串加密
    	 * 
    	 * @param str
    	 * @return
    	 * @throws InvalidKeyException
    	 * @throws IllegalBlockSizeException
    	 * @throws BadPaddingException
    	 */
    	public byte[] Encrytor(String str) throws InvalidKeyException,
    			IllegalBlockSizeException, BadPaddingException {
    		// 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式
    		c.init(Cipher.ENCRYPT_MODE, deskey);
    		byte[] src = str.getBytes();
    		// 加密,结果保存进cipherByte
    		cipherByte = c.doFinal(src);
    		return cipherByte;
    	}
    
    	/**
    	 * 对字符串解密
    	 * 
    	 * @param buff
    	 * @return
    	 * @throws InvalidKeyException
    	 * @throws IllegalBlockSizeException
    	 * @throws BadPaddingException
    	 */
    	public byte[] Decryptor(byte[] buff) throws InvalidKeyException,
    			IllegalBlockSizeException, BadPaddingException {
    		// 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式
    		c.init(Cipher.DECRYPT_MODE, deskey);
    		cipherByte = c.doFinal(buff);
    		return cipherByte;
    	}
    
    	/**
    	 * @param args
    	 * @throws NoSuchPaddingException 
    	 * @throws NoSuchAlgorithmException 
    	 * @throws BadPaddingException 
    	 * @throws IllegalBlockSizeException 
    	 * @throws InvalidKeyException 
    	 */
    	public static void main(String[] args) throws Exception {
    		EncrypDES de1 = new EncrypDES();
    		String msg ="lkasddad艾弗森的";
    		byte[] encontent = de1.Encrytor(msg);
    		byte[] decontent = de1.Decryptor(encontent);
    		System.out.println("明文是:" + msg);
    		System.out.println("加密后:" + new String(encontent));
    		System.out.println("解密后:" + new String(decontent));
    	}
    
    }
    

     

    非对称加密算法 RSA/DSA(sa结尾。。)

    1 代码类似上面,只涉及jdk的java.security和javax.crypto,RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥(即公钥)—————— 即哥德巴赫猜想!!

    2 关键代码

    初始化:   
     KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    		//初始化密钥对生成器,密钥大小为1024位
    		keyPairGen.initialize(1024);
    		//生成一个密钥对,保存在keyPair中
    		KeyPair keyPair = keyPairGen.generateKeyPair();
    		//得到私钥
    		RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();				
    		//得到公钥
    		RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();       
    
     加密:
    //Cipher负责完成加密或解密工作,基于RSA
    			Cipher cipher = Cipher.getInstance("RSA");
    			//根据公钥,对Cipher对象进行初始化
    			cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 采用加密模式ENCRYPT_MODE
    byte[] resultBytes = cipher.doFinal(srcBytes); 

    解密
    //Cipher负责完成加密或解密工作,基于RSA
    Cipher cipher = Cipher.getInstance("RSA");
    //根据公钥,对Cipher对象进行初始化
    cipher.init(Cipher.DECRYPT_MODE, privateKey);// 采用解密模式DECRYPT_MODE
    byte[] resultBytes = cipher.doFinal(srcBytes);

    1 主要有KeyPairGenerator,KeyPair,RSAPublicKey,RSAPrivateKey,Cipher

    2 实际运用此算法的时候,RSAPublicKey,RSAPrivateKey同时被生成出来,保存不同地方--可能是文件里面

    URLEncoding

    URLDecoding

    其他的一些加密算法

    =======================

    加密算法和SSL等安全协议的关系:

    ssl加密要比上面的复杂得多,它是一种协议,是一个过程,多种算法的集合。。 可以理解为其主要运用了RSA等算法来存储密钥、对称算法来传输数据的ssl协议实现

    一般ssl的加密过程:

    我的详细的加密过程如下 
    1:client created RSA key pair 
    2:client sent RSA public key to Server 
    3:server generated an AES key (AESKey) 
    4:server sent RSA encrypted AESKey to client 
    5:client got AESKey with RSA decryption 
    6:client and server use AESkey to encrypt and decrypt net data

    ====

    SSL协议通讯时候是对称算法的,可以使用AES128做期间的通讯。
    只有密钥协商的时候才是非对称的

    ===

    你的思路基本上和SSL差不多了,当然没有SSL那么完善。
    SSL的主要优点是防御中间人攻击,而对称加密还有你后来的RSA方法都无法做到这点

    ===

    ,SSL的握手过程中加入了HMAC,能有效防范重放攻击 (如果采用双向认证?)

    见 http://www.iteye.com/topic/213512

    http://www.iteye.com/topic/1125183 非常棒,非常详细,可惜没耐心看完。貌似其过程跟我另一篇关于ssh的文章相似

    =======================

    加密解密与SSH

     首先要明白ssh、ssl的区别

    http://www.cnblogs.com/haitao-fan/archive/2012/08/31/2665211.html
    http://www.cnblogs.com/FanTasYX/archive/2013/03/22/2976473.html

    其实,发现和ssl差别不是很大。。。

  • 相关阅读:
    【Unity与23种设计模式】命令模式(Command)
    【Unity3D与23种设计模式】组合模式(Composite)
    【Unity3D与23种设计模式】享元模式(Flyweight)
    【Unity3D与23种设计模式】建造者模式(Builder)
    【Unity3D与23种设计模式】工厂方法模式(Factory Method)
    【Unity3D与23种设计模式】模板方法模式(Template Method)
    【Unity3D与23种设计模式】策略模式(Strategy)
    【Unity3D与23种设计模式】桥接模式(Bridge)
    C# 清空数组Array.Clear
    Unity 修改windows窗口的标题
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/3564923.html
Copyright © 2011-2022 走看看