欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 客户端RSA加密的实现方法

程序员文章站 2023-12-05 16:54:04
android 客户端rsa加密的实现方法 针对java后端进行的rsa加密,android客户端进行解密,结果是部分乱码的问题: 注意两点,编码问题和客户端使用的...

android 客户端rsa加密的实现方法

针对java后端进行的rsa加密,android客户端进行解密,结果是部分乱码的问题:

注意两点,编码问题和客户端使用的算法问题

即:都使用utf-8编码,base64使用一致,另外,使用下面的代码在后端和移动端解密只有一点不同:

移动端使用

 cipher cipher = cipher.getinstance("rsa/ecb/pkcs1padding");

后端使用

 cipher cipher = cipher.getinstance("rsa");

其他地方都不需要改动

package rsa;

import android.util.base64;

import java.io.bytearrayinputstream;
import java.io.bytearrayoutputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.fileoutputstream;
import java.io.inputstream;
import java.io.outputstream;

//import org.apache.commons.codec.binary.base64;

/** *//**
 * <p>
 * base64编码解码工具包
 * </p>
 * @author icewee
 * @date 2012-5-19
 * @version 1.0
 */
public class base64utils {

  /** *//**
   * 文件读取缓冲区大小
   */
  private static final int cache_size = 1024;

  /** *//**
   * <p>
   * base64字符串解码为二进制数据
   * </p>
   *
   * @param base64
   * @return
   * @throws exception
   */
  public static byte[] decode(string base64) throws exception {
    return base64.decode(base64.getbytes(), base64.default);
  }
  /** *//**
   * <p>
   * 二进制数据编码为base64字符串
   * </p>
   *
   * @param bytes
   * @return
   * @throws exception
   */
  public static string encode(byte[] bytes) throws exception {
    return new string(base64.encode(bytes, base64.default));
  }
  /**
   *
   * @param str
   * @return
   * @throws exception
   */
  public static string encode(string str) throws exception {
    byte[] bytes = str.getbytes("utf-8");
    return encode(bytes);
  }
  /** *//**
   * <p>
   * 将文件编码为base64字符串
   * </p>
   * <p>
   * 大文件慎用,可能会导致内存溢出
   * </p>
   *
   * @param filepath 文件绝对路径
   * @return
   * @throws exception
   */
  public static string encodefile(string filepath) throws exception {
    byte[] bytes = filetobyte(filepath);
    return encode(bytes);
  }

  /** *//**
   * <p>
   * base64字符串转回文件
   * </p>
   *
   * @param filepath 文件绝对路径
   * @param base64 编码字符串
   * @throws exception
   */
  public static void decodetofile(string filepath, string base64) throws exception {
    byte[] bytes = decode(base64);
    bytearraytofile(bytes, filepath);
  }

  /** *//**
   * <p>
   * 文件转换为二进制数组
   * </p>
   *
   * @param filepath 文件路径
   * @return
   * @throws exception
   */
  public static byte[] filetobyte(string filepath) throws exception {
    byte[] data = new byte[0];
    file file = new file(filepath);
    if (file.exists()) {
      fileinputstream in = new fileinputstream(file);
      bytearrayoutputstream out = new bytearrayoutputstream(2048);
      byte[] cache = new byte[cache_size];
      int nread = 0;
      while ((nread = in.read(cache)) != -1) {
        out.write(cache, 0, nread);
        out.flush();
      }
      out.close();
      in.close();
      data = out.tobytearray();
    }
    return data;
  }

  /** *//**
   * <p>
   * 二进制数据写文件
   * </p>
   *
   * @param bytes 二进制数据
   * @param filepath 文件生成目录
   */
  public static void bytearraytofile(byte[] bytes, string filepath) throws exception {
    inputstream in = new bytearrayinputstream(bytes);
    file destfile = new file(filepath);
    if (!destfile.getparentfile().exists()) {
      destfile.getparentfile().mkdirs();
    }
    destfile.createnewfile();
    outputstream out = new fileoutputstream(destfile);
    byte[] cache = new byte[cache_size];
    int nread = 0;
    while ((nread = in.read(cache)) != -1) {
      out.write(cache, 0, nread);
      out.flush();
    }
    out.close();
    in.close();
  }

}

package rsa;

import android.util.base64;

import java.io.bytearrayoutputstream;
import java.security.key;
import java.security.keyfactory;
import java.security.keypair;
import java.security.keypairgenerator;
import java.security.privatekey;
import java.security.publickey;
import java.security.signature;
import java.security.interfaces.rsaprivatekey;
import java.security.interfaces.rsapublickey;
import java.security.spec.pkcs8encodedkeyspec;
import java.security.spec.x509encodedkeyspec;
import java.util.hashmap;
import java.util.map;

import javax.crypto.cipher;

/**
 * <p>
 * rsa公钥/私钥/签名工具包
 * </p>
 * <p>
 * 罗纳德·李维斯特(ron [r]ivest)、阿迪·萨莫尔(adi [s]hamir)和伦纳德·阿德曼(leonard [a]dleman)
 * </p>
 * <p>
 * 字符串格式的密钥在未在特殊说明情况下都为base64编码格式<br/>
 * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
 * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
 * </p>
 *
 * @author icewee
 * @date 2012-4-26
 * @version 1.0
 */
public class rsautils {

  /**
   * 加密算法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;

  /**
   * <p>
   * 生成密钥对(公钥和私钥)
   * </p>
   *
   * @return
   * @throws exception
   */
  public static map<string, object> genkeypair() throws exception {
    keypairgenerator keypairgen = keypairgenerator.getinstance(key_algorithm);
    keypairgen.initialize(1024);
    keypair keypair = keypairgen.generatekeypair();
    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 = base64.decode(privatekey,0);

    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 base64.encodetostring(signature.sign(), 0);
  }

  /**
   * <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 = base64.decode(publickey,0);
    x509encodedkeyspec keyspec = new x509encodedkeyspec(keybytes);
    keyfactory keyfactory = keyfactory.getinstance(key_algorithm);
    publickey publick = keyfactory.generatepublic(keyspec);
    signature signature = signature.getinstance(signature_algorithm);
    signature.initverify(publick);
    signature.update(data);
    return signature.verify(base64.decode(sign,0));
  }

  /**
   * <p>
   * 私钥解密
   * </p>
   *
   * @param encrypteddata 已加密数据
   * @param privatekey 私钥(base64编码)
   * @return
   * @throws exception
   */
  public static byte[] decryptbyprivatekey(byte[] encrypteddata, string privatekey)
      throws exception {
    byte[] keybytes = base64.decode(privatekey, 0);
    pkcs8encodedkeyspec pkcs8keyspec = new pkcs8encodedkeyspec(keybytes);
    keyfactory keyfactory = keyfactory.getinstance(key_algorithm);
    key privatek = keyfactory.generateprivate(pkcs8keyspec);
    cipher cipher = cipher.getinstance("rsa/ecb/pkcs1padding");
    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 = base64.decode(publickey,0);
    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 = base64.decode(publickey,0);
    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.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 = base64.decode(privatekey,0);
    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 base64.encodetostring(key.getencoded(),0);
  }

  /**
   * <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 base64.encodetostring(key.getencoded(), 0);
  }

}

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!