美文网首页
Android网络加密

Android网络加密

作者: yaofclc | 来源:发表于2020-02-16 06:40 被阅读0次

    加解密的技术分类

    • 哈希函数 - SHA256、MD5
    • 对称加密 - <font color=red>AES</font>、DES
    • 非堆成加密 - <font color=red>RSA</font>、ECC、Elgamal
    • 交换密钥 - <font color=red>DH</font>、ECDH

    对称加密算法 —— AES

    AES:Advanced Encryption Standard ,高级加密标准

    • 加密:C= E(K,P),

      • 其中P为明文,K为密钥,C为密文
    • 解密:P = D(K,C),

      • 其中C为密文,K为密钥,P为明文

    特点:加密解密用同一个密钥。即用同样的方式还原明文。

    优点:

    • 加密效率高
    • 计算量小
    • 使用方便

    缺点:

    • 双方需要协商密钥
    • 一旦密钥泄露则加密系统崩塌
    • 密钥更新和维护困难

    流程: 加密解密过程使用相同的密钥

    public class AES {
        private SecretKey mKey;
    
        public AES() {
            try {
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                //创建随机密码,并设置种子
                SecureRandom secureRandom = new SecureRandom();
                secureRandom.setSeed(System.currentTimeMillis());
                //初始化密钥对象
                keyGenerator.init(128, secureRandom);
                //生成AES密钥并保存
                mKey = keyGenerator.generateKey();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    
        public AES(byte[] key) {
            mKey = new SecretKeySpec(key, "AES");
        }
    
        public byte[] getmKey() {
            return mKey.getEncoded();
        }
    
        public void setmKey(byte[] key) {
            this.mKey = new SecretKeySpec(key,"AES");
        }
    
        public byte[] encrpty(String content) {
            if (mKey == null) {
                return new byte[]{-1};
            }
            try {
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, mKey);
                return cipher.doFinal(content.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();
            }
            return new byte[]{-1};
        }
    
        public byte[] decrypt(byte[] content) {
            if (mKey == null) {
                return new byte[]{-1};
            }
            try {
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, mKey);
                return cipher.doFinal(content);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            }
            return new byte[]{-1};
        }
    }
    

    非对称加密算法 - RSA

    RSA是一种公开密钥密码机制

    • RSA算法的可靠性基础

      • 大质数相乘计算很容易
      • 对极大质数做因数分解很困难
      • 1111 x 3331 = 3700741
      • 3700741 = ? x ?

    特点:加密解密用不同的密钥。即用不同样的方式还原明文

    优点:

    • 公钥可以开放
    • 密钥方便管理
    • 安全性高

    缺点:

    • 性能差,加密时间长
    • 使用相对复杂

    流程:使用公钥加密,私钥解密(也有使用私钥加密,使用公钥解密的情况)

    public class RSA {
        private static final String RSA_ALOGORITHM = "RSA/ECB/PKCS1Padding";
    
        //加密函数,传入明文、公钥;返回密文
        @RequiresApi(api = Build.VERSION_CODES.O)
        public static String encrypt(int data, String pubKey) {
            //由于dh参数均为int类型,这里设计成对int加密
            String message = String.valueOf(data);
            byte[] decoded = DataUtils.base64Decode(pubKey);
            byte[] result = new byte[0];
            try {
                try {
                    RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                            .generatePublic(new X509EncodedKeySpec(decoded));
                    Cipher cipher = Cipher.getInstance(RSA_ALOGORITHM);
                    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                    result = cipher.doFinal(message.getBytes("UTF-8"));
                } catch (InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (BadPaddingException e) {
                    e.printStackTrace();
                } catch (IllegalBlockSizeException e) {
                    e.printStackTrace();
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return DataUtils.base64Encode(result);
        }
    
        //传入密文及私钥,返回明文
        @RequiresApi(api = Build.VERSION_CODES.O)
        public static String decypt(String encrypted, String privateKey) {
            byte[] decode = DataUtils.base64Decode(privateKey);
            byte[] content = DataUtils.base64Decode(encrypted);
            byte[] result = new byte[]{0};
            //初始工作完成,开始进行解密
            try {
                RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
                        .generatePrivate(new PKCS8EncodedKeySpec(decode));
                Cipher cipher = Cipher.getInstance(RSA_ALOGORITHM);
                cipher.init(Cipher.DECRYPT_MODE, priKey);
                result = cipher.doFinal(content);
    
    
            } catch (InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return new String(result);
        }
    }
    

    密钥交换算法 - DH

    DH:Diffie-Hellman,一种确保共享KEY安全的穿越不安全网络的方法

    特点:

    • 不需要保证信道安全
    • 计算公式可完全公开
    • 双方不需要知道对方的私钥
    • 可协商出一个其他人都不知道的密钥

    三个概念:

    • PubKey:公钥(可公开)
    • PriKey:私钥(不可公开)
    • Sercet:密钥(加密用)

    公钥公式:A|B = g exp (a|b) % p

    密钥公式:s = B|A exp(a|b) % p

    注: A,B是公钥,a,b是私钥,p,g是双方协定使用的,s是双方协商使用的密钥

    public class DH {
    
        private static final int dhP = 23;
        private static final int dhG = 5;
        private int mPriKey;
    
    
        //在构造器中初始化好需要的参数,私钥
        public DH(){
            Random r = new Random();
            mPriKey = r.nextInt(10);
            System.out.println("dh prikey is : "+mPriKey);
        }
    
        public int getPublic(){
            //使用公钥计算公式计算出自己的公钥,用以交换
            return (int) (Math.pow(dhG, mPriKey) % dhP);
        }
        //接收对方的公钥,与自己的私钥通过密钥公式产生密钥
        //因为需要作为AES的密钥,那么需要转换成byte[]
        public byte[] getSecretKey(long publicKey){
            int buf = (int) (Math.pow(publicKey, mPriKey) % dhP);
            return sha256(buf);
        }
    
        public byte[] getSecretKey(byte[] publicKey){
            int buf = (int) (Math.pow(DataUtils.byte2Int(publicKey), mPriKey) % dhP);
            return sha256(buf);
        }
    
    
    
        //将DH交换之后的双方相同的密钥(int)做一个hash转换
        //目的是转换成byte[128]类型,用做AES密钥
        private byte[] sha256(int data){
            try {
                MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
                messageDigest.update(DataUtils.int2Byte(data));
                return messageDigest.digest();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return new byte[]{-1};
        }
    }
    

    C/S网络模型

    网络模型设计-C/S三次握手

    1. ClientHello 发送客户端DH公钥
    2. ServerHello 发送服务器DH公钥
    3. 确认收到,完成握手

    客户端平台搭建

    Android Http必备技能 - okHttp

    • okHttp自带连接池,可减少请求延迟
    • 支持GZIP压缩
    • 有相应缓存可减少重复请求

    万能的开放加密库-OpenSSL

    OpenSSL:生成私钥命令:

    genrsa -out rsa_private_key.pem 1024(该数值越大保密性越强,效率越低)
    

    OpenSSL:生成RSA公钥命令:

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

    AES对称加密

    AES加密库的使用:

    • 根据AES密钥创建Secret密钥向量
    • 生成初始化参数向量
    • 获取AES Cipher
    • 执行加密
    • Base64编码(建议)

    DH密钥交换

    • DH密钥交换主要是两个公式的编写,即:
      • 公钥计算公式
      • 密钥计算公式
    • 生成随机数作为私钥
    • 预置质数原根对

    相关文章

      网友评论

          本文标题:Android网络加密

          本文链接:https://www.haomeiwen.com/subject/mkaufhtx.html