API接口之对称加密、非对称加密(三)

目录

 

一、加密方式和区别

二、对称加密

2.1 DES加密

2.2 3DES加密

三、非对称加密

3.1 RSA加密

四、移动APP安全接口设计

4.1 非对称加密解密

4.2 对称加密解密


一、加密方式和区别

一般金融类的产品,涉及前端和后端交互的时候,都会都严格的数据安全保证。防止黑客攻击,信息篡改。

加密方式有很多,总的来说,分为2种:对称和非对称。我们先来看一下,这两种加密方式分别是什么?他们有什么区别?

对称加密:对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)

非对称加密:数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。因此安全性大大提高。

二、对称加密

所谓对称加密算法即:加密和解密使用相同密钥的算法。常见的有DES、3DES、AES、PBE等加密算法,这几种算法安全性依次是逐渐增强的。

API接口之对称加密、非对称加密(三)_第1张图片

常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES。对称加密算法使用起来简单快捷,密钥较短,且破译困难。

但是对称秘钥在使用过程中存在以下问题:

1、对称加密算法一般不能提供信息完整性的鉴别。它无法验证发送者和接受者的身份;

2、对称密钥的管理和分发工作是一件具有潜在危险的和烦琐的过程。如何防止秘钥泄露是一个难点。
 

2.1 DES加密

DES是一种对称加密算法,是一种非常简便的加密算法,但是密钥长度比较短。DES加密算法出自IBM的研究,后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法.简单的DES加密算法实现:
先引入jar包的依赖

    
      org.springframework.security
      spring-security-rsa
      1.0.8.RELEASE
    
public class DESUtil {
    private static final String KEY_ALGORITHM = "DES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//默认的加密算法

    /**
     * DES 加密操作
     * @param content 待加密内容
     * @param key 加密密钥
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String key) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return Base64.encodeBase64String(result);//通过Base64转码返回
        } catch (Exception ex) {
            Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * DES 解密操作
     * @param content
     * @param key
     * @return
     */
    public static String decrypt(String content, String key) {
        try {
            //实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
            //执行操作
            byte[] result = cipher.doFinal(Base64.decodeBase64(content));
            return new String(result, "utf-8");
        } catch (Exception ex) {
            Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String key) {
        //返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = null;
        try {
            kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            //DES 要求密钥长度为 56
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());
            kg.init(56, random);
            //生成一个密钥
            SecretKey secretKey = kg.generateKey();
            return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为DES专用密钥
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static void main(String[] args) {
        String content = "hello,您好";
        String key = "sde@5f98H*^hsff%dfs$r344&df8543*er";
        System.out.println("content:" + content);
        String s1 = DESUtil.encrypt(content, key);
        System.out.println("s1:" + s1);
        System.out.println("s2:"+ DESUtil.decrypt(s1, key));
    }

}

2.2 3DES加密

3DES是一种对称加密算法,在 DES 的基础上,使用三重数据加密算法,对数据进行加密,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法这样来说,破解的概率就小了很多。缺点由于使用了三重数据加密算法,可能会比较耗性能。简单的3DES加密算法实现:
 

public class TripDESUtil {

    private static final String KEY_ALGORITHM = "DESede";
    private static final String DEFAULT_CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";//默认的加密算法

    /**
     * DESede 加密操作
     * @param content 待加密内容
     * @param key 加密密钥
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String key) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return Base64.encodeBase64String(result);//通过Base64转码返回
        } catch (Exception ex) {
            Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * DESede 解密操作
     *
     * @param content
     * @param key
     * @return
     */
    public static String decrypt(String content, String key) {
        try {
            //实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
            //执行操作
            byte[] result = cipher.doFinal(Base64.decodeBase64(content));
            return new String(result, "utf-8");
        } catch (Exception ex) {
            Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * 生成加密秘钥
     * @return
     */
    private static SecretKeySpec getSecretKey(final String key) {
        //返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = null;
        try {
            kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            //DES 要求密钥长度为 56
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());
            kg.init(168, random);
            //生成一个密钥
            SecretKey secretKey = kg.generateKey();
            return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为DESede专用密钥
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static void main(String[] args) {
        String content = "hello,您好";
        String key = "sde@5f98H*^hsff%dfs$r344&df8543*er";
        System.out.println("content:" + content);
        String s1 = TripDESUtil.encrypt(content, key);
        System.out.println("s1:" + s1);
        System.out.println("s2:"+ TripDESUtil.decrypt(s1, key));
    }

}

三、非对称加密

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。一般公钥是公开的,私钥是自己保存。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。安全性相对对称加密来说更高,是一种高级加密方式。

3.1 RSA加密

RSA是一种非对称加密算法.RSA有两个密钥,一个是公开的,称为公开密钥;一个是私密的,称为私密密钥。公开密钥是对大众公开的,私密密钥是服务器私有的,两者不能互推得出。用公开密钥对数据进行加密,私密密钥可解密;私密密钥对数据加密,公开密钥可解密。速度较对称加密慢。简单的RSA加密算法实现:
 

public class RSAUtil {

    public static String publicKey; // 公钥
    public static String privateKey; // 私钥

    /**
     * 生成公钥和私钥
     */
    public static void generateKey() {
        // 1.初始化秘钥
        KeyPairGenerator keyPairGenerator;
        try {
            keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            SecureRandom sr = new SecureRandom(); // 随机数生成器
            keyPairGenerator.initialize(512, sr); // 设置512位长的秘钥
            KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 开始创建
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 进行转码
            publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded());
            // 进行转码
            privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * 私钥匙加密或解密
     *
     * @param content
     * @param privateKeyStr
     * @return
     */
    public static String encryptByprivateKey(String content, String privateKeyStr, int opmode) {
        // 私钥要用PKCS8进行处理
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr));
        KeyFactory keyFactory;
        PrivateKey privateKey;
        Cipher cipher;
        String text = null;
        try {
            keyFactory = KeyFactory.getInstance("RSA");
            // 还原Key对象
            privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            cipher = Cipher.getInstance("RSA");
            cipher.init(opmode, privateKey);
            //加密解密操作
            text = encryptTxt(opmode,cipher,content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return text;
    }

    public static String encryptTxt(int opmode, Cipher cipher, String content){
        byte[] result;
        String text = null;
        try{
            if (opmode == Cipher.ENCRYPT_MODE) { // 加密
                result = cipher.doFinal(content.getBytes());
                text = Base64.encodeBase64String(result);
            } else if (opmode == Cipher.DECRYPT_MODE) { // 解密
                result = cipher.doFinal(Base64.decodeBase64(content));
                text = new String(result, "UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return text;
    }

    /**
     * 公钥匙加密或解密
     *
     * @param content
     * @return
     */
    public static String encryptByPublicKey(String content, String publicKeyStr, int opmode) {
        // 公钥要用X509进行处理
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
        KeyFactory keyFactory;
        PublicKey publicKey;
        Cipher cipher;
        String text = null;
        try {
            keyFactory = KeyFactory.getInstance("RSA");
            // 还原Key对象
            publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            cipher = Cipher.getInstance("RSA");
            cipher.init(opmode, publicKey);
            //加密解密操作
            text = encryptTxt(opmode,cipher,content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return text;
    }


    public static void main(String[] args) {

        // 1. 生成(公钥和私钥)密钥对
        RSAUtil.generateKey();
        System.out.println("公钥:" + RSAUtil.publicKey);
        System.out.println("私钥:" + RSAUtil.privateKey);
        System.out.println("----------公钥加密私钥解密(推荐),非对称加密,公钥保存在客户端,私钥保存在服务端-------------");
        // 使用 公钥加密,私钥解密
        String textsr = "irish";
        String encryptByPublic = RSAUtil.encryptByPublicKey(textsr, RSAUtil.publicKey, Cipher.ENCRYPT_MODE);
        System.out.println("公钥加密:" + encryptByPublic);
        String text = RSAUtil.encryptByprivateKey(encryptByPublic, RSAUtil.privateKey, Cipher.DECRYPT_MODE);
        System.out.println("私钥解密:" + text);

        System.out.println("----------私钥加密公钥解密(不推荐),因为这样会把私钥暴露出来-------------");
        // 使用 私钥加密
        String body = "{\n" +
                "    \"loginName\":\"1+1\",\n" +
                "    \"password\":\"pass\"\n" +
                "}";
        String txtByPrivate = RSAUtil.encryptByprivateKey(body, RSAUtil.privateKey, Cipher.ENCRYPT_MODE);
        System.out.println("私钥加密:" + txtByPrivate);

        String txtByPublic = RSAUtil.encryptByPublicKey(txtByPrivate, RSAUtil.publicKey, Cipher.DECRYPT_MODE);
        System.out.println("公钥解密:" + txtByPublic);
    }
}

输出结果:

API接口之对称加密、非对称加密(三)_第2张图片

四、移动APP安全接口设计

4.1 非对称加密解密

非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密。简单的原理图,如下:

API接口之对称加密、非对称加密(三)_第3张图片

先生成秘钥对

        // 1. 生成(公钥和私钥)密钥对
        RSAUtil.generateKey();
        System.out.println("公钥:" + RSAUtil.publicKey);
        System.out.println("私钥:" + RSAUtil.privateKey);

客户端代码:

然后将公钥保存在客户端进行加密使用,私钥放在服务端进行解密使用

API接口之对称加密、非对称加密(三)_第4张图片

因为我是模拟客户端的请求,所以可以直接运行项目中的RSAUtil.java文件获得密钥对和加密的报文

API接口之对称加密、非对称加密(三)_第5张图片

服务端代码:

首先定义拦截器和需要拦截的请求,并且将私钥放到服务端(因为是demo,所以我就将私钥变量,直接放到拦截器了,正式开发需要分开定义)

API接口之对称加密、非对称加密(三)_第6张图片

服务端接收加密的请求,并通过私钥解密,将解密之后的明文,放入到业务方法

API接口之对称加密、非对称加密(三)_第7张图片

业务方法:

API接口之对称加密、非对称加密(三)_第8张图片

最终输出结果:

未解密的报文参数:{    "param":"ApIKo00FX5YmB/vRjTssCUpaug5sGudt1B2zoubIuBTrxhSXXL6oxMEy3j98M4R+VT/XRTNNsQQQ+mLmXHjqgWljHdpBY9OHdO23jQZW//17ozQgKY9ahsXXf1lBWvzZigglbTs7HaCHaIdDkieTKNVdzyWuVTFWZQVbx+BBc0d4XA2JbRPj18p3jtI8GIRKrITuxPHOhLGLrmEIrOL683w8rZHsE9iWp3CvDe25MnB+Zwx3DV39K06aqWGFC6sktqqdbUdzQmmUn8Yanz+MkYFPG5FiUV57tLcD+huh1caohflPRvQMImdqS5UGrREn7hZuPNTm4XFli/1TjXaFEZAl8tpy/ENhEq2vhwrGqY6zU137jKV1IB9taJUI2JuURi1fSUbkYmutIUak6voqwGkP9pyz3JETmKqxSScksBT4Jn6/PCFqwYBWpK52n2HkcB8RHk4+jzGeX8ZLxpuANWhFmF533GOToLMBKsKpSqLAwCPxyQLdehcf1y+iJisAKJQ/3PM2kQWZqhp90xe9w8qFLPsrDaL5qjuxvasy7NO7YcBkM5XbrUfa6z5A/PFuchm126UkS7ddNd5xy4InOSAyJK5PTSIlrFa7VhgxFFO1lO+JnnimsO4CESvUulzXoXXoAabqVmIIcp3pEyOb3wzSP77U3Uv7Oemj9MdjKr0="}
已解密的报文参数:{
    "base":{
        "uid":12,
        "name":"李四2"
    },
    "sex":"男"
}
===========================我是业务方法=========================
uid=12
name=李四2
性别是:男

项目代码地址:

https://github.com/loafer7423/signature

4.2 对称加密解密

它的原理是客户端和服务端公用一把秘钥,这把秘钥既可以用作加密,也可以用作解密。代码逻辑和上面的案例基本一致,只是加密解密的形式不一样。代码就不做了,逻辑如下:

API接口之对称加密、非对称加密(三)_第9张图片

 

你可能感兴趣的:(Java)