1.参考资料

1.1 android的Cipher官方文档

  https://developer.android.com/reference/javax/crypto/Cipher

  其中 构造Cipher实例时要提供加密算法参数 transformation 它的格式有两种:

    1. "algorithm/mode/padding"
    2. "algorithm"

  代码如下:

  Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");

  其中关于rsa的部分:

Algorithm Modes Paddings Supported API Levels
RSA ECB
NONE
NoPadding
OAEPPadding
PKCS1Padding
1+
OAEPwithSHA-1andMGF1Padding
OAEPwithSHA-256andMGF1Padding
10+
OAEPwithSHA-224andMGF1Padding
OAEPwithSHA-384andMGF1Padding
OAEPwithSHA-512andMGF1Padding
23+

1.2 关于算法、Modes、Paddings

  https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher

  其中 rsa 的mode ECB的介绍如下:注意红色部分。

ECB Electronic Codebook Mode, as defined in FIPS PUB 81 (generally this mode should not be used for multiple blocks of data).

 

2.生成密钥

2.1 使用openssl

第1步:生产私钥文件,rsa_private_key.pem

openssl genrsa -out rsa_private_key.pem 2048

查看下它的内容:

其中

  • -----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY----- 之间就是私钥经过base64编码后的字符。
  • 解码后就可以得到私钥的字节数组。

第2步:根据私钥生产公钥,rsa_public_key.pem

openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

它的内容与私钥相似。

其中

  • -----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- 之间就是公钥经过base64编码后的字符。
  • 解码后就可以得到公钥的字节数组。

第3步:对私钥进行PKCS#8编码

openssl pkcs8 -topk8 -in rsa_private_key.pem -out rsa_pkcs8_private_key.pem -nocrypt

第4步:认证(收费)

如果担心公钥的可靠性,可去权威机构认证一下,得到数字证书。

创建证书请求文件,填写各项信息,如国家、城市、公司,邮箱、密码等等。

openssl req -new -key rsa_private_key.pem -out rsa_cert.csr

用生成的 rsa_cert.csr文件 去权威机构(CA)申请证书,CA会给你数字证书文件。

2.2 用java代码生成密钥

除了上面方法外,也可以用java代码生成公钥、私钥。

       try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize();
KeyPair keyPair = kpg.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); } catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

3.示例

3.1 加密、解密(支持分段)

公钥加密--->私钥解密

     // 公钥加密,支持分段。最大 MAX_ENCRYPT_SIZE 字节
public static byte[] encryptByPublicKey(@NonNull byte[] data,RSAPublicKey key) throws Exception { // 加密数据
Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, key); int inOffset = ,outOffset = ; int olen = cipher.getOutputSize(data.length);
byte output[] = new byte[olen];
Log.e("RSAUtil", "encryptByPublicKey: data.len = " + data.length + " outLen = " + olen); int loop = data.length / MAX_ENCRYPT_SIZE; for (int i = ; i < loop; ++i){
int inLen = MAX_ENCRYPT_SIZE;
int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
Log.e("RSAUtil", "encryptByPublicKey: outLen = " + outLen + " inLen = " + inLen);
inOffset += inLen;
outOffset += outLen;
} if (inOffset <= data.length){
cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
}
return cipher.doFinal();
} // 私钥解密,支持分段。最大 MAX_DECRYPT_SIZE 字节
public static byte[] decryptByPrivateKey(@NonNull byte[] encrypted,RSAPrivateKey key) throws Exception { // 解密数据
Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, key); int inOffset = ,outOffset = ; int olen = cipher.getOutputSize(encrypted.length);
byte output[] = new byte[olen];
Log.e("RSAUtil", "decryptByPrivateKey: data.len = " + encrypted.length + " outLen = " + olen); int loop = encrypted.length / MAX_DECRYPT_SIZE; for (int i = ; i < loop; ++i){
int inLen = MAX_DECRYPT_SIZE;
int outLen = cipher.update(encrypted,inOffset,inLen,output,outOffset);
Log.e("RSAUtil", "decryptByPrivateKey: outLen = " + outLen + " inLen = " + inLen);
inOffset += inLen;
outOffset += outLen;
} if (inOffset <= encrypted.length){
cipher.update(encrypted,inOffset,encrypted.length - inOffset,output,outOffset);
} return cipher.doFinal();
}

私钥加密--->公钥解密

     // 私钥加密,支持分段。最大 MAX_ENCRYPT_SIZE 字节
public static byte[] encryptByPrivateKey(@NonNull byte[] data,RSAPrivateKey key) throws Exception { // 数据加密
Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, key); int inOffset = ,outOffset = ; int olen = cipher.getOutputSize(data.length);
byte output[] = new byte[olen];
Log.e("RSAUtil", "encryptByPrivateKey: data.len = " + data.length + " outLen = " + olen); int loop = data.length / MAX_ENCRYPT_SIZE; for (int i = ; i < loop; ++i){
int inLen = MAX_ENCRYPT_SIZE;
int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
Log.e("RSAUtil", "encryptByPrivateKey: outLen = " + outLen + " inLen = " + inLen);
inOffset += inLen;
outOffset += outLen;
} if (inOffset <= data.length){
cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
}
return cipher.doFinal();
} // 公钥解密,支持分段。最大 MAX_DECRYPT_SIZE 字节
public static byte[] decryptByPublicKey(@NonNull byte[] data,RSAPublicKey key) throws Exception { // 数据解密
Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, key); int inOffset = ,outOffset = ; int olen = cipher.getOutputSize(data.length);
byte output[] = new byte[olen];
Log.e("RSAUtil", "decryptByPublicKey: data.len = " + data.length + " outLen = " + olen); int loop = data.length / MAX_DECRYPT_SIZE; for (int i = ; i < loop; ++i){
int inLen = MAX_DECRYPT_SIZE;
int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
Log.e("RSAUtil", "decryptByPublicKey: outLen = " + outLen + " inLen = " + inLen);
inOffset += inLen;
outOffset += outLen;
} if (inOffset <= data.length){
cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
}
return cipher.doFinal();
}

3.2 签名、验证

    // 签名
public static byte[] sign(@NonNull byte [] data,RSAPrivateKey key) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(key);
signature.update(data);
return signature.sign();
} // 验签
public static boolean verify(byte [] data, byte [] signed,RSAPublicKey key) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(key);
signature.update(data);
return signature.verify(signed);

4.注意事项

  • 加密最多(秘钥长度/8-11)个字节的数据,2048为245,1024为117。
  • android系统的RSA实现是"RSA/None/NoPadding",标准JDK实现是"RSA/ECB/PKCS1Padding" ,有可能在android机上加密后无法在服务器上解密。

5.代码

  完整示例

  https://github.com/f9q/rsa

android rsa 示例的更多相关文章

  1. 二维码(2)二维码登录原理及Android客户端示例

    1,原理 服务器: 数据库: 建立一个2维码登录的数据表,产生一个登录页时,插入一条记录X,X含将要登录的用户名字段(初始为空),2维码中的数据字段(唯一) 登录页面: 在产生的2维码中包含关键数据Y ...

  2. Android程序示例

    目录 Android代码示例 OptionsMenu ImageButton CheckBox & RadioButton Context Menu快捷菜单 Key Event ListVie ...

  3. Android RSA加密解密

    概述 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数 ...

  4. 导入cocos2d-x samples android官方示例

    导了一晚上samples android示例,查了一晚上资料,费了很大的劲,终于成功导入并运行成功,分享一下经验: 1.下载eclipse与ADT跟android SDK,相信大家都会装了吧. 2.下 ...

  5. Android RSA加密对象数据

    前几天说了手头项目用MD5和双向加密DES来进行加密的,因为产品是在不断的改造中完善的.考虑到DES和MD5加解密还是会存下一定的风险,于是产品一拍,不行,听你们说MD5加密是不安全的,咱们产品以后做 ...

  6. Android编程示例:创建机场计划模拟器应用程序

    在本文中,我们将演示如何使用Android Studio和Java编程语言创建一个示例Android应用程序,从“临时”实现高级响应用户界面的功能.本文中讨论的应用程序将实现机场航班时刻表模拟的功能. ...

  7. Android系统示例分析之AndroidBeamDemo

    在这个示例工程中,只有一个Activity: public class Beam extends Activity implements CreateNdefMessageCallback,      ...

  8. Android系统示例之ActionBarCompat

    导入工程ActionBarCompat时,出现错误.从其他工程下拷贝project.propertiest文件过来,问题仍在.拷贝后需要重启Eclipse才解决.问题如下: [2013-07-03 1 ...

  9. Android系统示例分析之AccelerometerPlay

    程序界面: 创建 SimulationView , 实现接口 SensorEventListener , 实现接口中两个抽象方法 public void onSensorChanged(SensorE ...

随机推荐

  1. 用JS写的一个简单的时钟

    没什么技术含量,单纯的想传上去.手痒了 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  2. PAT甲级——A1075 PAT Judge

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

  3. java基础之Integer包装类

    Integer类概述: Integer 类在对象中包装了一个基本类型 int 的值 该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他 ...

  4. springboot整合rabbitMQ时遇到的消息无法入列问题

    问题描述: 对列和交换器配置如下(绑定的正常交换器的key是“convert”): 管理平台上手动发是可以的: 而通过程序发消息不行,根本没有进入队列: 解决:显式指定交换器(备选交换器和死信交换器都 ...

  5. Lp- Linux必学的60个命令

    1.作用 lp是打印文件的命令,使用权限是所有用户. 2.格式 lp [-c][-d][-m][-number][-title][-p] 3.主要参数 -c:先拷贝文件再打印. -d:打印队列文件. ...

  6. 细说WPF自定义路由事件

    WPF中的路由事件 as U know,和以前Windows消息事件区别不再多讲,这篇博文中,将首先回顾下WPF内置的路由事件的用法,然后在此基础上自定义一个路由事件. 1.WPF内置路由事件   W ...

  7. mysql导出某张表的部分数据

    .使用into outfile '保存到操作系统的外部文件路径' mysql -uroot -p123456 -hhostname -P3306 select column_name_list fro ...

  8. 图像复原MATLAB实现

    前言:本篇博客先介绍滤波器滤除噪声,再介绍滤波器复原,侧重于程序的实现. 一:三种常见的噪声 二:空间域滤波 空间域滤波复原是在已知噪声模型的基础上,对噪声的空间域进行滤波.空间域滤波复原方法主要包括 ...

  9. PHP实现记录浏览历史页面

    <?php /******* 说明:cookie只能保存字符串 本实例中,需要保存多个URL(历史访问记录),思路是先将URL数组转为字符串,然后保存,读取时,再循环读取 *******/ // ...

  10. Android SDK上手指南:应用程序发布

    Android SDK上手指南:应用程序发布 2013-12-26 15:47 核子可乐译 51CTO 字号:T | T 在今天的文章中,我们将重点探讨通过Google Play软件商店进行应用程序发 ...