Android 加密总结

基本概念

密码学的三大作用:加密( Encryption)、认证(Authentication),鉴定(Identification)

加密:

防止坏人获取你的数据

鉴权:

防止坏人假冒你的身份。

认证:

防止坏人修改了你的数据而你却并没有发现。

Base64编码

Base64编码算法是一种用64个字符(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)来表示任意二进制数据的方法。在加解密算法中,原始的数据和加密后的数据一般也是二进制数据,为了不传输出错,方便保存或者调试代码,一般需要对加密后的数据进行base64编码。

常用加密算法

对称加密算法(加解密密钥相同)

加解密速度快,适合大数据量的加解密处理,但是密钥管理困难,不适合互联网,一般用于内部系统
常见的有DES,3DES,AES,DES默认的是56位的加密密钥,已经不安全,不建议使用,推荐使用AES,Android 提供的AES加密算法API默认使用的是ECB模式,所以要显式指定加密算法为:CBC或CFB模式,可带上PKCS5Padding填充。AES密钥长度最少是128位,推荐使用256位。

  try {
      String a="abc";
      //生成key
      KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
      keyGenerator.init(256);
      //产生秘钥
      SecretKey secretKey=keyGenerator.generateKey();
      //获取秘钥
      byte[] bytes=secretKey.getEncoded();
      //还原秘钥
      SecretKey key=new SecretKeySpec(bytes,"AES");
      Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE,secretKey);
byte[] result=cipher.doFinal(a.getBytes());
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    }

非对称加密(加密密钥和解密密钥不同)

密钥容易管理,速度慢,适合小数据量加解密或数据签名,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密(这个过程可以做数字签名)。
非对称加密主要使用的是RSA算法。
生成密钥对:

public static KeyPair generateRSAKeyPair(int keyLength) {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
            kpg.initialize(keyLength);//密钥长度不要低于512位,建议使用2048位的密钥长度
            return kpg.genKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

公钥加密:

public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
        // 得到公钥
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 加密数据
        Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.ENCRYPT_MODE, keyPublic);
        return cp.doFinal(data);
    }

私钥加密:

  public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
        // 得到私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
        return cipher.doFinal(data);
    }

公钥解密:

 public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
        // 得到公钥
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, keyPublic);
        return cipher.doFinal(data);
    }

私钥解密:

  public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
        // 得到私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);

        // 解密数据
        Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.DECRYPT_MODE, keyPrivate);
        byte[] arr = cp.doFinal(encrypted);
        return arr;
    }

注意:android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding" ,这造成了在android机上加密后无法在服务器上解密的原因,1024位key的最多只能加密127位数据,否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)

消息摘要

MD5加密全程是Message-Digest Algoorithm 5(信息-摘要算法),它对信息进行摘要采集,再通过一定的位运算,最终获取加密后的MD5字符串。
  例如我们要加密一篇文章,那么我们会随机从每段话或者每行中获取一个字,把这些字统计出来后,再通过一定的运算获得一个固定长度的MD5加密后信息。因此,其很难被逆向破解。

Android端 AES+RSA结合实践

Android端

服务器端(server)分别生成自己的RSA密钥对,并提供接口给Android客户端获取RSA公钥(rsaPublicKey)
client生成AES密钥(aesKey)
client使用自己的AES密钥(aesKey)对转换为json格式的请求明文数据(data)进行加密,得到加密后的请求数据encryptData
client提供server提供的接口获取RSA公钥(rsaPublicKey)
client使用获取RSA公钥(rsaPublicKey)对AES密钥(aesKey)进行加密,得到encryptAesKey
client将encryptAesKey作为http请求头参数,将加密后的请求数据encryptData作为请求体一起传输给服务器端

服务器端

server响应client的http请求,读取http请求头。获得client传过来的加密后的AES密钥(encryptAesKey),读取http请求体,获得client传过来的加密后的请求数据(encryptData)。
server使用自己的RSA私钥(rsaPrivateKey)对加密后的AES密钥(encryptAesKey)进行RSA解密,得到AES密钥(aesKey)
使用解密后的AES密钥(aesKey)对加密后的请求数据(encryptData),进行AES解密操作,得到解密后的请求数据(data),该数据为json格式
对解密后的请求数据(data)进行json解析,然后做相关的响应操作。

你可能感兴趣的:(Android 加密总结)