android rsa 示例

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代码生成公钥、私钥。

 1       try {
 2             KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 3             kpg.initialize(2048);
 4             KeyPair keyPair =  kpg.genKeyPair();
 5             RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 6             RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 7 
 8         } catch (NoSuchAlgorithmException e) {
 9             e.printStackTrace();
10         }

3.示例

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

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

 1     // 公钥加密,支持分段。最大 MAX_ENCRYPT_SIZE 字节
 2     public static byte[] encryptByPublicKey(@NonNull byte[] data,RSAPublicKey key) throws Exception {
 3 
 4         // 加密数据
 5         Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
 6         cipher.init(Cipher.ENCRYPT_MODE, key);
 7 
 8         int inOffset = 0,outOffset = 0;
 9 
10         int olen = cipher.getOutputSize(data.length);
11         byte output[] = new byte[olen];
12         Log.e("RSAUtil", "encryptByPublicKey: data.len = " + data.length + " outLen = " + olen);
13 
14         int loop = data.length / MAX_ENCRYPT_SIZE;
15 
16         for (int i = 0 ; i < loop; ++i){
17             int inLen = MAX_ENCRYPT_SIZE;
18             int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
19             Log.e("RSAUtil", "encryptByPublicKey: outLen = " + outLen + " inLen = " + inLen);
20             inOffset += inLen;
21             outOffset += outLen;
22         }
23 
24         if (inOffset <= data.length){
25             cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
26         }
27         return cipher.doFinal();
28     }
29 
30 
31     // 私钥解密,支持分段。最大 MAX_DECRYPT_SIZE 字节
32     public static byte[] decryptByPrivateKey(@NonNull byte[] encrypted,RSAPrivateKey key) throws Exception {
33 
34         // 解密数据
35         Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
36         cipher.init(Cipher.DECRYPT_MODE, key);
37 
38 
39         int inOffset = 0,outOffset = 0;
40 
41         int olen = cipher.getOutputSize(encrypted.length);
42         byte output[] = new byte[olen];
43         Log.e("RSAUtil", "decryptByPrivateKey: data.len = " + encrypted.length + " outLen = " + olen);
44 
45         int loop = encrypted.length / MAX_DECRYPT_SIZE;
46 
47         for (int i = 0 ; i < loop; ++i){
48             int inLen = MAX_DECRYPT_SIZE;
49             int outLen = cipher.update(encrypted,inOffset,inLen,output,outOffset);
50             Log.e("RSAUtil", "decryptByPrivateKey: outLen = " + outLen + " inLen = " + inLen);
51             inOffset += inLen;
52             outOffset += outLen;
53         }
54 
55         if (inOffset <= encrypted.length){
56             cipher.update(encrypted,inOffset,encrypted.length - inOffset,output,outOffset);
57         }
58 
59         return cipher.doFinal();
60     }

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

 1     // 私钥加密,支持分段。最大 MAX_ENCRYPT_SIZE 字节
 2     public static byte[] encryptByPrivateKey(@NonNull byte[] data,RSAPrivateKey key) throws Exception {
 3 
 4         // 数据加密
 5         Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
 6         cipher.init(Cipher.ENCRYPT_MODE, key);
 7 
 8         int inOffset = 0,outOffset = 0;
 9 
10         int olen = cipher.getOutputSize(data.length);
11         byte output[] = new byte[olen];
12         Log.e("RSAUtil", "encryptByPrivateKey: data.len = " + data.length + " outLen = " + olen);
13 
14         int loop = data.length / MAX_ENCRYPT_SIZE;
15 
16         for (int i = 0 ; i < loop; ++i){
17             int inLen = MAX_ENCRYPT_SIZE;
18             int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
19             Log.e("RSAUtil", "encryptByPrivateKey: outLen = " + outLen + " inLen = " + inLen);
20             inOffset += inLen;
21             outOffset += outLen;
22         }
23 
24         if (inOffset <= data.length){
25             cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
26         }
27         return cipher.doFinal();
28     }
29 
30     // 公钥解密,支持分段。最大 MAX_DECRYPT_SIZE 字节
31     public static byte[] decryptByPublicKey(@NonNull byte[] data,RSAPublicKey key) throws Exception {
32 
33         // 数据解密
34         Cipher cipher = Cipher.getInstance(ANDROID_TRANSFORMATION);
35         cipher.init(Cipher.DECRYPT_MODE, key);
36 
37         int inOffset = 0,outOffset = 0;
38 
39         int olen = cipher.getOutputSize(data.length);
40         byte output[] = new byte[olen];
41         Log.e("RSAUtil", "decryptByPublicKey: data.len = " + data.length + " outLen = " + olen);
42 
43         int loop = data.length / MAX_DECRYPT_SIZE;
44 
45         for (int i = 0 ; i < loop; ++i){
46             int inLen = MAX_DECRYPT_SIZE;
47             int outLen = cipher.update(data,inOffset,inLen,output,outOffset);
48             Log.e("RSAUtil", "decryptByPublicKey: outLen = " + outLen + " inLen = " + inLen);
49             inOffset += inLen;
50             outOffset += outLen;
51         }
52 
53         if (inOffset <= data.length){
54             cipher.update(data,inOffset,data.length - inOffset,output,outOffset);
55         }
56         return cipher.doFinal();
57     }

3.2 签名、验证

 1    // 签名
 2     public static byte[] sign(@NonNull byte [] data,RSAPrivateKey key) throws Exception {
 3         Signature signature = Signature.getInstance("SHA256withRSA");
 4         signature.initSign(key);
 5         signature.update(data);
 6         return signature.sign();
 7     }
 8 
 9     // 验签
10     public static boolean verify(byte [] data, byte [] signed,RSAPublicKey key) throws Exception {
11         Signature signature = Signature.getInstance("SHA256withRSA");
12         signature.initVerify(key);
13         signature.update(data);
14         return signature.verify(signed);
15

4.注意事项

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

5.代码

  完整示例

  https://github.com/f9q/rsa

原文地址:https://www.cnblogs.com/mhbs/p/10480073.html