对称加密与非对称加密初接触

关于非对称加密与对称加密的资料网上随便搜搜就会有的这里就不再赘述了

在接触前先看张流程图

RSA加密流程

上图为RSA加密与后台的流程 PS: 画图就是这么diao : )

RSA加密与解密

  • 为了加强了解 RSA密钥分为公钥和私钥 公钥可以给发给别人
  • android这边可以将服务端发过来的公钥存储在assets文件夹下
  • Cipher类初始化需要声明transformation这里我们固定写RSA/ECB/PKCS1PADDING (为加密数据附加一段随机数)

读取公钥

  • 由公钥文件获取PublicKey对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static PublicKey getPublicKeyFromFile(InputStream bais) {
    PublicKey puk = null;
    try {
    CertificateFactory certificatefactory = CertificateFactory
    .getInstance("X509");
    Certificate cert = certificatefactory.generateCertificate(bais);

    bais.close();
    puk = cert.getPublicKey();
    Log.e(TAG, "getPublicKeyFromFile: " + puk);
    return puk;
    } catch (Exception e) {
    Log.e(TAG, "getPublicKeyFromFile: 异常 " + e.getMessage());
    return puk;
    }
    }

加密

  • 实际上加密只需要初始化Cipher并doFinal即可 但查资料得知公钥加密每次程度不能超过一定长度 所以需要对数据进行分段加密并进行Base64编码 详细代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public static String sPubEncrypt(String str,PublicKey publicKey){
    String encode = "";
    try {
    Log.e(TAG, "sPubEncrypt: " + publicKey);
    //实例化加密类
    Cipher cipher = Cipher.getInstance(RSATYPE, new BouncyCastleProvider());
    //取得明文的二进制
    byte[] plainText = str.getBytes();
    //加密
    cipher.init(Cipher.ENCRYPT_MODE,publicKey);

    // 对数据分段加密
    int inputLen = plainText.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(plainText, offSet, MAX_ENCRYPT_BLOCK);
    } else {
    cache = cipher.doFinal(plainText, offSet, inputLen - offSet);
    }
    out.write(cache, 0, cache.length);
    i++;
    offSet = i * MAX_ENCRYPT_BLOCK;
    }
    byte[] encryptedData = out.toByteArray();
    out.close();

    encode = Base64.encode(encryptedData);
    } catch (Exception e) {
    Log.e(TAG, "sPubEncrypt: 加密异常 " + e.getMessage());
    e.printStackTrace();
    } finally {
    return encode;
    }
    }

解密

  • 同理也是使用Cipher解密 只不过初始化参数换成了DECRYPT_MODE
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public String cPubDecrypt(String encString){
    Cipher cipher = null;
    String strDecrypt = null;
    try {
    cipher = Cipher.getInstance(RSATYPE);
    cipher.init(Cipher.DECRYPT_MODE,mPublicKey);
    //先将转为Base64编码的加密后数据转化为Byte数组
    byte[] enBytes = base64Dec(encString);
    //解密为byte数组,应该为字符串数组,最后转化为字符串
    byte[] deBytes = cipher.doFinal(enBytes);
    strDecrypt = new String(deBytes);
    } catch (Exception e) {
    Log.e(TAG, "cPubDecrypt: " + e.getMessage());
    e.printStackTrace();
    }finally {
    return strDecrypt;
    }
    }

DES加密与解密

  • 相比RSA DES要简单不少
  • 因为是对称加密 所以仅需一对密钥即可

获取密钥

  • 将服务端传来的DES密钥保存在本地即可
    1
    2
    3
    4
    5
    6
    public static SecretKey getKey(String strKey) throws Exception {
    DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes());
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
    SecretKey sk = keyFactory.generateSecret(desKeySpec);
    return sk;
    }

加密

  • 同样是用到了Cipher
    1
    2
    3
    4
    5
    6
    public static byte[] doEncrypt(byte[] data, Key key, String type)
    throws Exception {
    Cipher cipher = Cipher.getInstance(type);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    return cipher.doFinal(data);
    }

解密

  • 初始化Cipher参数换成了DECRYPT_MODE
    1
    2
    3
    4
    5
    6
    public static byte[] doDecrypt(byte[] data, Key key, String type)
    throws Exception {
    Cipher cipher = Cipher.getInstance(type);
    cipher.init(Cipher.DECRYPT_MODE, key);
    return cipher.doFinal(data);
    }

2016年12月13日09:48:46

补充

  • RSA不能被服务器的私钥解密的几点猜想
1
2
3
4
5
6
7
8
9
10
11
12
13
14
影响因素
publicKey源文件
publicKey对象
key中modulus开头00
Base64编码
文件类型(*.pem *.der)
Cipher初始值

排除
多个Base64编码结果相同
文件类型
源文件
00为补位


END