【总结】公钥加密私钥解密/私钥加密公钥机密验证

来源:互联网 发布:免费.tk域名的注册 编辑:程序博客网 时间:2024/05/18 01:04

看到一篇文章:http://blog.csdn.net/cleble/article/details/50378829

联想到比特币以及工作内容所想到的问题。

RSA是非对称加密,用某篇文章的讲解就是说:假设有个黑科技的魔法机器,左边进的数据会唯一转换成右边的数据。右边不能进。

有了这个魔法工具,有左边的数据可以很容易的看到右边的数据。但是通过右边的数据完全不知道左边的数据。如果想知道,只能一个一个的去试,总有一天可以通过魔法工具试出右边数据的左边数据是什么。(看得懂吗?)

此处反思。。。




现在的问题是,有个反黑科技的魔法机器,专门怼上面的魔法机器。并且唯一职责就是只能从右边的数据获取左边的数据。右边的数据永远不知道左边的数据是什么。(看得懂吗?)

此处反思。。。




上面两种魔法机器每次运作都需要消耗一样东西。要么私钥要么公钥,并且两个成对使用。也就是说黑科技魔法工具使用私钥,那么反黑科技魔法工具就使用公钥。反之亦然。


现在的问题是,假设默认情况下是这样的:

黑科技魔法工具只能用私钥加密,反黑科技工具只能用公钥解密。如果某一天,有人一不小心给了黑科技魔法工具公钥,然后想投机取巧,给反黑科技魔法工具喂私钥。还能够解出数据吗?


先看代码:

首先是私钥加密公钥解密

1.16自己写的进制工具

package utils;import java.io.UnsupportedEncodingException;/** *  * @author qq1623299667 * */public class HexUtil {/** * 将任何字符串按指定编码输出成特定格式的16进制 * @param string * @param charsetName * @return */public static String stringToHexString(String string,String charsetName) {StringBuilder sb = new StringBuilder();try {for (int i = 0; i < string.length(); i++) {char ch = string.charAt(i);byte[] bytes = String.valueOf(ch).getBytes(charsetName);String hex = bytesToHexString(bytes);sb.append(hex);}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return sb.toString();}/** * 将字节码数组按16进制的方式保存为字符串 * @param bytes * @return */public static String bytesToHexString(byte[] bytes){      StringBuilder sb = new StringBuilder();      for (int i = 0; i < bytes.length; i++) {          int num = bytes[i] & 0xFF;          String hex = Integer.toHexString(num);        if (hex.length() < 2) {              sb.append(0);          }          sb.append(hex);     }  return sb.toString();}/** * 将16进制的字符串转换成byte * @param hexString * @return */public static byte[] hexStringTobytes(String hexString){StringBuilder sb = new StringBuilder();for(int i=0;i<hexString.length()/2;i++){sb.append(hexString.substring(2*i,2*i+2));}hexString = sb.toString();byte[] bytes = new byte[hexString.length()/2];for(int i=0;i<hexString.length()/2;i++){bytes[i] = (byte)(0xff & Integer.parseInt(hexString.substring(2*i, 2*i+2), 16));}return bytes;}/** * 将16进制的字符串转换成string * @param hexString * @return */public static String hexStringToString(String hexString,String charsetName){try {return new String(hexStringTobytes(hexString),charsetName);} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}/** * 将16进制字符串按特定格式格式化 * @param hexString * @return */public static String hexStringFormat(String hexString){StringBuilder sb = new StringBuilder();sb.append("\r\n");for(int i=0;i<hexString.length()/2;i++){sb.append(hexString.substring(2*i, 2*i+2).toUpperCase());sb.append(" ");if(i%16==15){sb.append("\r\n");}}return sb.toString();}}

2.加解密类

package privatekeyencryprsa;import java.security.InvalidKeyException;  import java.security.NoSuchAlgorithmException;  import java.security.interfaces.RSAPrivateKey;  import java.security.interfaces.RSAPublicKey;    import javax.crypto.BadPaddingException;  import javax.crypto.Cipher;  import javax.crypto.IllegalBlockSizeException;  import javax.crypto.NoSuchPaddingException;    public class EncrypRSA {            /**      * 加密      * @param RSAPrivateKey      * @param srcBytes      * @return      * @throws NoSuchAlgorithmException      * @throws NoSuchPaddingException      * @throws InvalidKeyException      * @throws IllegalBlockSizeException      * @throws BadPaddingException      */      protected byte[] encrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{          if(privateKey!=null){              //Cipher负责完成加密或解密工作,基于RSA              Cipher cipher = Cipher.getInstance("RSA");              //根据公钥,对Cipher对象进行初始化              cipher.init(Cipher.ENCRYPT_MODE, privateKey);              byte[] resultBytes = cipher.doFinal(srcBytes);              return resultBytes;          }          return null;      }          /**      * 解密       * @param RSAPublicKey      * @param srcBytes      * @return      * @throws NoSuchAlgorithmException      * @throws NoSuchPaddingException      * @throws InvalidKeyException      * @throws IllegalBlockSizeException      * @throws BadPaddingException      */      protected byte[] decrypt(RSAPublicKey publicKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{          if(publicKey!=null){              //Cipher负责完成加密或解密工作,基于RSA              Cipher cipher = Cipher.getInstance("RSA");              //根据公钥,对Cipher对象进行初始化              cipher.init(Cipher.DECRYPT_MODE, publicKey);              byte[] resultBytes = cipher.doFinal(srcBytes);              return resultBytes;          }          return null;      }          } 

3.测试类

package privatekeyencryprsa;import java.security.InvalidKeyException;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import javax.crypto.BadPaddingException;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import utils.HexUtil;public class TestRSA {/**      * @param args      * @throws NoSuchAlgorithmException       * @throws BadPaddingException       * @throws IllegalBlockSizeException       * @throws NoSuchPaddingException       * @throws InvalidKeyException       */      public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {          EncrypRSA rsa = new EncrypRSA();          String msg = "可怜的测试工具";          //KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象          KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");          //初始化密钥对生成器,密钥大小为1024位          keyPairGen.initialize(1024);          //生成一个密钥对,保存在keyPair中          KeyPair keyPair = keyPairGen.generateKeyPair();          //得到私钥          RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();                       //得到公钥          RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();                    //用私钥加密          byte[] srcBytes = msg.getBytes();          byte[] resultBytes = rsa.encrypt(privateKey, srcBytes);                    //用公钥解密          byte[] decBytes = rsa.decrypt(publicKey, resultBytes);                    System.out.println("明文是:" + msg);          System.out.println("加密后是:" + new String(resultBytes));          System.out.println("加密后16进制是:" + HexUtil.hexStringFormat(HexUtil.bytesToHexString(resultBytes)));          System.out.println("解密后是:" + new String(decBytes));      }  }

4.测试结果

明文是:可怜的测试工具加密后是:?�k�����/��K�A�������jBk:����m���L0�N/�e'�}_��=���.&�*��r*_5����@��=���d����>�G��^���!��6*le�Y�w�2�Dr&�Oz�O�Y8�:��1加密后16进制是:3F 94 6B 95 8F F2 EB F1 2F F0 88 4B DF 41 CA 11 ED 28 08 AF FD FE 99 F2 6A 42 6B 3A C8 C4 D0 D6 6D 8A 83 96 4C 30 81 4E 2F E6 65 27 AD 7D 5F B1 8A 3D AF 89 B4 2E 26 F9 0B 2A BC A4 72 2A 5F 35 EF 89 F6 A4 E9 40 E5 17 C5 3D B4 81 17 EB 64 CA D1 01 A1 B6 3E F2 47 B8 C1 5E AB AC F7 21 D7 EE BD 36 2A 6C 65 F6 59 A5 77 EB 32 87 14 44 72 26 C3 4F 7A 14 9F 4F C5 59 38 81 3A B0 07 B8 15 31 解密后是:可怜的测试工具

然后是公钥加密私钥解密

1.加解密类

package publickeyencryprsa;import java.security.InvalidKeyException;  import java.security.KeyPair;  import java.security.KeyPairGenerator;  import java.security.NoSuchAlgorithmException;  import java.security.interfaces.RSAPrivateKey;  import java.security.interfaces.RSAPublicKey;    import javax.crypto.BadPaddingException;  import javax.crypto.Cipher;  import javax.crypto.IllegalBlockSizeException;  import javax.crypto.NoSuchPaddingException;    public class EncrypRSA {            /**      * 加密      * @param publicKey      * @param srcBytes      * @return      * @throws NoSuchAlgorithmException      * @throws NoSuchPaddingException      * @throws InvalidKeyException      * @throws IllegalBlockSizeException      * @throws BadPaddingException      */      protected byte[] encrypt(RSAPublicKey publicKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{          if(publicKey!=null){              //Cipher负责完成加密或解密工作,基于RSA              Cipher cipher = Cipher.getInstance("RSA");              //根据公钥,对Cipher对象进行初始化              cipher.init(Cipher.ENCRYPT_MODE, publicKey);              byte[] resultBytes = cipher.doFinal(srcBytes);              return resultBytes;          }          return null;      }            /**      * 解密       * @param privateKey      * @param srcBytes      * @return      * @throws NoSuchAlgorithmException      * @throws NoSuchPaddingException      * @throws InvalidKeyException      * @throws IllegalBlockSizeException      * @throws BadPaddingException      */      protected byte[] decrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{          if(privateKey!=null){              //Cipher负责完成加密或解密工作,基于RSA              Cipher cipher = Cipher.getInstance("RSA");              //根据公钥,对Cipher对象进行初始化              cipher.init(Cipher.DECRYPT_MODE, privateKey);              byte[] resultBytes = cipher.doFinal(srcBytes);              return resultBytes;          }          return null;      }          } 

2.测试类

package publickeyencryprsa;import java.security.InvalidKeyException;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import javax.crypto.BadPaddingException;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import utils.HexUtil;public class TestRSA {/**      * @param args      * @throws NoSuchAlgorithmException       * @throws BadPaddingException       * @throws IllegalBlockSizeException       * @throws NoSuchPaddingException       * @throws InvalidKeyException       */      public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {          EncrypRSA rsa = new EncrypRSA();          String msg = "可怜的测试工具";          //KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象          KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");          //初始化密钥对生成器,密钥大小为1024位          keyPairGen.initialize(1024);          //生成一个密钥对,保存在keyPair中          KeyPair keyPair = keyPairGen.generateKeyPair();          //得到私钥          RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();                       //得到公钥          RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();                    //用公钥加密          byte[] srcBytes = msg.getBytes();          byte[] resultBytes = rsa.encrypt(publicKey, srcBytes);                    //用私钥解密          byte[] decBytes = rsa.decrypt(privateKey, resultBytes);                    System.out.println("明文是:" + msg);          System.out.println("加密后是:" + new String(resultBytes));          System.out.println("加密后16进制是:" + HexUtil.hexStringFormat(HexUtil.bytesToHexString(resultBytes)));          System.out.println("解密后是:" + new String(decBytes));      }  }

3.测试结果

明文是:可怜的测试工具1�'jC1y��`=N�G|���P�98o���������s1bb                                  �b�O������n�C�^\�����ǹ�加密后16进制是:7E 5B 75 D2 19 20 EC 2C 5E 7E 86 4B 47 63 29 56 7C 66 F1 78 C0 2E B2 D9 D2 93 73 81 F8 E4 91 95 9E E4 E9 73 0F 31 14 62 7F 62 0D 31 D5 27 6A 43 31 79 D8 DB 60 3D 4E F8 47 7C FC 01 9F FA 50 BD 39 38 0E 6F 88 E1 06 ED 1B F1 ED B5 7F ED 0C E7 16 62 ED 4F DB E9 17 0A 90 A2 BE 0E F3 6E 87 43 E6 5E 5C BB FE 81 A0 E1 B3 7F C7 B9 05 E0 00 E6 3C F2 0C D6 54 6F 48 D0 AD B8 06 BB 39 8D DE CF 解密后是:可怜的测试工具

可以看到,即使有个粗心的小伙子弄错了该给黑科技魔法工具喂什么钥,他还是可以通过反黑科技魔法工具机智的找到原来的数据。

但是,他会发现不同,就是加密后的数据发生了更改。


例子就到这里,我们已经知道不论是公钥加密还是私钥加密。我们都可以从密文得到相应的明文。

我们现在需要反思的一件事就是:什么时候用私钥加密什么时候用公钥加密?


以下是我的一点见解,可能理解有错,请各位看官抱着只讨论不打脸的态度审视:

那种秘钥加密取决于具体的业务场景:

公钥加密类:收费软件的数据签名

私钥加密类:服务器给手机的通讯加密,比特币持有者数据签名









阅读全文
0 0