zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    win7下的nginx小demo
    破解navicat
    MVC下用C#实现Excel导出
    使用IE10登录,URL出现SessionId的解决办法
    C#错误:The Controls collection cannot be modified
    更改数据库排序规则
    windows server 2008 r2电脑历史操作记录
    jquery easyui无法绑定下拉框内容
    Jquery实现自动提示下拉框
    CLSID {91493441-5A91-11CF-8700-00AA0060263B}错误
  • 原文地址:https://www.cnblogs.com/mhbs/p/10480073.html
Copyright © 2011-2022 走看看