常用的加密算法

来源:互联网 发布:芭碧琪面膜怎么样 知乎 编辑:程序博客网 时间:2024/06/16 20:06
一。摘要算法

    1》MD5算法(Message Digest Algorithm 5) 可以保证数据传输完整性和一致性 摘要后长度为16字节 摘要信息中不包含原文信息

所有加密结果不可逆(无法解密) 一般在传送文件时 对源文件进行md5 hash 传送到对方后 检测hash值是否相等 如果相等文件传输正确

如果不相等 说明文件被篡改(加入木马)或者未传送完成

    其他MD算法 MD2(16字节)

     

[html] view plain copy
  1. public static void main(String[] args) throws NoSuchAlgorithmException {  
  2.         MessageDigest md=MessageDigest.getInstance("MD5") ;  
  3.         String code="hello";  
  4.         byte[] bt=md.digest(code.getBytes());  
  5.         System.out.println(bt.length);  
  6.     }  
    2》SHA算法Secure Hash Algorithm(安全hash算法) 安全散列算法(hash函数 将原始信息压缩 返回散列值)可以是SHA-1,SHA1是目前最安全

的摘要算法 摘要的长度为 20字节 

     其他的SHA 包括 SHA-256(32字节)

    

[html] view plain copy
  1. public static void main(String[] args) throws NoSuchAlgorithmException {  
  2.         MessageDigest md=MessageDigest.getInstance("SHA") ;//或者SHA-1 SHA1  
  3.         String code="hello";  
  4.         byte[] bt=md.digest(code.getBytes());  
  5.         System.out.println(bt.length);  
  6.           
  7.     }  

二。编码和解码

   1》16进制 编码  计算机系统使用 2进制 为了编写存储方便一般将2进制 转换为16进制字符串 其中base64也是其中类似转换一种 16进制编码和base64都是

可逆的 一般用于存储

[html] view plain copy
  1. public static byte[] toByte(String src){  
  2.         ByteArrayOutputStream baos=new ByteArrayOutputStream();  
  3.         for(int i=0;i<src.length();i=i+2){  
  4.             char fchar=src.charAt(i);  
  5.             char nchar=src.charAt(i+1);  
  6.             byte srcb=0;  
  7.             if(fchar=='0'){  
  8.                 srcb=Byte.parseByte(nchar+"", 16);  
  9.             }else{  
  10.                 srcb=(byte)(Integer.parseInt(fchar+""+nchar, 16));  
  11.             }  
  12.             baos.write(srcb);  
  13.         }  
  14.         return baos.toByteArray();  
  15.     }  
  16.       
  17.       
  18.     public static String toHex(byte[] src){  
  19.         StringBuffer sb=new StringBuffer();  
  20.         for(byte s:src){  
  21.             //0XFF表示  8位的 11111111  和它&后 只剩下 8位 其他位都为0  
  22.             String result=Integer.toHexString(s&0xFF);  
  23.             if(result.length()==1){  
  24.                 result='0'+result;  
  25.             }  
  26.             sb.append(result);  
  27.         }  
  28.         return sb.toString();  
  29.     }  

  

 2》Base64编码  用于将字节数组和字符串互相转换

[html] view plain copy
  1. public static void main(String[] args) throws NoSuchAlgorithmException, IOException {  
  2.         byte[] src="hello".getBytes();  
  3.         //摘要出来的结果为字节数组  存储到数据库不方便  
  4.         MessageDigest md=MessageDigest.getInstance("SHA") ;  
  5.         byte[] bt=md.digest(src);  
  6.         //使用base64转换为字符串方便存储  
  7.         BASE64Encoder base=new BASE64Encoder();  
  8.         String str=base.encode(bt);  
  9.         System.out.println(str);  
  10.           
  11.         //还原成字节数组  
  12.         BASE64Decoder de=new BASE64Decoder();  
  13.         byte[] bts=de.decodeBuffer(str);  
  14.         System.out.println(bt.length==bts.length);  
  15.     }  

三。对称加密

   1》DES算法 (Data Encryptin Standard) 是对称加密算法的一种 使用秘钥加解密  秘钥必须是56字节  

      概念解释:

            秘钥 :用于加密和解密的钥匙  秘钥可以使用 getEncoded方法 获取byte[] 存储在文件系统中

            公钥和私钥:用于非对称加密的钥匙 公钥加密 私钥解密  私钥一般用于解密所以私钥一般存储在密钥库中

            口令:一般是自定义的字符串  可以通过口令和盐生成秘钥 

[html] view plain copy
  1. /**  
  2.      * 生成56字节的秘钥  
  3.      */  
  4.     public static SecretKey genKey(int len) throws NoSuchAlgorithmException{  
  5.         KeyGenerator kg=KeyGenerator.getInstance("DES");  
  6.         kg.init(len);  
  7.         return kg.generateKey();  
  8.     }  
  9.     public static void main(String[] args) throws Exception {  
  10.         //SecretKey sk=new SecretKeySpec(kl.getBytes(), "DES");  
  11.         SecretKey sk=genKey(57);  
  12.         //---------加密  
  13.         String password="tiger";  
  14.         Cipher cipher=Cipher.getInstance("DES");  
  15.         cipher.init(Cipher.ENCRYPT_MODE, sk);  
  16.         //被加密之后获取的字节数组  
  17.         byte[] mcontent=cipher.doFinal(password.getBytes());  
  18.         //---------解密  
  19.         Cipher cipher1=Cipher.getInstance("DES");  
  20.         cipher1.init(Cipher.DECRYPT_MODE, sk);  
  21.         System.out.println(new String(cipher1.doFinal(mcontent)));  
  22.           
  23.       
  24.     }  

   2》AES算法 (Advanced Encryptin Standard 高级加密标准) 是对称加密算法一种升级 因为 56位秘钥 在计算机系统性能越来越高的前提下 56位很容易被

  破解 所以 AES将秘钥的长度提高到128, 192 or 256  必须是这三个数 128默认可以使用  192和256由于美国限制 需要相关授权 否则抛出异常

[html] view plain copy
  1. public static final String AL="AES";  
  2.     /**  
  3.      * 生成56字节的秘钥  
  4.      */  
  5.     public static SecretKey genKey(int len) throws NoSuchAlgorithmException{  
  6.         KeyGenerator kg=KeyGenerator.getInstance(AL);  
  7.         kg.init(len);  
  8.         return kg.generateKey();  
  9.     }  
  10.     public static void main(String[] args) throws Exception {  
  11.         //SecretKey sk=new SecretKeySpec(kl.getBytes(), "DES");  
  12.         SecretKey sk=genKey(128);  
  13.         //---------加密  
  14.         String password="tiger";  
  15.         Cipher cipher=Cipher.getInstance(AL);  
  16.         cipher.init(Cipher.ENCRYPT_MODE, sk);  
  17.         //被加密之后获取的字节数组  
  18.         byte[] mcontent=cipher.doFinal(password.getBytes());  
  19.         //---------解密  
  20.         Cipher cipher1=Cipher.getInstance(AL);  
  21.         cipher1.init(Cipher.DECRYPT_MODE, sk);  
  22.         System.out.println(new String(cipher1.doFinal(mcontent)));  
  23.           
  24.       
  25.     }  

 3》PBE算法(Password Base Encryption) 基于自定义口令的加解密算法  定义口令 同时还必须定义 盐和 使用盐混淆的次数 

加解密过程中 该三个参数都必须一致

[html] view plain copy
  1. //盐 用于将明文进行多次混淆  
  2.     static byte[] salt = new byte[8];  
  3.     static Random r = new Random();  
  4.     static int saltCount=100;  
  5.     static{  
  6.         r.nextBytes(salt);  
  7.     }  
  8.     public static final String AL="PBEWithMD5AndDES";  
  9.     /**  
  10.      * 生成自定义口令的秘钥  
  11.      */  
  12.     public static SecretKey genKey(String kl) throws Exception{  
  13.         char[] klChar=kl.toCharArray();  
  14.         PBEKeySpec pbe=new PBEKeySpec(klChar);  
  15.         SecretKeyFactory skf=SecretKeyFactory.getInstance(AL);  
  16.         return skf.generateSecret(pbe);  
  17.     }  
  18.     /**  
  19.      * 使用口令和盐进行加密  
  20.      */  
  21.     public static  byte[] encrypt(SecretKey key,byte[] src) throws Exception{  
  22.         Cipher cipher=Cipher.getInstance(AL);  
  23.         //使用口令  盐(100次混淆)  
  24.         PBEParameterSpec parameter=new PBEParameterSpec(salt, saltCount);  
  25.         cipher.init(Cipher.ENCRYPT_MODE, key,parameter);  
  26.         //被加密之后获取的字节数组  
  27.         byte[] mcontent=cipher.doFinal(src);  
  28.         return mcontent;  
  29.     }  
  30.     /**  
  31.      * 使用口令和盐进行解密  盐和口令和混淆的次数都必须和加密之前一致  
  32.      */  
  33.     public static byte[] decrypt(SecretKey key,byte[] src) throws Exception{  
  34.         Cipher cipher=Cipher.getInstance(AL);  
  35.         //使用口令  盐(100次混淆)  
  36.         PBEParameterSpec parameter=new PBEParameterSpec(salt, saltCount);  
  37.         cipher.init(Cipher.DECRYPT_MODE, key,parameter);  
  38.         //被加密之后获取的字节数组  
  39.         byte[] mcontent=cipher.doFinal(src);  
  40.         return mcontent;  
  41.     }  
  42.       
  43.       
  44.     public static void main(String[] args) throws Exception {  
  45.         //SecretKey sk=new SecretKeySpec(kl.getBytes(), "DES");  
  46.         SecretKey sk=genKey("123456");  
  47.         //---------加密  
  48.         String password="tiger";  
  49.         byte[] mw=encrypt(sk, password.getBytes());  
  50.         //---------解密  
  51.         System.out.println(new String(decrypt(sk, mw)));  
  52.     }  


四。非对称加密

  1》DH算法  是一种对称加密到非对称加密的过度算法 使用DH算法生成密钥对 使用对称加密算法获取秘钥后 进行加解密 双方必须都存在公钥和私钥

[html] view plain copy
  1. public static void main(String[] args) throws Exception {  
  2.         // 生成DH密钥对  
  3.         KeyPairGenerator kpg=KeyPairGenerator.getInstance("DH");  
  4.         kpg.initialize(512);  
  5.         KeyPair kp=kpg.generateKeyPair();  
  6.         PublicKey pk=kp.getPublic();  
  7.         PrivateKey prk=kp.getPrivate();  
  8.         //实例化    
  9.         KeyAgreement keyAgree = KeyAgreement.getInstance("DH");    
  10.         //初始化    
  11.         keyAgree.init(prk);    
  12.         keyAgree.doPhase(pk, true);    
  13.         //生成本地密钥    
  14.         SecretKey secretKey = keyAgree.generateSecret("DES");    
  15.   
  16.         //还是使用对称方式加解密  
  17.         //使用本地秘钥加密  
  18.         Cipher cip=Cipher.getInstance("DES");  
  19.         cip.init(Cipher.ENCRYPT_MODE, secretKey);  
  20.         byte[] mw=cip.doFinal("test".getBytes());  
  21.         //使用本地秘钥解密  
  22.         Cipher cip1=Cipher.getInstance("DES");  
  23.         cip1.init(Cipher.DECRYPT_MODE, secretKey);  
  24.         System.out.println(new String(cip1.doFinal(mw)));  
  25.           
  26.     }  
2》RSA算法  目前影响力最大的非对称加密算法  一般公钥对外公开 加密后传送给服务器 服务器使用独有的私钥解密(当然也可以私钥加密 公钥解密 一般不这样 因为谁都有公钥都能解密 加密就没有意义了) 加密的数据在传输过程是 无法破解的  秘钥对初始化大小必须是64的倍数  实际值 只能在512-1024中

[html] view plain copy
  1. public static void main(String[] args) throws Exception {  
  2.         // 生成RSA密钥对  
  3.         KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");  
  4.         kpg.initialize(512);  
  5.         KeyPair kp=kpg.generateKeyPair();  
  6.         PublicKey pk=kp.getPublic();  
  7.         PrivateKey prk=kp.getPrivate();   
  8.   
  9.         //公钥加密  
  10.         Cipher cip=Cipher.getInstance("RSA");  
  11.         cip.init(Cipher.ENCRYPT_MODE, pk);  
  12.         byte[] mw=cip.doFinal("test".getBytes());  
  13.         //私钥解密  
  14.         Cipher cip1=Cipher.getInstance("RSA");  
  15.         cip1.init(Cipher.DECRYPT_MODE, prk);  
  16.         System.out.println(new String(cip1.doFinal(mw)));  
  17.           
  18.     }  

RSA算法中 一般公钥和私钥都都可以调用getEncoded()转换为byte数组 使用base64编码后 存储在文件中 方便公钥分发 读取文件后需要转换对应

的公钥和私钥的方法为:

[html] view plain copy
  1. /**  
  2.      * 读取公钥字节数组转换为对象  
  3.      * @throws Exception   
  4.      */  
  5.     public PublicKey getPub(byte[] bt) throws Exception{  
  6.         X509EncodedKeySpec x=new X509EncodedKeySpec(bt);  
  7.         KeyFactory fac=KeyFactory.getInstance("RSA");  
  8.         return fac.generatePublic(x);  
  9.     }  
  10.     /**  
  11.      * 读取私钥字节数组转换为对象  
  12.      * @throws Exception   
  13.      */  
  14.     public PrivateKey getPri(byte[] bt) throws Exception{  
  15.         PKCS8EncodedKeySpec x=new PKCS8EncodedKeySpec(bt);  
  16.         KeyFactory fac=KeyFactory.getInstance("RSA");  
  17.         return fac.generatePrivate(x);  
  18.     }  
  19.       


五。数据签名(DSA)

   签名是非对称加密技术和摘要技术的综合运用用户A将明文和使用私钥加密的明文摘要一起发送给用户B 用户B使用公钥解密出摘要 然后使用相同的摘要

算法将明文摘要  将两个摘要字符串比较如果相等 则表明内容没有被篡改

  原理实现过程如下

[html] view plain copy
  1. public static void main(String[] args) throws Exception {  
  2.         //获取公钥和私钥  
  3.         KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");  
  4.         kpg.initialize(512);  
  5.         KeyPair kp=kpg.generateKeyPair();  
  6.         PublicKey pk=kp.getPublic();  
  7.         PrivateKey prk=kp.getPrivate();   
  8.         //使用私钥签名  
  9.         String message="hello my name is jiaozi";  
  10.         //返回的byte就可以进行传输  
  11.         byte[] srcByte=sign(message.getBytes(),prk);  
  12.         //假设这里模拟篡改数据 肯定会出现异常 或者检验不通过  
  13.         srcByte[9]=10;  
  14.         //存在公钥的用户 接受到该srcByte 就可以验证是否被篡改  
  15.         System.out.println(verify(srcByte,pk));  
  16.     }  
  17.     /**  
  18.      * 签名过程  
  19.      */  
  20.     public static byte[] sign(byte[] content,PrivateKey pk) throws Exception{  
  21.         //对明文进行摘要  
  22.         MessageDigest md=MessageDigest.getInstance("MD5");  
  23.         byte[] zy=md.digest(content);  
  24.           
  25.         //对摘要进行加密  
  26.         Cipher cp=Cipher.getInstance("RSA");  
  27.         cp.init(Cipher.ENCRYPT_MODE, pk);  
  28.         byte[] enZy=cp.doFinal(zy);  
  29.         //要一起传送的数据 双方约定好使用Map  
  30.         Map map=new HashMap();  
  31.         map.put("content", content);  
  32.         map.put("enZy", enZy);  
  33.         //传输过程使用byte数组 这里使用序列化将对象打包转换为字节数组  
  34.         ByteArrayOutputStream baos=new ByteArrayOutputStream();  
  35.         ObjectOutputStream oos=new ObjectOutputStream(baos);  
  36.         oos.writeObject(map);  
  37.         oos.close();  
  38.         return baos.toByteArray();  
  39.     }  
  40.       
  41.     /**  
  42.      * 验证签名过程  
  43.      */  
  44.     public static boolean verify(byte[] content,PublicKey pk) throws Exception{  
  45.         //将获取的数据转换为Map   
  46.         ByteArrayInputStream baos=new ByteArrayInputStream(content);  
  47.         ObjectInputStream oos=new ObjectInputStream(baos);  
  48.         Map map=(Map)oos.readObject();  
  49.         oos.close();  
  50.         //获取到明文和加密的摘要信息  
  51.         byte[] srcContent=(byte[])map.get("content");  
  52.         byte[] enZy=(byte[])map.get("enZy");  
  53.           
  54.         //使用相同的摘要算法 将明文摘要  
  55.         MessageDigest md=MessageDigest.getInstance("MD5");  
  56.         byte[] contentZy=md.digest(srcContent);  
  57.         //将加密的摘要解密  
  58.         Cipher cp=Cipher.getInstance("RSA");  
  59.         cp.init(Cipher.DECRYPT_MODE, pk);  
  60.         byte[] zy=cp.doFinal(enZy);  
  61.         BASE64Encoder bas=new BASE64Encoder();  
  62.         if(bas.encode(contentZy).equals(bas.encode(zy))){  
  63.             return true;  
  64.         }  
  65.         return false;  
  66.     }  
自己实现这个过程略显复杂 java提供了MD5WithRSA和SHA1WithRAS算法直接实现上述过程

[html] view plain copy
  1. public static void main(String[] args) throws Exception {  
  2.             //获取公钥和私钥  
  3.             KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");  
  4.             kpg.initialize(512);  
  5.             KeyPair kp=kpg.generateKeyPair();  
  6.             PublicKey pk=kp.getPublic();  
  7.             PrivateKey prk=kp.getPrivate();   
  8.             //使用私钥签名  
  9.             String message="hello my name is jiaozi";  
  10.             //返回的byte和明文就可以进行传输  
  11.             byte[] hash=sign(message.getBytes(),prk);  
  12.             //存在公钥的用户 接受到该srcByte 就可以验证是否被篡改  
  13.             System.out.println(verify(message.getBytes(),hash,pk));  
  14.               
  15.               
  16.         }  
  17.         /**  
  18.          * 签名过程 返回的是加密的摘要  
  19.          */  
  20.         public static byte[] sign(byte[] content,PrivateKey pk) throws Exception{  
  21.             Signature si=Signature.getInstance("MD5WithRSA");//或者使用SHA1WithRSA  
  22.             si.initSign(pk);  
  23.             si.update(content);  
  24.             return si.sign();  
  25.         }  
  26.           
  27.         /**  
  28.          * 验证签名过程  content表示原文可能获取原文的hash  hash表示sign函数返回的加密摘要  
  29.          */  
  30.         public static boolean verify(byte[] content,byte[] hash,PublicKey pk) throws Exception{  
  31.             Signature si=Signature.getInstance("MD5WithRSA");//或者使用SHA1WithRSA  
  32.             si.initVerify(pk);  
  33.             si.update(content);  
  34.             return si.verify(hash);  
  35.         }  
原创粉丝点击