您的位置:首页 > 移动开发 > Android开发

android(客户端)和PC(服务器端)通信RSA 加密解密

2013-12-06 11:39 495 查看
android客户端代码:

package com.suning.reminder.util;

import java.io.BufferedReader;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.security.Key;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.SecureRandom;

import java.security.Security;

import java.security.Signature;

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.util.Arrays;

import java.util.HashMap;

import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.configuration.ConfigurationException;

import org.apache.commons.configuration.PropertiesConfiguration;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.openssl.PEMReader;

import org.bouncycastle.openssl.PasswordFinder;

public class RSAUtil {

 /**

  * 加密算法RSA

  */

 public static final String KEY_ALGORITHM = "RSA";

 /**

  * 签名算法

  */

 public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

 /**

  * 获取公钥的key

  */

 private static final String PUBLIC_KEY = "RSAPublicKey";

 /**

  * 获取私钥的key

  */

 private static final String PRIVATE_KEY = "RSAPrivateKey";

 /**

  * RSA最大加密明文大小

  */

 private static final int MAX_ENCRYPT_BLOCK = 117;

 /**

  * RSA最大解密密文大小

  */

 private static final int MAX_DECRYPT_BLOCK = 128;

 

 

 public static String privateKeyPath="private_key.pem";

 public static String publicKeyPath="public_key.pem";

 public static File getFile(){

  String p=RSAUtil.class.getClassLoader().getResource(privateKeyPath).getPath();

  return new File(Escape.unescape(p));

 }

 public static File getPublicFile(){

  String p=RSAUtil.class.getClassLoader().getResource(publicKeyPath).getPath();

  return new File(Escape.unescape(p));

 }

 /**

  * 生成秘钥对

  *

  * @return

  * @throws NoSuchAlgorithmException

  */

 public static KeyPair generateKey() throws NoSuchAlgorithmException {

  KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);

  keyPairGen.initialize(1024, new SecureRandom());

  KeyPair keyPair = keyPairGen.generateKeyPair();

  return keyPair;

 }

 /**

  * 保存到properties文件

  *

  * @param keyPair

  * @param publicKeyFile

  * @param privateKeyFile

  * @throws ConfigurationException

  */

 public static void saveKey(KeyPair keyPair, String publicKeyFile,

   String privateKeyFile) throws ConfigurationException {

  PublicKey pubkey = keyPair.getPublic();

  PrivateKey prikey = keyPair.getPrivate();

  // save public key

  PropertiesConfiguration publicConfig = new PropertiesConfiguration(

    publicKeyFile);

  publicConfig.setProperty("PULIICKEY", toHexString(pubkey.getEncoded()));

  publicConfig.save();

  // save private key

  PropertiesConfiguration privateConfig = new PropertiesConfiguration(

    privateKeyFile);

  privateConfig.setProperty("PRIVATEKEY",

    toHexString(prikey.getEncoded()));

  privateConfig.save();

 }

 /**

  * @param filename

  * @param type

  *            : 1-public 0-private

  * @return

  * @throws ConfigurationException

  * @throws NoSuchAlgorithmException

  * @throws InvalidKeySpecException

  */

 public static PrivateKey loadKeyPRI(String filename)

   throws ConfigurationException, NoSuchAlgorithmException,

   InvalidKeySpecException {

  PropertiesConfiguration config = new PropertiesConfiguration(filename);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM,

    new BouncyCastleProvider());

  // privateKey

  String privateKeyValue = config.getString("PRIVATEKEY");

  PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(

    toBytes(privateKeyValue));

  PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);

  return privateKey;

 }

 public static PublicKey loadKeyPUB(String filename)

   throws ConfigurationException, NoSuchAlgorithmException,

   InvalidKeySpecException {

  PropertiesConfiguration config = new PropertiesConfiguration(filename);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM,

    new BouncyCastleProvider());

  // publicKey

  String privateKeyValue = config.getString("PULIICKEY");

  X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(

    toBytes(privateKeyValue));

  PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec);

  return publicKey;

 }

 /**

  * Encrypt String.

  *

  * @return byte[]

  */

 public static byte[] encrypt(RSAPublicKey publicKey, byte[] data) {

  if (publicKey != null) {

   try {

    Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,

      new BouncyCastleProvider());

    cipher.init(Cipher.ENCRYPT_MODE, publicKey);

    return cipher.doFinal(data);

   } catch (Exception e) {

    e.printStackTrace();

   }

  }

  return null;

 }

 /**

  * Basic decrypt method

  *

  * @return byte[]

  */

 public static byte[] decrypt(RSAPrivateKey privateKey, byte[] raw) {

  if (privateKey != null) {

   try {

    Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,

      new BouncyCastleProvider());

    cipher.init(Cipher.DECRYPT_MODE, privateKey);

    return cipher.doFinal(raw);

   } catch (Exception e) {

    e.printStackTrace();

   }

  }

  return null;

 }

 public static String toHexString(byte[] b) {

  StringBuilder sb = new StringBuilder(b.length * 2);

  for (int i = 0; i < b.length; i++) {

   sb.append(HEXCHAR[(b[i] & 0xf0) >>> 4]);

   sb.append(HEXCHAR[b[i] & 0x0f]);

  }

  return sb.toString();

 }

 public static final byte[] toBytes(String s) {

  byte[] bytes;

  bytes = new byte[s.length() / 2];

  for (int i = 0; i < bytes.length; i++) {

   bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),

     16);

  }

  return bytes;

 }

 private static char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7',

   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

 /**

  * <p>

  * 生成密钥对(公钥和私钥)

  * </p>

  *

  * @return

  * @throws Exception

  */

 public static Map<String, Object> genKeyPair() throws Exception {

  KeyPair keyPair = generateKey();

  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

  Map<String, Object> keyMap = new HashMap<String, Object>(2);

  keyMap.put(PUBLIC_KEY, publicKey);

  keyMap.put(PRIVATE_KEY, privateKey);

  return keyMap;

 }

 /**

  * <p>

  * 用私钥对信息生成数字签名

  * </p>

  *

  * @param data

  *            已加密数据

  * @param privateKey

  *            私钥(BASE64编码)

  *

  * @return

  * @throws Exception

  */

 public static String sign(byte[] data, String privateKey) throws Exception {

  byte[] keyBytes = Base64Utils.decode(privateKey);

  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);

  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

  signature.initSign(privateK);

  signature.update(data);

  return Base64Utils.encode(signature.sign());

 }

 /**

  * <p>

  * 校验数字签名

  * </p>

  *

  * @param data

  *            已加密数据

  * @param publicKey

  *            公钥(BASE64编码)

  * @param sign

  *            数字签名

  *

  * @return

  * @throws Exception

  *

  */

 public static boolean verify(byte[] data, String publicKey, String sign)

   throws Exception {

  byte[] keyBytes = Base64Utils.decode(publicKey);

  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  PublicKey publicK = keyFactory.generatePublic(keySpec);

  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

  sign
ed1b
ature.initVerify(publicK);

  signature.update(data);

  return signature.verify(Base64Utils.decode(sign));

 }

 /**

  * <P>

  * 私钥解密

  * </p>

  *

  * @param encryptedData

  *            已加密数据

  * @param privateKey

  *            私钥(BASE64编码)

  * @return

  * @throws Exception

  */

 public static byte[] decryptByPrivateKey(byte[] encryptedData,

   String privateKey) throws Exception {

  byte[] keyBytes = Base64Utils.decode(privateKey);

  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

  cipher.init(Cipher.DECRYPT_MODE, privateK);

  int inputLen = encryptedData.length;

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  int offSet = 0;

  byte[] cache;

  int i = 0;

  // 对数据分段解密

  while (inputLen - offSet > 0) {

   if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

    cache = cipher

      .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

   } else {

    cache = cipher

      .doFinal(encryptedData, offSet, inputLen - offSet);

   }

   out.write(cache, 0, cache.length);

   i++;

   offSet = i * MAX_DECRYPT_BLOCK;

  }

  byte[] decryptedData = out.toByteArray();

  out.close();

  return decryptedData;

 }

 /**

  * <p>

  * 公钥解密

  * </p>

  *

  * @param encryptedData

  *            已加密数据

  * @param publicKey

  *            公钥(BASE64编码)

  * @return

  * @throws Exception

  */

 public static byte[] decryptByPublicKey(byte[] encryptedData,

   String publicKey) throws Exception {

  byte[] keyBytes = Base64Utils.decode(publicKey);

  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  Key publicK = keyFactory.generatePublic(x509KeySpec);

  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

  cipher.init(Cipher.DECRYPT_MODE, publicK);

  int inputLen = encryptedData.length;

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  int offSet = 0;

  byte[] cache;

  int i = 0;

  // 对数据分段解密

  while (inputLen - offSet > 0) {

   if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

    cache = cipher

      .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

   } else {

    cache = cipher

      .doFinal(encryptedData, offSet, inputLen - offSet);

   }

   out.write(cache, 0, cache.length);

   i++;

   offSet = i * MAX_DECRYPT_BLOCK;

  }

  byte[] decryptedData = out.toByteArray();

  out.close();

  return decryptedData;

 }

 /**

  * <p>

  * 公钥加密

  * </p>

  *

  * @param data

  *            源数据

  * @param publicKey

  *            公钥(BASE64编码)

  * @return

  * @throws Exception

  */

 public static byte[] encryptByPublicKey(byte[] data, String publicKey)

   throws Exception {

  byte[] keyBytes = Base64Utils.decode(publicKey);

  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  Key publicK = keyFactory.generatePublic(x509KeySpec);

  // 对数据加密

  Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");//keyFactory.getAlgorithm()解决javax.crypto.BadPaddingException: Blocktype异常的几种解决办法

  cipher.init(Cipher.ENCRYPT_MODE, publicK);

  int inputLen = data.length;

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  int offSet = 0;

  byte[] cache;

  int i = 0;

  // 对数据分段加密

  while (inputLen - offSet > 0) {

   if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

   } else {

    cache = cipher.doFinal(data, offSet, inputLen - offSet);

   }

   out.write(cache, 0, cache.length);

   i++;

   offSet = i * MAX_ENCRYPT_BLOCK;

  }

  byte[] encryptedData = out.toByteArray();

  out.close();

  return encryptedData;

 }

 /**

  * <p>

  * 私钥加密

  * </p>

  *

  * @param data

  *            源数据

  * @param privateKey

  *            私钥(BASE64编码)

  * @return

  * @throws Exception

  */

 public static byte[] encryptByPrivateKey(byte[] data, String privateKey)

   throws Exception {

  byte[] keyBytes = Base64Utils.decode(privateKey);

  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

  Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

  cipher.init(Cipher.ENCRYPT_MODE, privateK);

  int inputLen = data.length;

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  int offSet = 0;

  byte[] cache;

  int i = 0;

  // 对数据分段加密

  while (inputLen - offSet > 0) {

   if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

   } else {

    cache = cipher.doFinal(data, offSet, inputLen - offSet);

   }

   out.write(cache, 0, cache.length);

   i++;

   offSet = i * MAX_ENCRYPT_BLOCK;

  }

  byte[] encryptedData = out.toByteArray();

  out.close();

  return encryptedData;

 }

 /**

  * <p>

  * 获取私钥

  * </p>

  *

  * @param keyMap

  *            密钥对

  * @return

  * @throws Exception

  */

 public static String getPrivateKey(Map<String, Object> keyMap)

   throws Exception {

  Key key = (Key) keyMap.get(PRIVATE_KEY);

  return Base64Utils.encode(key.getEncoded());

 }

 /**

  * <p>

  * 获取公钥

  * </p>

  *

  * @param keyMap

  *            密钥对

  * @return

  * @throws Exception

  */

 public static String getPublicKey(Map<String, Object> keyMap)

   throws Exception {

  Key key = (Key) keyMap.get(PUBLIC_KEY);

  return Base64Utils.encode(key.getEncoded());

 }

   public static PublicKey getPublicKey(String key) throws Exception {   

     byte[] keyBytes;  

          keyBytes =Base64Utils.decode(key);

          X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);   

          KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   

          PublicKey publicKey = keyFactory.generatePublic(keySpec);   

          return publicKey; 

   }

  
 public static byte[] encrypt(PublicKey pubkey, String text) {

  try {

   Cipher rsa;

   rsa = Cipher.getInstance(KEY_ALGORITHM);

   rsa.init(Cipher.ENCRYPT_MODE, pubkey);

   return rsa.doFinal(text.getBytes());

  } catch (Exception e) {

   e.printStackTrace();

  }

  return null;

 }

 public static String decrypt(PrivateKey decryptionKey, byte[] buffer) {

  try {

   Cipher rsa;

   rsa = Cipher.getInstance(KEY_ALGORITHM);

   rsa.init(Cipher.DECRYPT_MODE, decryptionKey);

   byte[] utf8 = rsa.doFinal(buffer);

   return new String(utf8, "UTF8");

  } catch (Exception e) {

   e.printStackTrace();

  }

  return null;

 }

 public static KeyPair readKeyPair(File privateKey, String keyPassword)

   throws IOException {

  FileReader fileReader = new FileReader(privateKey);

  PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(

    keyPassword.toCharArray()));

  try {

   return (KeyPair) r.readObject();

  } catch (IOException ex) {

   throw ex;

  } finally {

   r.close();

   fileReader.close();

  }

 }

 public static Key readPublicKey(File privateKey, String keyPassword)

   throws IOException {

  FileReader fileReader = new FileReader(privateKey);

  PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(

    keyPassword.toCharArray()));

  try {

   return (RSAPublicKey) r.readObject();

  } catch (IOException ex) {

   throw ex;

  } finally {

   r.close();

   fileReader.close();

  }

 }

 public static class DefaultPasswordFinder implements PasswordFinder {

  private final char[] password;

  private DefaultPasswordFinder(char[] password) {

   this.password = password;

  }

  @Override

  public char[] getPassword() {

   return Arrays.copyOf(password, password.length);

  }

 }

 // ----------------------------------------------------------

 // 测试

 public static void main(String args[]) throws Exception {

  Security.addProvider(new BouncyCastleProvider());

  /*String path = System.getProperty("project.root");

   String p = "private_key.pem";

   p=RSAUtil.class.getClassLoader().getResource(p).getPath();

  StringBuffer sb=new StringBuffer();

  File privateKey = new File(p);

  KeyPair keyPair = RSAUtil.readKeyPair(privateKey, "1234");

  PrivateKey prikey = keyPair.getPrivate();*/

  /*String path=System.getProperty("project.root");

  Security.addProvider(new BouncyCastleProvider());

  System.err.println("公钥加密——私钥解密");

  File privateKey = new File(

    "D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\private_key.pem");

  KeyPair keyPair = readKeyPair(privateKey, "1234");

  PrivateKey prikey = keyPair.getPrivate();

  PublicKey pubkey = keyPair.getPublic();

  String source = "logonId=18801148262&userId=34006452405&phoneNo=18801148262";

  System.out.println("\r加密前文字:\r\n" + source);

  byte[] data = source.getBytes();

  byte[] encodedData = RSAUtil.encryptByPublicKey(data, Base64Utils

    .encode(pubkey.getEncoded()));

  String temp=Base64Utils.encode(encodedData);

  //String temp="tBSLW2kbMJKHIkH46pUoCAsofxp7yYlUSzDRwoRN8WYuShhRaKv7MxPK+mdGj21+UFU9Dn+XEAu5JbjtTlt/XW3eVv26qeae3wMhE+c+MWEKyo5qBdkO2DnOpYmGPb0TPGyTDaI7NQJENus2EYeOd+CPfD4JKA15gUxoN0tZwo0="; 

  //String temp="gu6PFc7yPMcdJpOsNy5prFuObAJoSbYry4NWH8zmlhbx9bm5zgtF1HNiOwTIe9blZPfDHgLCyWyu78/FXJNtldaHwVhp12/Ez23iP701L3vxaBAC/mYXqW2ofGUsCSSPIJq3r+XraPvq1H/N4j4VvfkVBK+USB9ya9qupKn/Oj0="; 

  System.out.println("加密后文字:\r\n" + temp);

  byte[] decodedData = RSAUtil.decryptByPrivateKey(Base64Utils.decode(temp),

    Base64Utils.encode(prikey.getEncoded()));

  String target = new String(decodedData);

  System.out.println("解密后文字: \r\n" + target);*/

  Security.addProvider(new BouncyCastleProvider());

  String userInfo=null;

  //userInfo="logonId="+loginBackBean.getLogonId()+"&userId="+loginBackBean.getUserId()+"&phoneNo="+loginBackBean.getPhoneNo();

  userInfo="logonId=15510717593&userId=34006452405&phoneNo=18801148262";

  PublicKey publicKey = RSAUtil.getPublicKey(getFromAssets("D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\public_key.pem"));

  System.out.println("\r加密前文字:\r\n" + userInfo);

  byte[] encodedData = RSAUtil.encryptByPublicKey(userInfo.getBytes(), Base64Utils

    .encode(publicKey.getEncoded()));

  userInfo=Base64Utils.encode(encodedData);

  System.out.println("加密后文字:\r\n" + userInfo);

  /*File privateKey = new File(

    "D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\private_key.pem");

  KeyPair keyPair = readKeyPair(privateKey, "1234");

  PrivateKey prikey = keyPair.getPrivate();

  PublicKey pubkey =  keyPair.getPublic();

  byte[] encodedData = RSAUtil.encryptByPublicKey(userInfo.getBytes(), Base64Utils

    .encode(publicKey.getEncoded()));

  userInfo=Base64Utils.encode(encodedData);

  System.out.println("加密后文字:\r\n" + userInfo);

  

  //String  prikey =getFromAssets("D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\private_key.pem");

  byte[] decodedData = RSAUtil.decryptByPrivateKey(Base64Utils.decode(userInfo),

    Base64Utils.encode(prikey.getEncoded()));

  String target = new String(decodedData);

  System.out.println("解密后文字: \r\n" + target);*/

  

  

  File privateKey = RSAUtil.getFile();

  Security.addProvider(new BouncyCastleProvider());

  KeyPair keyPair = RSAUtil.readKeyPair(privateKey, "1234");

  PrivateKey prikey = keyPair.getPrivate();

  byte[] decodedData = RSAUtil.decryptByPrivateKey(

    Base64Utils.decode(userInfo),

    Base64Utils.encode(prikey.getEncoded()));

  String target = new String(decodedData);

  System.out.println("解密后文字: \r\n" + target);

  

 /* 

  String source = "logonId=18801148262&userId=34006452405&phoneNo=18801148262";

  File publicKey = new File(

    "D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\rsa_public_key.pem");

  File privateKey = new File(

  "D:\\workspace\\PBR_SERVICE\\src\\main\\resources\\rsa_private_key.pem");

  KeyPair keyPair = readKeyPair(privateKey, "redbaby");

  PrivateKey prikey = keyPair.getPrivate();

  System.out.println(prikey);

  

  PublicKey pubkey = (PublicKey) readPublicKey(publicKey, "redbaby");

  System.out.println(pubkey);

  System.out.println("\r加密前文字:\r\n" + source);

  byte[] encodedData = encrypt(pubkey, source);

  System.out.println("加密后文字:\r\n" + new String(encodedData));

  String target = decrypt(prikey, encodedData);

  System.out.println("解密后文字: \r\n" + target);*/

 }

 public void testSign() throws Exception {

//  System.err.println("私钥加密——公钥解密");

//  String source = "这是一行测试RSA数字签名的无意义文字";

//  System.out.println("原文字:\r\n" + source);

//  byte[] data = source.getBytes();

//  byte[] encodedData = encryptByPrivateKey(data, privateKey);

//  System.out.println("加密后:\r\n" + new String(encodedData));

//  byte[] decodedData = decryptByPublicKey(encodedData, publicKey);

//  String target = new String(decodedData);

//  System.out.println("解密后: \r\n" + target);

//  System.err.println("私钥签名——公钥验证签名");

//  String sign = sign(encodedData, privateKey);

//  System.err.println("签名:\r" + sign);

//  boolean status = verify(encodedData, publicKey, sign);

//  System.err.println("验证结果:\r" + status);

 }

 
 public String getFromAssets(String fileName){

    String result="";

  try {  

      InputStreamReader inputReader = new InputStreamReader(getAssets().open(fileName));

      BufferedReader bufReader = new BufferedReader(inputReader);

       String line="";

       while((line = bufReader.readLine()) != null) {

        result += line;

        }

   } catch (Exception e) { 

        e.printStackTrace(); 

     }

   return result; 

  }  

 }

 

发送请求:

      PublicKey publicKey = RSAUtil.getPublicKey(getFromAssets(RSAUtil.publicKeyPath));

      System.out.println("\r加密前文字:\r\n" + userInfo);

      //PublicKey pubkey = (PublicKey)RSAUtil.encryptByPublicKey(publicKey);

      byte[] encodedData = RSAUtil.encryptByPublicKey(userInfo.getBytes(), Base64Utils

        .encode(publicKey.getEncoded()));

      userInfo=Base64Utils.encode(encodedData);

      System.out.println("加密后文字:\r\n" + userInfo);

 

 

服务器端主要代码:

/**

  * <P>

  * 私钥解密

  * </p>

  *

  * @param encryptedData

  *            已加密数据

  * @param privateKey

  *            私钥(BASE64编码)

  * @return

  * @throws Exception

  */

 public static byte[] decryptByPrivateKey(byte[] encryptedData,

   String privateKey) throws Exception {

  byte[] keyBytes = Base64Utils.decode(privateKey);

  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

  cipher.init(Cipher.DECRYPT_MODE, privateK);

  int inputLen = encryptedData.length;

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  int offSet = 0;

  byte[] cache;

  int i = 0;

  // 对数据分段解密

  while (inputLen - offSet > 0) {

   if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

    cache = cipher

      .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

   } else {

    cache = cipher

      .doFinal(encryptedData, offSet, inputLen - offSet);

   }

   out.write(cache, 0, cache.length);

   i++;

   offSet = i * MAX_DECRYPT_BLOCK;

  }

  byte[] decryptedData = out.toByteArray();

  out.close();

  return decryptedData;

 }

接收请求,处理私钥解密

File privateKey = RSAUtil.getFile();

  Security.addProvider(new BouncyCastleProvider());
  KeyPair keyPair = RSAUtil.readKeyPair(privateKey, "1234");

  PrivateKey prikey = keyPair.getPrivate();

  byte[] decodedData = RSAUtil.decryptByPrivateKey(

    Base64Utils.decode(userInfo),

    Base64Utils.encode(prikey.getEncoded()));

  String target = new String(decodedData);

  System.out.println("解密后文字: \r\n" + target);

  return target;

 

android客户端加密和pc服务器端解密需要注意事项:javax.crypto.BadPaddingException: Blocktype

1.异常描述:最近做项目为了增强数据传输的安全性用到了RSA加密。即android客户端将要传送的信息,用私钥通过RSA非对称加密算法加密后,传到服务器端(PC端)。服务器端用对应(密钥)的公钥来解密时解密失败,抛出“javax.crypto.BadPaddingException: Blocktype”异常。

2.异常原因:Android系统使用的虚拟机(dalvik)跟SUN标准JDK是有所区别的,其中他们默认的RSA实现就不同。即Android端用Cipher.getInstance("RSA")方法进行加密时,使用的provider是Bouncycastle Security provider,Bouncycastle Security provider默认实现的是“RSA/None/NoPadding”算法,而服务器(PC)端用Cipher.getInstance("RSA")进行解密时,使用的是Sun的security
provider,实现的是“RSA/None/PKCS1Padding”算法,所以,解密时会失败。

3.解决办法:我这里提供三种解决办法:

第一种:将服务器(pc)端的Cipher.getInstance("RSA")方法改为Cipher.getInstance("RSA/ECB/NoPadding")。但这种改法有一个缺点就是解密后的明文比加密之前多了很多空格。(空格的长度个数+原来的明文字符数=产生密钥时采用的bit数/8)

第二种:将Android端的Cipher.getInstance("RSA")方法改为Cipher.getInstance("RSA/None/PKCS1Padding")。这种方法解密后的明文和加密前的明文是对应的,不会出现第一种方法中的现象,推荐这种方法。

第三种:在服务器(pc)端的jdk中加入Bouncycastle Security provider,关于Bouncycastle JCE的安装配置及验证请参看
http://blog.csdn.net/caoshichao520326/article/details/8732670, 配置好Bouncycastle Security
provider后,将服务器(pc)端的Cipher.getInstance("RSA")方法改为Cipher.getInstance("RSA","BC")。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: