单车

单车第三天

2018-09-03  本文已影响9人  shenyoujian

转自http://coder520.com/
1、登录遇到的问题:

2、实操

 public static void main(String[] args) throws Exception {
        String key = "123456789abcdefg";
        String result = "神游建";
        //加密
        String enResult = encrypt(result, key);
        System.out.println(enResult);
        //解密
        String deResult = decrypt(enResult, key);
        System.out.println(deResult);
    }
image.png

base64util的作用,虽然在本机能够加密显示,但是什么==*等这些字符在网络传输的时候会出问题,所以需要base64util编码一下,改成可以传输的字符。

public static void main(String[] args) throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        System.out.println(Base64Util.encode(privateKey.getEncoded()));
        System.out.println(Base64Util.encode(publicKey.getEncoded()));
}

然后把私钥保存在文件里,安全其他开发人员就看不到,公钥就在类里定义好,私钥就通过读取文件流获取。


image.png
image.png

读取私钥方法

/**
     * 读取密钥字符串
     * @throws Exception
     */

    public static void convert() throws Exception {
        byte[] data = null;

        try {
            InputStream is = RSAUtil.class.getResourceAsStream("/enc_pri");
            int length = is.available();
            data = new byte[length];
            is.read(data);
        } catch (Exception e) {
        }

        String dataStr = new String(data);
        try {
            PRIVATE_KEY = dataStr;
        } catch (Exception e) {
        }

        if (PRIVATE_KEY == null) {
            throw new Exception("Fail to retrieve key");
        }
    }

接着私钥解密和公钥加密的方法,然后在main函数里测试

byte[] enR = encryptByPublicKey("ljs".getBytes("utf-8"),PUBLIC_KEY);
        System.out.println(enR.toString());
        byte[] deR = decryptByPrivateKey(enR);
        System.out.println(new String(deR, "utf-8"));

这里报空指针异常Exception in thread "main" java.lang.NullPointerException,原因是我们新加的私钥配置文件没加载,在pom里设置。注意加密算法不同,私钥也就不同,如果修改了需要重新生成。

                 <includes>
                    <include>*.yml</include>
                    <include>*.properties</include>
                    <include>*.xml</include>
                    <include>enc_pri</include>
                </includes>

最后需要指定编码不然解密后还是乱码。


image.png

最后整个加密解密流程测试

public static void main(String[] args) throws Exception {
        /**AES加密数据,客户端操作开始**/
        String key = "123456789abcdefg";            //约定好的key
        String result = "神游建";                    //传输的数据
        String enResult = encrypt(result, key);     //加密
        System.out.println(enResult);
        /**RSA加密AES的密钥,客户端操作结束**/
        byte[] enKey = RSAUtil.encryptByPublicKey(key.getBytes(), "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCEPB4Y7bd4ttV3phsm7VpR lmG0j19QUQWRG+MVCgw7f7ahvgwiXpwrqWP4hyZFxlFRUT4PlS11cKNut1Qm xjco1pYIxZUG6TfQj+a9rnUOGogdkyS76IpKi5/xal6MTmPqlfpE9SkBLvDc qLFX8FBo0+/ReoPrIPg3H4Saj99tOwIDAQAB");
        System.out.println(new String(enKey, "utf-8"));
        //需要再转码不然在http传输会出问题,因为上面输出乱码
        String baseKey = Base64Util.encode(enKey);

        /**服务端RSA解密AES的key**/
        byte[] de = Base64Util.decode(baseKey);
        byte[] deResultKey = RSAUtil.decryptByPrivateKey(de);
        System.out.println(new String(deResultKey, "utf-8"));
        String deResult = decrypt(enResult, key);       //服务端解密数据
        System.out.println(deResult);
    }
image.png

同样可以看到如果没base64转码会出现乱码,在http传输是会出问题的。

总结:
安卓端传输数据,先在安卓端使用AES对称加密进行数据加密,加密的key是存在安卓端上的,但是key不能明文传输,这样别人通过网络获取key和加密的数据同样可以解密,但是又不能对称加密传输,这样又得再用一个key,无限循环。。所以使用非对称加密key,在安卓端非对称加密key之后和对称加密的数据一起传输。服务端就可以使用非对称的私钥解密key,接着使用key解密数据。
这样还是不够安全,因为rsa的公钥是相同的,也就是说不同客户端的公钥都是相同的,如果黑客反编译的安卓app,这样就可以获取公钥,这样就不安全,我们可以服务端随机生成rsa公钥,然后与安卓端的标识绑定起来。防止反编译可以在安卓端使用代码混淆。这样就解决了相同公钥与反编译的问题,但是没有一个完美的系统。。同样上面也可以使用https。

上一篇 下一篇

猜你喜欢

热点阅读