• java与IOS之间的RSA加解密


        很简单的一个需求,ipad端给密码RSA加密,传到java后台,解密。RSA加密算法是基于一个密钥对的,分为公钥和私钥,一般情况公钥加密,私钥解密,但也可私钥加密,公钥解密。还可以验签,就是先用私钥对数据进行加密,然后对加密后的数据进行签名,得到一个签名值。然后再用公钥先验签,证明是对应私钥加密过的数据才解密。主要是为了防止来源不确定的数据。 
        根据上面的介绍,大家也都知道,RSA算法的关键就是密钥对,我和IOS的同事各自找了RSA的算法实现代码,都能正常根据密钥对加解密。问题是我们各自使用对方的密钥对就不能加解密成功。IOS同事也是一个新手。连RSA算法是个什么概念都没搞清楚,我也懂点IOS。所以就陪着他一起看代码,找资料。看到底什么原因引起的密钥对不能共用。后来找到下面这篇文章: 
    Java中使用OpenSSL生成的RSA公私钥进行数据加解密 

    原来在用mac 系统中自带的openssl生成的密钥对文件是X509编码格式的。而我们JAVA所需的私钥文件是PKCS#8编码格式的。。所以要将在mac 系统中生成的私钥文件转下码就行了。转码方式参考上面链接。附下java代码: 

    Java代码  收藏代码
    1. import java.io.BufferedReader;  
    2. import java.io.IOException;  
    3. import java.io.InputStream;  
    4. import java.io.InputStreamReader;  
    5. import java.security.InvalidKeyException;  
    6. import java.security.KeyFactory;  
    7. import java.security.KeyPair;  
    8. import java.security.KeyPairGenerator;  
    9. import java.security.NoSuchAlgorithmException;  
    10. import java.security.SecureRandom;  
    11. import java.security.interfaces.RSAPrivateKey;  
    12. import java.security.interfaces.RSAPublicKey;  
    13. import java.security.spec.InvalidKeySpecException;  
    14. import java.security.spec.PKCS8EncodedKeySpec;  
    15. import java.security.spec.X509EncodedKeySpec;  
    16.   
    17. import javax.crypto.BadPaddingException;  
    18. import javax.crypto.Cipher;  
    19. import javax.crypto.IllegalBlockSizeException;  
    20. import javax.crypto.NoSuchPaddingException;  
    21.   
    22. import sun.misc.BASE64Decoder;  
    23. import sun.misc.BASE64Encoder;  
    24.   
    25. public class RSAEncrypt {  
    26.     private static final String DEFAULT_PUBLIC_KEY=     
    27.         "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChDzcjw/rWgFwnxunbKp7/4e8w" + " " +    
    28.         "/UmXx2jk6qEEn69t6N2R1i/LmcyDT1xr/T2AHGOiXNQ5V8W4iCaaeNawi7aJaRht" + " " +    
    29.         "Vx1uOH/2U378fscEESEG8XDqll0GCfB1/TjKI2aitVSzXOtRs8kYgGU78f7VmDNg" + " " +    
    30.         "XIlk3gdhnzh+uoEQywIDAQAB" + " ";    
    31.         
    32.     private static final String DEFAULT_PRIVATE_KEY=    
    33.         "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKEPNyPD+taAXCfG" + " " +    
    34.         "6dsqnv/h7zD9SZfHaOTqoQSfr23o3ZHWL8uZzINPXGv9PYAcY6Jc1DlXxbiIJpp4" + " " +    
    35.         "1rCLtolpGG1XHW44f/ZTfvx+xwQRIQbxcOqWXQYJ8HX9OMojZqK1VLNc61GzyRiA" + " " +    
    36.         "ZTvx/tWYM2BciWTeB2GfOH66gRDLAgMBAAECgYBp4qTvoJKynuT3SbDJY/XwaEtm" + " " +    
    37.         "u768SF9P0GlXrtwYuDWjAVue0VhBI9WxMWZTaVafkcP8hxX4QZqPh84td0zjcq3j" + " " +    
    38.         "DLOegAFJkIorGzq5FyK7ydBoU1TLjFV459c8dTZMTu+LgsOTD11/V/Jr4NJxIudo" + " " +    
    39.         "MBQ3c4cHmOoYv4uzkQJBANR+7Fc3e6oZgqTOesqPSPqljbsdF9E4x4eDFuOecCkJ" + " " +    
    40.         "DvVLOOoAzvtHfAiUp+H3fk4hXRpALiNBEHiIdhIuX2UCQQDCCHiPHFd4gC58yyCM" + " " +    
    41.         "6Leqkmoa+6YpfRb3oxykLBXcWx7DtbX+ayKy5OQmnkEG+MW8XB8wAdiUl0/tb6cQ" + " " +    
    42.         "FaRvAkBhvP94Hk0DMDinFVHlWYJ3xy4pongSA8vCyMj+aSGtvjzjFnZXK4gIjBjA" + " " +    
    43.         "2Z9ekDfIOBBawqp2DLdGuX2VXz8BAkByMuIh+KBSv76cnEDwLhfLQJlKgEnvqTvX" + " " +    
    44.         "TB0TUw8avlaBAXW34/5sI+NUB1hmbgyTK/T/IFcEPXpBWLGO+e3pAkAGWLpnH0Zh" + " " +    
    45.         "Fae7oAqkMAd3xCNY6ec180tAe57hZ6kS+SYLKwb4gGzYaCxc22vMtYksXHtUeamo" + " " +    
    46.         "1NMLzI2ZfUoX" + " ";    
    47.     
    48.     /**  
    49.      * 私钥  
    50.      */    
    51.     private RSAPrivateKey privateKey;    
    52.     
    53.     /**  
    54.      * 公钥  
    55.      */    
    56.     private RSAPublicKey publicKey;    
    57.         
    58.     /**  
    59.      * 字节数据转字符串专用集合  
    60.      */    
    61.     private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};    
    62.         
    63.     
    64.     /**  
    65.      * 获取私钥  
    66.      * @return 当前的私钥对象  
    67.      */    
    68.     public RSAPrivateKey getPrivateKey() {    
    69.         return privateKey;    
    70.     }    
    71.     
    72.     /**  
    73.      * 获取公钥  
    74.      * @return 当前的公钥对象  
    75.      */    
    76.     public RSAPublicKey getPublicKey() {    
    77.         return publicKey;    
    78.     }    
    79.     
    80.     /**  
    81.      * 随机生成密钥对  
    82.      */    
    83.     public void genKeyPair(){    
    84.         KeyPairGenerator keyPairGen= null;    
    85.         try {    
    86.             keyPairGen= KeyPairGenerator.getInstance("RSA");    
    87.         } catch (NoSuchAlgorithmException e) {    
    88.             e.printStackTrace();    
    89.         }    
    90.         keyPairGen.initialize(1024, new SecureRandom());    
    91.         KeyPair keyPair= keyPairGen.generateKeyPair();    
    92.         this.privateKey= (RSAPrivateKey) keyPair.getPrivate();    
    93.         this.publicKey= (RSAPublicKey) keyPair.getPublic();    
    94.     }    
    95.     
    96.     /**  
    97.      * 从文件中输入流中加载公钥  
    98.      * @param in 公钥输入流  
    99.      * @throws Exception 加载公钥时产生的异常  
    100.      */    
    101.     public void loadPublicKey(InputStream in) throws Exception{    
    102.         try {    
    103.             BufferedReader br= new BufferedReader(new InputStreamReader(in));    
    104.             String readLine= null;    
    105.             StringBuilder sb= new StringBuilder();    
    106.             while((readLine= br.readLine())!=null){    
    107.                 if(readLine.charAt(0)=='-'){    
    108.                     continue;    
    109.                 }else{    
    110.                     sb.append(readLine);    
    111.                     sb.append(' ');    
    112.                 }    
    113.             }    
    114.             loadPublicKey(sb.toString());    
    115.         } catch (IOException e) {    
    116.             throw new Exception("公钥数据流读取错误");    
    117.         } catch (NullPointerException e) {    
    118.             throw new Exception("公钥输入流为空");    
    119.         }    
    120.     }    
    121.     
    122.     
    123.     /**  
    124.      * 从字符串中加载公钥  
    125.      * @param publicKeyStr 公钥数据字符串  
    126.      * @throws Exception 加载公钥时产生的异常  
    127.      */    
    128.     public void loadPublicKey(String publicKeyStr) throws Exception{    
    129.         try {    
    130.             BASE64Decoder base64Decoder= new BASE64Decoder();    
    131.             byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);  
    132.             KeyFactory keyFactory= KeyFactory.getInstance("RSA");    
    133.             X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);    
    134.             this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec);    
    135.         } catch (NoSuchAlgorithmException e) {    
    136.             throw new Exception("无此算法");    
    137.         } catch (InvalidKeySpecException e) {    
    138.             throw new Exception("公钥非法");    
    139.         } catch (IOException e) {    
    140.             throw new Exception("公钥数据内容读取错误");    
    141.         } catch (NullPointerException e) {    
    142.             throw new Exception("公钥数据为空");    
    143.         }    
    144.     }    
    145.     
    146.     /**  
    147.      * 从文件中加载私钥  
    148.      * @param keyFileName 私钥文件名  
    149.      * @return 是否成功  
    150.      * @throws Exception   
    151.      */    
    152.     public void loadPrivateKey(InputStream in) throws Exception{    
    153.         try {    
    154.             BufferedReader br= new BufferedReader(new InputStreamReader(in));    
    155.             String readLine= null;    
    156.             StringBuilder sb= new StringBuilder();    
    157.             while((readLine= br.readLine())!=null){    
    158.                 if(readLine.charAt(0)=='-'){    
    159.                     continue;    
    160.                 }else{    
    161.                     sb.append(readLine);    
    162.                     sb.append(' ');    
    163.                 }    
    164.             }    
    165.             loadPrivateKey(sb.toString());    
    166.         } catch (IOException e) {    
    167.             throw new Exception("私钥数据读取错误");    
    168.         } catch (NullPointerException e) {    
    169.             throw new Exception("私钥输入流为空");    
    170.         }    
    171.     }    
    172.     
    173.     public void loadPrivateKey(String privateKeyStr) throws Exception{    
    174.         try {    
    175.             BASE64Decoder base64Decoder= new BASE64Decoder();    
    176.             byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);    
    177.             PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);    
    178.             KeyFactory keyFactory= KeyFactory.getInstance("RSA");    
    179.             this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);    
    180.         } catch (NoSuchAlgorithmException e) {    
    181.             throw new Exception("无此算法");    
    182.         } catch (InvalidKeySpecException e) {    
    183.             e.printStackTrace();  
    184.             throw new Exception("私钥非法");    
    185.         } catch (IOException e) {    
    186.             throw new Exception("私钥数据内容读取错误");    
    187.         } catch (NullPointerException e) {    
    188.             throw new Exception("私钥数据为空");    
    189.         }    
    190.     }    
    191.     
    192.     /**  
    193.      * 加密过程  
    194.      * @param publicKey 公钥  
    195.      * @param plainTextData 明文数据  
    196.      * @return  
    197.      * @throws Exception 加密过程中的异常信息  
    198.      */    
    199.     public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{    
    200.         if(publicKey== null){    
    201.             throw new Exception("加密公钥为空, 请设置");    
    202.         }    
    203.         Cipher cipher= null;    
    204.         try {    
    205.             cipher= Cipher.getInstance("RSA");//, new BouncyCastleProvider());    
    206.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);    
    207.             byte[] output= cipher.doFinal(plainTextData);    
    208.             return output;    
    209.         } catch (NoSuchAlgorithmException e) {    
    210.             throw new Exception("无此加密算法");    
    211.         } catch (NoSuchPaddingException e) {    
    212.             e.printStackTrace();    
    213.             return null;    
    214.         }catch (InvalidKeyException e) {    
    215.             throw new Exception("加密公钥非法,请检查");    
    216.         } catch (IllegalBlockSizeException e) {    
    217.             throw new Exception("明文长度非法");    
    218.         } catch (BadPaddingException e) {    
    219.             throw new Exception("明文数据已损坏");    
    220.         }    
    221.     }    
    222.     
    223.     /**  
    224.      * 解密过程  
    225.      * @param privateKey 私钥  
    226.      * @param cipherData 密文数据  
    227.      * @return 明文  
    228.      * @throws Exception 解密过程中的异常信息  
    229.      */    
    230.     public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{    
    231.         if (privateKey== null){    
    232.             throw new Exception("解密私钥为空, 请设置");    
    233.         }    
    234.         Cipher cipher= null;    
    235.         try {    
    236.             cipher= Cipher.getInstance("RSA");//, new BouncyCastleProvider());    
    237.             cipher.init(Cipher.DECRYPT_MODE, privateKey);    
    238.             byte[] output= cipher.doFinal(cipherData);    
    239.             return output;    
    240.         } catch (NoSuchAlgorithmException e) {    
    241.             throw new Exception("无此解密算法");    
    242.         } catch (NoSuchPaddingException e) {    
    243.             e.printStackTrace();    
    244.             return null;    
    245.         }catch (InvalidKeyException e) {    
    246.             throw new Exception("解密私钥非法,请检查");    
    247.         } catch (IllegalBlockSizeException e) {    
    248.             throw new Exception("密文长度非法");    
    249.         } catch (BadPaddingException e) {    
    250.             throw new Exception("密文数据已损坏");    
    251.         }           
    252.     }    
    253.     
    254.         
    255.     /**  
    256.      * 字节数据转十六进制字符串  
    257.      * @param data 输入数据  
    258.      * @return 十六进制内容  
    259.      */    
    260.     public static String byteArrayToString(byte[] data){    
    261.         StringBuilder stringBuilder= new StringBuilder();    
    262.         for (int i=0; i<data.length; i++){    
    263.             //取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移    
    264.             stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);    
    265.             //取出字节的低四位 作为索引得到相应的十六进制标识符    
    266.             stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);    
    267.             if (i<data.length-1){    
    268.                 stringBuilder.append(' ');    
    269.             }    
    270.         }    
    271.         return stringBuilder.toString();    
    272.     }    
    273.     
    274.     
    275.     public static void main(String[] args){    
    276.         RSAEncrypt rsaEncrypt= new RSAEncrypt();    
    277.         //rsaEncrypt.genKeyPair();    
    278.          
    279.     
    280.         //加载公钥    
    281.         try {    
    282.             rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);    
    283.             System.out.println("加载公钥成功");    
    284.         } catch (Exception e) {    
    285.             System.err.println(e.getMessage());    
    286.             System.err.println("加载公钥失败");    
    287.         }    
    288.     
    289.         //加载私钥    
    290.         try {    
    291.             rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY);    
    292.             System.out.println("加载私钥成功");    
    293.         } catch (Exception e) {    
    294.             System.err.println(e.getMessage());    
    295.             System.err.println("加载私钥失败");    
    296.         }    
    297.     
    298.         //测试字符串    
    299.         String encryptStr= "abc";    
    300.         System.out.println("私钥长度:"+rsaEncrypt.getPrivateKey().toString().length());  
    301.         System.out.println("公钥长度:"+rsaEncrypt.getPublicKey().toString().length());  
    302.         try {    
    303.             //加密    
    304.             byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes());    
    305.               
    306.              
    307.             //解密    
    308.             byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher);    
    309.   
    310.               
    311.              
    312.             System.out.println("密文长度:"+ cipher.length);    
    313.             System.out.println(RSAEncrypt.byteArrayToString(cipher));    
    314.             System.out.println("明文长度:"+ plainText.length);    
    315.             System.out.println(RSAEncrypt.byteArrayToString(plainText));    
    316.             System.out.println(new String(plainText));    
    317.         } catch (Exception e) {    
    318.             System.err.println(e.getMessage());    
    319.         }    
    320.     }  
    321. }  



    提供两种方式加载密钥对,可通过字符串或者文件流,文件是指生成的.pem文件才可以哦。 
    另外附一份IOS中加密方法,不过这里要求的文件是der。 
    http://blog.yorkgu.me/2011/10/27/rsa-in-ios-using-publick-key-generated-by-openssl/ IOS中加密后返回的NSdata对象,可以对NSdata对象进行base64编码转换成字符串,然后java用BASE64Decoder解码之后,就转换成了byte[],可直接用上面方法解密。。。

  • 相关阅读:
    TCP 连接中的TIME_WAIT
    tcp 重组原理
    自己用wireshark 抓了个包,分析了一下
    wireshark 使用技巧
    IP 网际协议
    CSS3 选择器
    ajax 底层源码解析
    初识 Java
    jQuery (DOM篇)
    绘制 SVG
  • 原文地址:https://www.cnblogs.com/sunnyke/p/4613097.html
Copyright © 2020-2023  润新知