美文网首页
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