zoukankan      html  css  js  c++  java
  • IOS, Android, Java Web Rest : RSA 加密和解密问题

    IOS, Android, Java Web Rest :  RSA 加密和解密问题

    一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了.

    注意:

    1. 公钥私钥是BASE64编码的,私钥需要转换成PKCS8格式;

    2. 密文是字节数组,可以转化为BASE64编码字符串或16进制字符串。

    3.JAVA,Android RSA 加密默认是"RSA/None/NoPadding", IOS需要调用方法进行设置。

    (1)IOS RSA 加密算法,

    https://github.com/ideawu/Objective-C-RSA

    加密模式是"RSA/None/NoPadding", IOS需要调用方法进行设置。

    (2)Android, Java , RSA加密:

    下面是Java代码 (公钥私钥需要替换成你自己的,否则不工作!)

    加密默认是"RSA/None/NoPadding"

    package com.jcfax.app.utils;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.security.InvalidKeyException;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.security.Security;  
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    import sun.misc.BASE64Decoder;//将base64转换为byte[]
    import sun.misc.BASE64Encoder;//转byet[]换为base64
    
    import java.net.URLEncoder;
    import java.net.URLDecoder;
    import java.io.UnsupportedEncodingException;
    
    
    //================================================================================
    public class RSAEncrypt {
    	
    	/** 指定加密算法为RSA */
    	private static String ALGORITHM = "RSA";
    	/** 指定key的大小 */
    	private static int KEYSIZE = 1024;
    		
    	//String source_text= "Hello,World!"; 
    	//RSA Public key
    	private static final String DEFAULT_PUBLIC_KEY= 
    		"MIGfMA0GCSqGSIb3DwQEBAQUAA4GNADCBiQKBgQDSS5owhX3tsB5tCuVuJMZrmMrq" + "
    " +
    		"KmctKjAUOdBAFO2i5VvJzVTwwCxY3XJ2L9pAZZDKorpxCrkQ7b6sA+93lxJ6TABtq" + "
    " +
    		"kRaGaEJEE2GclgkkdCesozecGkDXitPQ/Y1i+HKVxnNxv9E/a/ChvfGn50DKIW1S" + "
    " +
    		"Pzna8iFwgEq1QcUrrfwIDAQAB" + "
    ";
    	
    	//RSA  Private Key (PKCS8 格式)
    	private static final String DEFAULT_PRIVATE_KEY=		
    		"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANJLmjCFfe2wHm0K" + "
    " +
    		"5W4kxmuYyuoqZy0qMBQ50EAU7aLlW8nNVPALFjdcnYv2kBlkMqiunEKuRDtvqwD7" + "
    " +
    		"3eXEnpMAG2qRFoZoQkQTYZyWCSR0J6yjN5waQNeK09D9jWL4cpXGc3G/0T9r8KG9" + "
    " +
    		"8afnQMohbVI/OdryIWASrVBxSut/AgMBAAECgYEAj7qMT81tHB7bLLvdw0HvO2ra" + "
    " +
    		"hOEmU4AaDDjXVHT5VfRcn7hu7QEm1f++zgJeynvpA9ETi59/kv/naGy8ZGXV2nRG" + "
    " +
    		"cWK0U5+6DgT7oOeG6KlZie3Hw/KHPlKnwW3FoXRIh4bSGcxx6pxyrxCwQYKzM4Yc" + "
    " +
    		"VetYXBS6gnZbuj8D8YECQQD8+dl0rG2Xm/Khn0M69g3rStL4QAaLXGOcB0uiDl+J" + "
    " +
    		"trpw3D1fDN/yFrrE0VzxzvXxalGzVn4NOP/PZckvjUZ3AkEA1M8kg3xlPWQURfKZ" + "
    " +
    		"KpBphPa13v1V2ot43Ce2wHTwpxXU9Uj5cwlz/+Jv5VZSwiYNCXwPkv79Kh8d14nMZ" + "
    " +
    		"L+tdOQJBANrZav48jTKzftvDY+4GH1SGjqyk9wRpEONSjGPN+2iv4+rvHUi1YqeU" + "
    " +
    		"ck8CsF2gpbQMPlHfaX0W6ncJn1q75VECQCB84xEjq3z8y0+GYrWpyEIhO9CoEjRD" + "
    " +
    		"+JZ7hZ3J+2pGpK7qkFSnx/gXL7BN+8lyfW5t9L0FIgaqf6erdJvpLZkCQEmc2Ml2" + "
    " +
    		"bgTq5sWFr+KsI+yWxUgP76M4JP7u8/XeH7a16nJSj/D6xSpkYz9bYkOI2Ulh3wbE" + "
    " +
    		"sLxepdwmlvm3kSIY=" + "
    ";		
    
    	/**
    	 * 私钥
    	 */
    	private RSAPrivateKey privateKey;
    
    	/**
    	 * 公钥
    	 */
    	private RSAPublicKey publicKey;
    	
    	/**
    	 * 字节数据转字符串专用集合
    	 */
    	private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    	
    
    	/**
    	 * 获取私钥
    	 * @return 当前的私钥对象
    	 */
    	public RSAPrivateKey getPrivateKey() {
    		return privateKey;
    	}
    
    	/**
    	 * 获取公钥
    	 * @return 当前的公钥对象
    	 */
    	public RSAPublicKey getPublicKey() {
    		return publicKey;
    	}
    
    	/**
    	 * 随机生成密钥对:1024位密钥
    	 */
    	public void genKeyPair(){
    		KeyPairGenerator keyPairGen= null;
    		try {
    			keyPairGen= KeyPairGenerator.getInstance(ALGORITHM);
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}
    		keyPairGen.initialize(KEYSIZE, new SecureRandom());
    		KeyPair keyPair= keyPairGen.generateKeyPair();
    		this.privateKey= (RSAPrivateKey) keyPair.getPrivate();
    		this.publicKey= (RSAPublicKey) keyPair.getPublic();
    	}
    
    	/**
    	 * 从文件中输入流中加载公钥
    	 * @param in 公钥输入流
    	 * @throws Exception 加载公钥时产生的异常
    	 */
    	public void loadPublicKey(InputStream in) throws Exception{
    		try {
    			BufferedReader br= new BufferedReader(new InputStreamReader(in));
    			String readLine= null;
    			StringBuilder sb= new StringBuilder();
    			while((readLine= br.readLine())!=null){
    				if(readLine.charAt(0)=='-'){
    					continue;
    				}else{
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			loadPublicKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("公钥数据流读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("公钥输入流为空");
    		}
    	}
    
    
    	/**
    	 * 从字符串中加载公钥
    	 * @param publicKeyStr 公钥数据字符串
    	 * @throws Exception 加载公钥时产生的异常
    	 */
    	public void loadPublicKey(String publicKeyStr) throws Exception{
    		//System.out.println("==print publicKeyStr==");
    		//System.out.println(publicKeyStr);
    		
    		try {
    			BASE64Decoder base64Decoder= new BASE64Decoder();
    			byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);			
    			//System.out.println(new String(buffer)); 			
    			KeyFactory keyFactory= KeyFactory.getInstance(ALGORITHM);
    			X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);
    			this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("公钥非法");
    		} catch (IOException e) {
    			throw new Exception("公钥数据内容读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("公钥数据为空");
    		}
    	}
    
    	/**
    	 * 从文件中加载私钥
    	 * @param keyFileName 私钥文件名
    	 * @return 是否成功
    	 * @throws Exception 
    	 */
    	public void loadPrivateKey(InputStream in) throws Exception{
    		try {
    			BufferedReader br= new BufferedReader(new InputStreamReader(in));
    			String readLine= null;
    			StringBuilder sb= new StringBuilder();
    			while((readLine= br.readLine())!=null){
    				if(readLine.charAt(0)=='-'){
    					continue;
    				}else{
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			loadPrivateKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("私钥数据读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("私钥输入流为空");
    		}
    	}
    
    	public void loadPrivateKey(String privateKeyStr) throws Exception{
    		//System.out.println("==print privateKeyStr==");
    		//System.out.println(privateKeyStr);
    		
    		try {
    			BASE64Decoder base64Decoder= new BASE64Decoder();
    			byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
    			//System.out.println(new String(buffer)); 
    			PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);
    			KeyFactory keyFactory= KeyFactory.getInstance(ALGORITHM);
    			this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("私钥非法");
    		} catch (IOException e) {
    			throw new Exception("私钥数据内容读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("私钥数据为空");
    		}
    	}
    
    	/**
    	 * 加密过程
    	 * @param publicKey 公钥
    	 * @param plainTextData 明文数据
    	 * @return
    	 * @throws Exception 加密过程中的异常信息
    	 */
    	public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{
    		if(publicKey== null){
    			throw new Exception("加密公钥为空, 请设置");
    		}
    		Cipher cipher= null;
    		try {
    			cipher= Cipher.getInstance(ALGORITHM, new BouncyCastleProvider());
    			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    			byte[] output= cipher.doFinal(plainTextData);
    			return output;
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此加密算法");
    		} catch (NoSuchPaddingException e) {
    			e.printStackTrace();
    			return null;
    		}catch (InvalidKeyException e) {
    			throw new Exception("加密公钥非法,请检查");
    		} catch (IllegalBlockSizeException e) {
    			throw new Exception("明文长度非法");
    		} catch (BadPaddingException e) {
    			throw new Exception("明文数据已损坏");
    		}
    	}
    
    	/**
    	 * 解密过程
    	 * @param privateKey 私钥
    	 * @param cipherData 密文数据
    	 * @return 明文
    	 * @throws Exception 解密过程中的异常信息
    	 */
    	public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{
    		if (privateKey== null){
    			throw new Exception("解密私钥为空, 请设置");
    		}
    		Cipher cipher= null;
    		try {
    			cipher= Cipher.getInstance(ALGORITHM, new BouncyCastleProvider());
    			cipher.init(Cipher.DECRYPT_MODE, privateKey);
    			
    			//Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());  
                //final Cipher cipher = Cipher.getInstance(PADDING, PROVIDER);  
                
    			byte[] output= cipher.doFinal(cipherData);
    			return output;
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此解密算法");
    		} catch (NoSuchPaddingException e) {
    			e.printStackTrace();
    			return null;
    		}catch (InvalidKeyException e) {
    			throw new Exception("解密私钥非法,请检查");
    		} catch (IllegalBlockSizeException e) {
    			throw new Exception("密文长度非法");
    		} catch (BadPaddingException e) {
    			throw new Exception("密文数据已损坏");
    		}		
    	}
    
    	
    	/**
    	 * 字节数据转十六进制字符串
    	 * @param data 输入数据
    	 * @return 十六进制内容
    	 */
    	public static String byteArrayToString(byte[] data){
    		
    		//char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    		StringBuilder stringBuilder= new StringBuilder();
    		for (int i=0; i<data.length; i++){
    			//取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
    			stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);
    			//取出字节的低四位 作为索引得到相应的十六进制标识符
    			stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
    //			if (i<data.length-1){
    //				stringBuilder.append(' ');
    //			}
    		}
    		return stringBuilder.toString();
    	}
    
    	private static byte toByte(char c) {   
    	    byte b = (byte) "0123456789abcdef".indexOf(c);   
    	    return b;   
    	}  
        /**
    	* 把16进制字符串转换成字节数组  
        * @param hex  
        * @return  
        */  
        
    	public static byte[] hexStringToByte(String hex) {   
    	    int len = (hex.length() / 2);   
    	    byte[] result = new byte[len];   
    	    char[] achar = hex.toCharArray();   
    	    for (int i = 0; i < len; i++) {   
    	     int pos = i * 2;   
    	     result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));   
    	    }   
    	    return result;   
    	}  
    	
    	
       //===================================================================
    	//测试用例
    	public static void main(String[] args) {
    		
    		RSAEncrypt rsaEncrypt= new RSAEncrypt();
    		//rsaEncrypt.genKeyPair();
    
    		//加载公钥
    		try {
    			rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);
    			System.out.println("Loading RSA Public Key,成功!");
    		} catch (Exception e) {
    			System.err.println(e.getMessage());
    			System.err.println("Loading RSA Public Key,失败!");
    		}
    
    		//加载私钥
    		try {
    			rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY);
    			System.out.println("Loading RSA Private Key,成功!");
    		} catch (Exception e) {
    			System.err.println(e.getMessage());
    			System.err.println("Loading RSA Private Key,失败!");
    		}
    
    		long currentTime =System.currentTimeMillis();
    		System.err.println(currentTime/1000);
    		
    		 //测试字符串  
    		//System.out.println("--print  source_text --");
            String source_text= "Hello,World!";       
           // System.out.println(source_text);  
           // System.out.println("明文长度:"+ source_text.length());  
            
            try {  
                //使用公钥加密  
            	System.out.println("==使用公钥加密==");
                byte[] cipher_byte = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), source_text.getBytes());   
                
                System.out.println(new String(cipher_byte));  
                System.out.println("密文长度:"+ cipher_byte.length);  
                
                //for(int i=0;i<cipher_text.length;i++)
                //	System.out.println(cipher_text[i]);
                	
                //System.out.println(RSAEncrypt.byteArrayToString(cipher_byte));              
                //String cipher_hex="7e4f2c4794d19a1800060f0d716411d8c1eebefb080415154eb39ef3f703377dec058b0c319f729b4fe40fba5656ee71f75efe1b7b80683207243e7ec1ee81b854ea39768a0bb190923a2437a1f51bff11fc4c0847cf6c4c46c4010f54af4334cd7a88ca9d846c3ea2e12e7d5744c949d174483bf78c08d68a89b4d5cdb9fc65";
                //cipher_byte=RSAEncrypt.hexStringToByte(cipher_hex);            
                //System.out.println(new String(cipher_byte)); 
                
                //使用私钥解密,从这里开始!  
                System.out.println("==使用私钥解密,得到明文!==");
                //byte[] cipher_byte    密文二进制数组,最大长度小于128 Bytes.
                byte[] plain_text = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher_byte);         
                
                System.out.println(new String(plain_text)); 
                //System.out.println("明文长度:"+ plain_text.length);  
                //System.out.println(RSAEncrypt.byteArrayToString(plain_text));  
                
                
            } catch (Exception e) {  
                System.err.println(e.getMessage());  
            }  
            
    	}
    }
    

     --

  • 相关阅读:
    js 改变颜色值
    React之使用Context跨组件树传递数据
    App.js实现使用js开发app的应用,此文是中文文档
    转: CSS3 @media 用法总结
    转: 如何用手机访问电脑本地 localhost 网页或者服务器, 以调试web项目
    js 替换字符串中所有匹配的字符
    转:display:flex不兼容Android、Safari低版本的解决方案 【flex布局】
    转:HTML5页面如何在手机端浏览器调用相机、相册功能
    文本相似度度量
    idea中maven中jdk版本的选择(转)
  • 原文地址:https://www.cnblogs.com/GrantYu/p/5012911.html
Copyright © 2011-2022 走看看