关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java实现SSH模式加密原理及代码

    Java实现SSH模式加密原理及代码

    2016-01-07 00:00:00 出处:金丝燕网
    分享

    一、SSH加密原理

    SSH是先通过非对称加密告诉服务端一个对称加密口令,然后进行验证用户名和密码的时候,使用双方已经知道的加密口令进行加密和解密,见下图:

    这里写图片描述

    解释:SSH中为什么要使用非对称加密,又使用对称加密,到底有什么用处?到底安全不安全?既然后来又使用了对称加密,开始的时候为什么还要用非对称加密?反过来,既然用非对称加密,为什么又要使用对称加密呢?

    非对称加密,是为了将客户端产生的256位随机的口令传递到服务端,那么在传递的过程中,使用公钥进行了加密,这样,这个256位的加密口令就很难被网络上进行破解。 对称加密,因为频繁的使用非对称加密是非常浪费性能的,那么SSH就是用了256位长度的口令作为接下来传递用户名密码时的加密口令,其破解的难度,想必大家都知道了,每一位上都有0-9种变化。 这样安全吗,我觉得还是很不错的,具体使用起来也易于让人理解。

    二、我的SSH加密原理

    ①、使用场景

    我所开发的项目是大宗期货交易,主要服务于交易所,这也就产生一个需求就是,我们需要控制交易所使用我们软件的周期。也就是说我们的项目留有一个后门,用来控制项目的周期,假如交易所使用软件的周期到了,那么如果他不续费,而项目的代码部署在人家的服务器上,此时我们就很难控制了,但是有了这个后门,到期后会自动停止软件,这样就不担心交易所不给我们钱了。

    ②、使用方式

    我们给交易的项目代码中包含一个后门,该后门通过webservice client发送一个请求到web service。 web service接收到请求后,回给client需要的信息。

    在以上这个过程当中,就会产生一个SSH加密的请求方式,请允许我用一个拙劣的图表示一下。
    这里写图片描述

    三、我的SSH具体实现

    既然要用到webservice,那么就需要建立web service服务,还有web service client。关于这方面,我暂时不想说太多,方式有很多,我在这就不误导大家了。我是通过eclipse搞定的,可参照webservice之间通信?。

    接下来,我将介绍代码,但是考虑到篇幅问题,一些不必要的代码我就不贴出来了,关键在于讲解清楚这个原理。

    ①、service

    ExchangeService.java

    public byte[] request(String param, String resultType) {
        logger.info("请求参数:" + param);
    
        // 返回对象
        KeyResult keyResult = new KeyResult();
    
        try {
            // 先获取公钥
            if (resultType.equals(PUBLIC_KEY_RESULT_TYPE)) {
    
                Map<String, Object> keyMap = RSACoder.initKey();
                // 产生公钥和私钥
                privateKey = RSACoder.getPrivateKey(keyMap);
    
                keyResult.setKey(RSACoder.getPublicKey(keyMap));
    
                logger.info("公钥字符串:" + keyResult.getKey());
                logger.info("私钥字符串:" + privateKey);
    
            } else if (resultType.equals(ECHOSTR_RESULT_TYPE)) {
    
                // 设置客户端的口令信息
                byte[] paramByte = new BASE64Decoder().decodeBuffer(param);
                echoStr = new String(RSACoder.decryptByPrivateKey(paramByte, privateKey));
    
            } else {
                // 通过数据库获取交易所对应的权限信息.
                // 先将请求转换为byte数组,然后再进行解密,最后转换为字符串
                ExchangeInfo info = ExchangeInfo.dao.getInfoByName(new String(CryptUtil.decrypt(
                        new BASE64Decoder().decodeBuffer(param), echoStr.getBytes())));
    
                String result = "";
    
                // 获取系统启用权限
                if (resultType.equals(PRIVILEGE_RESULT_TYPE)) {
                    // 先判断使用权限
    
                    // 在判断使用日期
                    // 当前登录用登录时获取登录的当前日期和开始日期进行比较,然后计算还可以使用的日期
                    long time = (new Date().getTime() / 1000) - string2DateInt(openday);
                    // 换算成天数
                    int day = (int) (time / (60 * 60 * 24));
                    // 还可以使用的天数
                    if (usedays - day > 0) {
                        // 可以使用
                        result = "1";
                    } else {
                        // 无法使用
                        result = "0";
                    }
    
                }
    
                keyResult.setResult(CryptUtil.encrypt(result.getBytes(), echoStr.getBytes()));
            }
    
            return JsonUtil.objectToByte(keyResult);
        } catch (Exception e) {
            logger.error("webservice出错了!!!!");
            logger.error(e.getMessage(), e);
        }
    
        return null;
    }

    再赘述一下:

    第一个判断语句中的内容就是生成公钥和私钥,并且返回公钥。 第二个判断语句中的内容就是保存client发送的随机字符串,这一步非常关键,随机字符串首先通过公钥进行了加密,这大大加强了加密的深度。 第三个判断语句中的内容就是将client的权限通过随机字符串进行加密。

    ②、client

    ExchangeUtil.java

    public static boolean canRunForExchange(String resultType) {
        int i = 1;
        boolean result = false;
    
        while (true) {
            try {
                // webservice调用类
                ExchangeServiceProxy proxy = new ExchangeServiceProxy();
                BASE64Encoder encoder = new BASE64Encoder();
    
                // step1.获取service产生的公钥
                KeyResult keyResult = JsonUtil.byteToObject(proxy.request(null, PUBLIC_KEY_RESULT_TYPE),
                        KeyResult.class);
    
                // step2.产生随机字符串,发送到webserivce
                String echoStr = StrUtil.getEchoStrByLength(10);
                byte[] echoByteParam = RSACoder.encryptByPublicKey(echoStr.getBytes(), keyResult.getKey());
                proxy.request(encoder.encode(echoByteParam), ECHOSTR_RESULT_TYPE);
    
                // step3.加密客户端请求信息,然后发送到webservice
                // 先加密为byte数组,然后转换成字符串
                byte[] results = proxy.request(
                        encoder.encode(CryptUtil.encrypt(Constants.client_type.getBytes(), echoStr.getBytes())),
                        resultType);
                keyResult = JsonUtil.byteToObject(results, KeyResult.class);
    
                // step4.通过口令解密服务端返回消息
                String response = new String(CryptUtil.decrypt(keyResult.getResult(), echoStr.getBytes()));
                if (response.equals("1")) {
                    result = true;
                }
                break;
            } catch (Exception e) {
                logger.debug("第" + i + "次加载webservice失败");
                i++;
                logger.error(e.getMessage(), e);
    
                if (i >= 10) {
                    break;
                }
            }
        }
    
        return result;
    }

    稍作解释:

    通过循环主要为了防止网络断开时服务不停的发送请求,最多10次就够了。 主要有四步操作,注释中我想解释的还可以。

    ③、共享加密解密公共类

    CryptUtil.java

    package com.honzh.socket.util;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    
    public class CryptUtil {
        /** 
        * @Title: encrypt 
        * @Description: 加密
        * @param data
        * @param key
        * @return
        * @throws Exception
        */
        public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
            key = get8(key);
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(key);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            return cipher.doFinal(data);
        }
    
        /** 
        * @Title: decrypt 
        * @Description: 解密
        * @param data
        * @param key
        * @return
        * @throws Exception
        */
        public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
            key = get8(key);
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(key);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return cipher.doFinal(data);
        }
    
        private static byte[] get8(byte[] key) {
            byte[] key1 = new byte[8];
            for (int i = 0; i < 8; i++) {
                key1[i] = key[i];
            }
            return key1;
        }
    
        public static String toHexString(byte[] data) {
            String s = "";
            for (int i = 0; i < data.length; i++) {
                s += Integer.toHexString(data[i] & 0xFF)+"-";
            }
            return s;
        }
    
    }

    一般情况下,SHA和MD5两种加密就够我们使用了!

    至于其他的辅助类我就不多介绍了,网上有很多资源,也许你的项目也有类似的实现方式。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。