zoukankan      html  css  js  c++  java
  • RSA加密

    RSA加密的原理:

    https://www.cnblogs.com/coolYuan/p/9168284.html

    其实知不知道RSA加密的原理都不太影响开发,无非是前端页面输入用户名密码后,在发送请求到后台去的时候,把用户名密码的明文字符串加密成密文传递到后台,这样别人截获请求参数的时候,截获到的只能是看不懂的密文,后台收到密文后,进行解密,解密后用明文做明文原本该做的逻辑判断和处理。

    简单说就是js加密,Java解密。

    js加密需要一个js的RSA加密库 jsencrypt.min.js

    java解密需要一个RSA加密解密的jar包 bcprov-jdk15-145.jar

    js代码:

            <!-- 用户名密码加密 -->
            <script type="text/javascript" src="/login/js/jsencrypt.min.js"></script>
            <!-- remote -->
            <script type="text/javascript" src="/resource/remoting/resource/remote.js"></script>
            <script type="text/javascript" src="/login/js/signInAction.js"></script>
            <h:outputScript library="seam" name="seam.rescript.js" />
            <script>
            var publicKey = "";
            var encrypt = new JSEncrypt();
            function getPublicKey() {
                Seam.Component.getInstance("signInAction").getKey(function(data){
                    console.log(data);
                    publicKey = data;
                    encrypt.setPublicKey(publicKey);
                    
                }, excHandler);
            }
            function encryptionUserName() {
                var username = $('.loguserName').val();
                username = encrypt.encrypt(username);
                Seam.Component.getInstance("signInAction").setUserName(username, function(){}, excHandler);
            }
            function encryptionUserPwd() {
                var password = $('.logpassword').val();
                password = encrypt.encrypt(password);
                Seam.Component.getInstance("signInAction").setUserPwd(password, function(){}, excHandler);
            }
            j(function(){
                getPublicKey();
            });
            </script>

     getPublicKey 获取公钥,encrypt.setPublicKey 这个是设置公钥, encrypt.encrypt 这个是加密方法, Seam.Component.getInstance 这个是平台框架的类似Ajax的方法,用于js请求后台。

    Java 加密解密工具类代码:

    package com.seam.mango.utils;
    
    import org.apache.commons.codec.binary.Base64;
    import javax.crypto.Cipher;
    import java.security.*;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.X509EncodedKeySpec;
    
    /**
     * 用到的jar包:bcprov-jdk15-145.jar*/
    public class RSAUtils {private static final KeyPair keyPair = initKey();
        
        /**
         * 计算公钥
         */
        private static KeyPair initKey() {
            try {
                Provider provider =new org.bouncycastle.jce.provider.BouncyCastleProvider();
                Security.addProvider(provider);
                SecureRandom random = new SecureRandom();
                KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
                generator.initialize(1024, random);
                return generator.generateKeyPair();
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }
        
        /**
         * 加密
         */
        public static String encrypt( String str, String publicKey ) throws Exception{
            //base64编码的公钥
            byte[] decoded = Base64.decodeBase64(publicKey.getBytes());
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] outStr = Base64.encodeBase64(cipher.doFinal(str.getBytes("UTF-8")));
            return new String(outStr);
        }
        
        /**
         * 获取公钥
         */
        public static String generateBase64PublicKey() {
            PublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
            return new String(Base64.encodeBase64(publicKey.getEncoded()));
        }
        
        /**
         * 解密
         */
        public static String decryptBase64(String string) {
            return new String(decrypt(Base64.decodeBase64(string.getBytes())));
        }
        private static byte[] decrypt(byte[] byteArray) {
            try {
                Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                Security.addProvider(provider);
                Cipher cipher = Cipher.getInstance(
                        "RSA/ECB/PKCS1Padding" /*"RSA/None/PKCS1Padding"*/ /*"RSA/None/NoPadding"*/ /*"RSA/ECB/NoPadding"*/ , provider);
                PrivateKey privateKey = keyPair.getPrivate();
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                byte[] plainText = cipher.doFinal(byteArray);
                return plainText;
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }
    
    }

    java原先的登录方法只需要接收加密的字符串调用解密的方法就可以了,原先的逻辑不用动:

        /**
         * 前端获取公钥
         */
        @WebRemote
        public String getKey(){
            return RSAUtils.generateBase64PublicKey();
        }
        /**
         * 接收前端用户名密文
         */
        @WebRemote
        public void setUserName(String username){
            credentials.setUsername(username);
            System.out.println("==================== username: " + username + " =====================");
        }
        /**
         * 接收前端密码密文
         */
        @WebRemote
        public void setUserPwd(String pwd){
            credentials.setPassword(pwd);
            System.out.println("==================== pwd: " + pwd + " =====================");
        }

    登录方法里加入解密过程:

    credentials.setUsername(RSAUtils.decryptBase64(credentials.getUsername()));
    credentials.setPassword(RSAUtils.decryptBase64(credentials.getPassword()));

    上面说的这些其实都不是难点,难的是环境的配置,因为没有人告诉你该怎么配环境,只能看代码跑起来的时候报什么错,根据报错内容去搜索解决方案,大致遇到的就是下面两个异常:

    1、unknown block type

    这个异常百度后,大致觉得是因为jdk在调用加密解密有关的jar包时,需要安全认证

    我不明白,Security.addProvider(provider); 这句话不起作用的吗?

    手动加认证的方式:

    修改 jdk1.8.0_60_x64jrelibsecurityjava.security

     添加一个provider

    security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider

     将jar包 bcprov-jdk15-145.jar 放入 jdk1.8.0_60_x64jrelibext 目录

    2、Cannot verify jar

    我对这个异常的大致理解是 jboss 运行时,对加密解密也需要安全认证

    需要修改jboss的配置文件,步骤如下:

    在 jboss-eap-6.2modulesorg 路径下添加 bouncycastle 文件夹,里面再添加 main 文件夹

    把jar包 bcprov-jdk15-145.jar 放入 jboss-eap-6.2modulesorgouncycastlemain 目录

    并再 jboss-eap-6.2modulesorgouncycastlemain 目录下添加 module.xml 文件,这个文件可以仿照 modules 文件夹里的其他 module.xml 文件,内容如下

    <?xml version="1.0" encoding="UTF-8"?>
    
    <module xmlns="urn:jboss:module:1.1" name="org.bouncycastle">
        <resources>
            <resource-root path="bcprov-jdk15-145.jar"/>
        </resources>
        <dependencies>
            <module name="javax.api" slot="main" export="true"/>
        </dependencies>
    </module>

    最后一步,找到 jboss-eap-6.2standaloneconfigurationstandalone.xml 配置文件, 并找到这一行:
    <subsystem xmlns="urn:jboss:domain:ee:1.1">

    添加下面的配置:

               <global-modules>
                   <module name="org.bouncycastle" slot="main"/>
               </global-modules>

    到此,这个看似小菜却又并不小菜的功能搞定!

  • 相关阅读:
    SpringBoot | Thymeleaf | 局部更新
    面试 | 冒泡排序优化
    JSP && Servlet | AXIS 0配置 入门
    155. 最小栈
    idea | 命名空间改过后重新导入项目方法
    Java | 基础归纳 | Map.Entry<String, String>
    08_Azkaban案例实践1_Command单一job示例
    07_Azkaban工作流调度器简介及其安装
    06_工作流调度器概述
    05_ Flume多级Agent之间串联案例
  • 原文地址:https://www.cnblogs.com/LcxSummer/p/12870559.html
Copyright © 2011-2022 走看看